[clang] 4497ec2 - [clang][CGRecordLayout] Remove dependency on isZeroSize (#96422)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 15 20:59:55 PDT 2024
Author: Michael Buch
Date: 2024-07-16T04:59:51+01:00
New Revision: 4497ec293a6e745be817dc88027169bd5e4f7246
URL: https://github.com/llvm/llvm-project/commit/4497ec293a6e745be817dc88027169bd5e4f7246
DIFF: https://github.com/llvm/llvm-project/commit/4497ec293a6e745be817dc88027169bd5e4f7246.diff
LOG: [clang][CGRecordLayout] Remove dependency on isZeroSize (#96422)
This is a follow-up from the conversation starting at
https://github.com/llvm/llvm-project/pull/93809#issuecomment-2173729801
The root problem that motivated the change are external AST sources that
compute `ASTRecordLayout`s themselves instead of letting Clang compute
them from the AST. One such example is LLDB using DWARF to get the
definitive offsets and sizes of C++ structures. Such layouts should be
considered correct (modulo buggy DWARF), but various assertions and
lowering logic around the `CGRecordLayoutBuilder` relies on the AST
having `[[no_unique_address]]` attached to them. This is a
layout-altering attribute which is not encoded in DWARF. This causes us
LLDB to trip over the various LLVM<->Clang layout consistency checks.
There has been precedent for avoiding such layout-altering attributes
from affecting lowering with externally-provided layouts (e.g., packed
structs).
This patch proposes to replace the `isZeroSize` checks in
`CGRecordLayoutBuilder` (which roughly means "empty field with
[[no_unique_address]]") with checks for
`CodeGen::isEmptyField`/`CodeGen::isEmptyRecord`.
**Details**
The main strategy here was to change the `isZeroSize` check in
`CGRecordLowering::accumulateFields` and
`CGRecordLowering::accumulateBases` to use the `isEmptyXXX` APIs
instead, preventing empty fields from being added to the `Members` and
`Bases` structures. The rest of the changes fall out from here, to
prevent lookups into these structures (for field numbers or base
indices) from failing.
Added `isEmptyRecordForLayout` and `isEmptyFieldForLayout` (open to
better naming suggestions). The main difference to the existing
`isEmptyRecord`/`isEmptyField` APIs, is that the `isEmptyXXXForLayout`
counterparts don't have special treatment for `unnamed bitfields`/arrays
and also treat fields of empty types as if they had
`[[no_unique_address]]` (i.e., just like the `AsIfNoUniqueAddr` in
`isEmptyField` does).
Added:
clang/test/CodeGenCXX/zero-init-empty-virtual.cpp
Modified:
clang/lib/CodeGen/ABIInfoImpl.cpp
clang/lib/CodeGen/ABIInfoImpl.h
clang/lib/CodeGen/CGClass.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGExprConstant.cpp
clang/lib/CodeGen/CGOpenMPRuntime.cpp
clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
clang/lib/CodeGen/CodeGenTBAA.cpp
clang/test/CodeGen/2009-06-14-anonymous-union-init.c
clang/test/CodeGen/X86/x86_64-vaarg.c
clang/test/CodeGen/paren-list-agg-init.cpp
clang/test/CodeGen/voidptr-vaarg.c
clang/test/CodeGenCXX/2011-12-19-init-list-ctor.cpp
clang/test/CodeGenCXX/bitfield-access-empty.cpp
clang/test/CodeGenCXX/class-layout.cpp
clang/test/CodeGenCXX/compound-literals.cpp
clang/test/CodeGenCXX/exceptions.cpp
clang/test/CodeGenCXX/lambda-deterministic-captures.cpp
clang/test/CodeGenCXX/partial-destruction.cpp
clang/test/CodeGenCXX/pod-member-memcpys.cpp
clang/test/CodeGenCXX/pr18962.cpp
clang/test/CodeGenCXX/references.cpp
clang/test/CodeGenCXX/temporaries.cpp
clang/test/CodeGenObjCXX/lambda-to-block.mm
clang/test/OpenMP/irbuilder_for_iterator.cpp
clang/test/OpenMP/irbuilder_for_rangefor.cpp
clang/test/OpenMP/task_member_call_codegen.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp
index e9a26abb77837..35e8f79ba1bac 100644
--- a/clang/lib/CodeGen/ABIInfoImpl.cpp
+++ b/clang/lib/CodeGen/ABIInfoImpl.cpp
@@ -310,6 +310,41 @@ bool CodeGen::isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
return true;
}
+bool CodeGen::isEmptyFieldForLayout(const ASTContext &Context,
+ const FieldDecl *FD) {
+ if (FD->isZeroLengthBitField(Context))
+ return true;
+
+ if (FD->isUnnamedBitField())
+ return false;
+
+ return isEmptyRecordForLayout(Context, FD->getType());
+}
+
+bool CodeGen::isEmptyRecordForLayout(const ASTContext &Context, QualType T) {
+ const RecordType *RT = T->getAs<RecordType>();
+ if (!RT)
+ return false;
+
+ const RecordDecl *RD = RT->getDecl();
+
+ // If this is a C++ record, check the bases first.
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (CXXRD->isDynamicClass())
+ return false;
+
+ for (const auto &I : CXXRD->bases())
+ if (!isEmptyRecordForLayout(Context, I.getType()))
+ return false;
+ }
+
+ for (const auto *I : RD->fields())
+ if (!isEmptyFieldForLayout(Context, I))
+ return false;
+
+ return true;
+}
+
const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {
const RecordType *RT = T->getAs<RecordType>();
if (!RT)
diff --git a/clang/lib/CodeGen/ABIInfoImpl.h b/clang/lib/CodeGen/ABIInfoImpl.h
index 92986fb431646..2a3ef6b8a6c96 100644
--- a/clang/lib/CodeGen/ABIInfoImpl.h
+++ b/clang/lib/CodeGen/ABIInfoImpl.h
@@ -137,6 +137,16 @@ bool isEmptyField(ASTContext &Context, const FieldDecl *FD, bool AllowArrays,
bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays,
bool AsIfNoUniqueAddr = false);
+/// isEmptyFieldForLayout - Return true iff the field is "empty", that is,
+/// either a zero-width bit-field or an \ref isEmptyRecordForLayout.
+bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD);
+
+/// isEmptyRecordForLayout - Return true iff a structure contains only empty
+/// base classes (per \ref isEmptyRecordForLayout) and fields (per
+/// \ref isEmptyFieldForLayout). Note, C++ record fields are considered empty
+/// if the [[no_unique_address]] attribute would have made them empty.
+bool isEmptyRecordForLayout(const ASTContext &Context, QualType T);
+
/// isSingleElementStruct - Determine if a structure is a "single
/// element struct", i.e. it has exactly one non-empty field or
/// exactly one field which is itself a single element
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 0a595bb998d26..667e260f2228d 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ABIInfoImpl.h"
#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
@@ -933,7 +934,7 @@ namespace {
}
void addMemcpyableField(FieldDecl *F) {
- if (F->isZeroSize(CGF.getContext()))
+ if (isEmptyFieldForLayout(CGF.getContext(), F))
return;
if (!FirstField)
addInitialField(F);
@@ -1815,7 +1816,7 @@ namespace {
const CXXDestructorDecl *DD)
: Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
void PushCleanupForField(const FieldDecl *Field) {
- if (Field->isZeroSize(Context))
+ if (isEmptyFieldForLayout(Context, Field))
return;
unsigned FieldIndex = Field->getFieldIndex();
if (FieldHasTrivialDestructorBody(Context, Field)) {
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index af1e1a25d1d8b..5fdd3cc490e59 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ABIInfoImpl.h"
#include "CGCUDARuntime.h"
#include "CGCXXABI.h"
#include "CGCall.h"
@@ -4757,7 +4758,7 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
/// The resulting address doesn't necessarily have the right type.
static Address emitAddrOfFieldStorage(CodeGenFunction &CGF, Address base,
const FieldDecl *field) {
- if (field->isZeroSize(CGF.getContext()))
+ if (isEmptyFieldForLayout(CGF.getContext(), field))
return emitAddrOfZeroSizeField(CGF, base, field);
const RecordDecl *rec = field->getParent();
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index dba98d0985fb1..7c65fccb60855 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
@@ -736,7 +737,7 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
// Zero-sized fields are not emitted, but their initializers may still
// prevent emission of this struct as a constant.
- if (Field->isZeroSize(CGM.getContext())) {
+ if (isEmptyFieldForLayout(CGM.getContext(), Field)) {
if (Init->HasSideEffects(CGM.getContext()))
return false;
continue;
@@ -858,7 +859,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
continue;
// Don't emit anonymous bitfields or zero-sized fields.
- if (Field->isUnnamedBitField() || Field->isZeroSize(CGM.getContext()))
+ if (Field->isUnnamedBitField() ||
+ isEmptyFieldForLayout(CGM.getContext(), *Field))
continue;
// Emit the value of the initializer.
@@ -2526,8 +2528,10 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
// Ignore empty bases.
- if (base->isEmpty() ||
- CGM.getContext().getASTRecordLayout(base).getNonVirtualSize()
+ if (isEmptyRecordForLayout(CGM.getContext(), I.getType()) ||
+ CGM.getContext()
+ .getASTRecordLayout(base)
+ .getNonVirtualSize()
.isZero())
continue;
@@ -2541,7 +2545,8 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
for (const auto *Field : record->fields()) {
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
// will fill in later.)
- if (!Field->isBitField() && !Field->isZeroSize(CGM.getContext())) {
+ if (!Field->isBitField() &&
+ !isEmptyFieldForLayout(CGM.getContext(), Field)) {
unsigned fieldIndex = layout.getLLVMFieldNo(Field);
elements[fieldIndex] = CGM.EmitNullConstant(Field->getType());
}
@@ -2563,7 +2568,7 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
// Ignore empty bases.
- if (base->isEmpty())
+ if (isEmptyRecordForLayout(CGM.getContext(), I.getType()))
continue;
unsigned fieldIndex = layout.getVirtualBaseIndex(base);
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 8bc202f402aa3..652fb700fc6af 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "CGOpenMPRuntime.h"
+#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGRecordLayout.h"
@@ -7729,12 +7730,15 @@ class MappableExprsHandler {
for (const auto &I : RD->bases()) {
if (I.isVirtual())
continue;
- const auto *Base = I.getType()->getAsCXXRecordDecl();
+
+ QualType BaseTy = I.getType();
+ const auto *Base = BaseTy->getAsCXXRecordDecl();
// Ignore empty bases.
- if (Base->isEmpty() || CGF.getContext()
- .getASTRecordLayout(Base)
- .getNonVirtualSize()
- .isZero())
+ if (isEmptyRecordForLayout(CGF.getContext(), BaseTy) ||
+ CGF.getContext()
+ .getASTRecordLayout(Base)
+ .getNonVirtualSize()
+ .isZero())
continue;
unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
@@ -7742,10 +7746,12 @@ class MappableExprsHandler {
}
// Fill in virtual bases.
for (const auto &I : RD->vbases()) {
- const auto *Base = I.getType()->getAsCXXRecordDecl();
+ QualType BaseTy = I.getType();
// Ignore empty bases.
- if (Base->isEmpty())
+ if (isEmptyRecordForLayout(CGF.getContext(), BaseTy))
continue;
+
+ const auto *Base = BaseTy->getAsCXXRecordDecl();
unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
if (RecordLayout[FieldIndex])
continue;
@@ -7756,7 +7762,8 @@ class MappableExprsHandler {
for (const auto *Field : RD->fields()) {
// Fill in non-bitfields. (Bitfields always use a zero pattern, which we
// will fill in later.)
- if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
+ if (!Field->isBitField() &&
+ !isEmptyFieldForLayout(CGF.getContext(), Field)) {
unsigned FieldIndex = RL.getLLVMFieldNo(Field);
RecordLayout[FieldIndex] = Field;
}
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index 875745d4a48e4..ea44e6f21f3c8 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -10,8 +10,9 @@
//
//===----------------------------------------------------------------------===//
-#include "CGRecordLayout.h"
+#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
+#include "CGRecordLayout.h"
#include "CodeGenTypes.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
@@ -384,7 +385,7 @@ void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) {
Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd);
assert((Field == FieldEnd || !Field->isBitField()) &&
"Failed to accumulate all the bitfields");
- } else if (Field->isZeroSize(Context)) {
+ } else if (isEmptyFieldForLayout(Context, *Field)) {
// Empty fields have no storage.
++Field;
} else {
@@ -633,7 +634,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
// non-reusable tail padding.
CharUnits LimitOffset;
for (auto Probe = Field; Probe != FieldEnd; ++Probe)
- if (!Probe->isZeroSize(Context)) {
+ if (!isEmptyFieldForLayout(Context, *Probe)) {
// A member with storage sets the limit.
assert((getFieldBitOffset(*Probe) % CharBits) == 0 &&
"Next storage is not byte-aligned");
@@ -731,7 +732,7 @@ void CGRecordLowering::accumulateBases() {
// Bases can be zero-sized even if not technically empty if they
// contain only a trailing array member.
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
- if (!BaseDecl->isEmpty() &&
+ if (!isEmptyRecordForLayout(Context, Base.getType()) &&
!Context.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero())
Members.push_back(MemberInfo(Layout.getBaseClassOffset(BaseDecl),
MemberInfo::Base, getStorageType(BaseDecl), BaseDecl));
@@ -879,7 +880,7 @@ CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const {
if (!isNonVirtualBaseType && isOverlappingVBaseABI())
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
- if (BaseDecl->isEmpty())
+ if (isEmptyRecordForLayout(Context, Base.getType()))
continue;
// If the vbase is a primary virtual base of some base, then it doesn't
// get its own storage location but instead lives inside of that base.
@@ -895,7 +896,7 @@ CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const {
void CGRecordLowering::accumulateVBases() {
for (const auto &Base : RD->vbases()) {
const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
- if (BaseDecl->isEmpty())
+ if (isEmptyRecordForLayout(Context, Base.getType()))
continue;
CharUnits Offset = Layout.getVBaseClassOffset(BaseDecl);
// If the vbase is a primary virtual base of some base, then it doesn't
@@ -1161,7 +1162,7 @@ CodeGenTypes::ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty) {
const FieldDecl *FD = *it;
// Ignore zero-sized fields.
- if (FD->isZeroSize(getContext()))
+ if (isEmptyFieldForLayout(getContext(), FD))
continue;
// For non-bit-fields, just check that the LLVM struct offset matches the
diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index 284421f494711..b889d1bfe003f 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include "CodeGenTBAA.h"
+#include "ABIInfoImpl.h"
#include "CGRecordLayout.h"
#include "CodeGenTypes.h"
#include "clang/AST/ASTContext.h"
@@ -309,7 +310,7 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
unsigned idx = 0;
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
i != e; ++i, ++idx) {
- if ((*i)->isZeroSize(Context))
+ if (isEmptyFieldForLayout(Context, *i))
continue;
uint64_t Offset =
diff --git a/clang/test/CodeGen/2009-06-14-anonymous-union-init.c b/clang/test/CodeGen/2009-06-14-anonymous-union-init.c
index 8ccd7bc4ec338..13f6357f7966d 100644
--- a/clang/test/CodeGen/2009-06-14-anonymous-union-init.c
+++ b/clang/test/CodeGen/2009-06-14-anonymous-union-init.c
@@ -1,7 +1,19 @@
-// RUN: %clang_cc1 -emit-llvm < %s | grep "zeroinitializer, i16 16877"
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefixes=CHECK,EMPTY
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s --check-prefixes=CHECK,EMPTY-MSVC
// PR4390
struct sysfs_dirent {
- union { struct sysfs_elem_dir {} s_dir; };
+ union { struct sysfs_elem_dir { int x; } s_dir; };
unsigned short s_mode;
};
struct sysfs_dirent sysfs_root = { {}, 16877 };
+
+// CHECK: @sysfs_root = {{.*}}global %struct.sysfs_dirent { %union.anon zeroinitializer, i16 16877 }
+
+struct Foo {
+ union { struct empty {} x; };
+ unsigned short s_mode;
+};
+struct Foo foo = { {}, 16877 };
+
+// EMPTY: @foo = {{.*}}global %struct.Foo { i16 16877 }
+// EMPTY-MSVC: @foo = {{.*}}global %struct.Foo { [4 x i8] undef, i16 16877 }
diff --git a/clang/test/CodeGen/X86/x86_64-vaarg.c b/clang/test/CodeGen/X86/x86_64-vaarg.c
index d6b885d9fb18c..7d5102f93ca6f 100644
--- a/clang/test/CodeGen/X86/x86_64-vaarg.c
+++ b/clang/test/CodeGen/X86/x86_64-vaarg.c
@@ -56,7 +56,8 @@ typedef struct {
// CHECK: vaarg.end:
// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP1]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ]
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 8, i1 false)
-// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[RETVAL]], align 8
+// CHECK-NEXT: [[COERCE:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[COERCE]], align 8
// CHECK-NEXT: ret double [[TMP3]]
//
s1 f(int z, ...) {
diff --git a/clang/test/CodeGen/paren-list-agg-init.cpp b/clang/test/CodeGen/paren-list-agg-init.cpp
index 88b1834d42d87..16cfe772a4ae5 100644
--- a/clang/test/CodeGen/paren-list-agg-init.cpp
+++ b/clang/test/CodeGen/paren-list-agg-init.cpp
@@ -48,14 +48,13 @@ struct E {
~E() {};
};
-// CHECK-DAG: [[STRUCT_F:%.*]] = type { i8 }
struct F {
F (int i = 1);
F (const F &f) = delete;
F (F &&f) = default;
};
-// CHECK-DAG: [[STRUCT_G:%.*]] = type <{ i32, [[STRUCT_F]], [3 x i8] }>
+// CHECK-DAG: [[STRUCT_G:%.*]] = type <{ i32, [4 x i8] }>
struct G {
int a;
F f;
@@ -78,12 +77,12 @@ namespace gh61145 {
~Vec();
};
- // CHECK-DAG: [[STRUCT_S1:%.*]] = type { [[STRUCT_VEC]] }
+ // CHECK-DAG: [[STRUCT_S1:%.*]] = type { i8 }
struct S1 {
Vec v;
};
- // CHECK-DAG: [[STRUCT_S2:%.*]] = type { [[STRUCT_VEC]], i8 }
+ // CHECK-DAG: [[STRUCT_S2:%.*]] = type { i8, i8 }
struct S2 {
Vec v;
char c;
@@ -377,7 +376,7 @@ void foo18() {
// CHECK-NEXT: [[G:%.*g.*]] = alloca [[STRUCT_G]], align 4
// CHECK-NEXT: [[A:%.*a.*]] = getelementptr inbounds [[STRUCT_G]], ptr [[G]], i32 0, i32 0
// CHECK-NEXT: store i32 2, ptr [[A]], align 4
-// CHECK-NEXT: [[F:%.*f.*]] = getelementptr inbounds [[STRUCT_G]], ptr [[G]], i32 0, i32 1
+// CHECK-NEXT: [[F:%.*]] = getelementptr inbounds i8, ptr [[G]], i64 4
// CHECk-NEXT: call void @{{.*F.*}}(ptr noundef nonnull align 1 dereferenceable(1)) [[F]], ie32 noundef 1)
// CHECK: ret void
void foo19() {
@@ -392,9 +391,8 @@ namespace gh61145 {
// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S1]], align 1
// a.k.a. Vec::Vec()
// CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
- // CHECK-NEXT: [[V1:%.*v1.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// a.k.a. Vec::Vec(Vec&&)
- // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[V1]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
+ // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// a.k.a. S1::~S1()
// CHECK-NEXT: call void @_ZN7gh611452S1D1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]])
// a.k.a.Vec::~Vec()
@@ -413,9 +411,8 @@ namespace gh61145 {
// CHECK-NEXT: [[AGG_TMP_ENSURED:%.*agg.tmp.ensured.*]] = alloca [[STRUCT_S2]], align 1
// a.k.a. Vec::Vec()
// CHECK-NEXT: call void @_ZN7gh611453VecC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[V]])
- // CHECK-NEXT: [[V1:%.*v1.*]] = getelementptr inbounds [[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// a.k.a. Vec::Vec(Vec&&)
- // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[V1]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
+ // CHECK-NEXT: call void @_ZN7gh611453VecC1EOS0_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]], ptr noundef nonnull align 1 dereferenceable(1) [[V]])
// CHECK-NEXT: [[C:%.*c.*]] = getelementptr inbounds [[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32
// CHECK-NEXT: store i8 0, ptr [[C]], align 1
// a.k.a. S2::~S2()
diff --git a/clang/test/CodeGen/voidptr-vaarg.c b/clang/test/CodeGen/voidptr-vaarg.c
index d023ddf0fb5d2..4f008fd85115a 100644
--- a/clang/test/CodeGen/voidptr-vaarg.c
+++ b/clang/test/CodeGen/voidptr-vaarg.c
@@ -245,7 +245,8 @@ typedef struct {
// CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4
// CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[LIST_ADDR]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[RETVAL]], ptr align 4 [[ARGP_CUR]], i32 4, i1 false)
-// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds [[STRUCT_EMPTY_INT_T]], ptr [[RETVAL]], i32 0, i32 0
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[COERCE_DIVE]], align 4
// CHECK-NEXT: ret i32 [[TMP0]]
//
empty_int_t empty_int(__builtin_va_list list) {
diff --git a/clang/test/CodeGenCXX/2011-12-19-init-list-ctor.cpp b/clang/test/CodeGenCXX/2011-12-19-init-list-ctor.cpp
index 14557829268ef..3efb8c449c8fa 100644
--- a/clang/test/CodeGenCXX/2011-12-19-init-list-ctor.cpp
+++ b/clang/test/CodeGenCXX/2011-12-19-init-list-ctor.cpp
@@ -19,8 +19,8 @@ struct S {
};
// CHECK: store i32 0, ptr @arr
-// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr @arr, i32 0, i32 1), ptr noundef @.str)
+// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (i8, ptr @arr, i64 4), ptr noundef @.str)
// CHECK: store i32 1, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 1)
-// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 1), i32 0, i32 1), ptr noundef @.str.1)
+// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (i8, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 1), i64 4), ptr noundef @.str.1)
// CHECK: store i32 2, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 2)
-// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (%struct.S, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 2), i32 0, i32 1), ptr noundef @.str.2)
+// CHECK: call void @_ZN1AC1EPKc(ptr {{[^,]*}} getelementptr inbounds (i8, ptr getelementptr inbounds (%struct.S, ptr @arr, i64 2), i64 4), ptr noundef @.str.2)
diff --git a/clang/test/CodeGenCXX/bitfield-access-empty.cpp b/clang/test/CodeGenCXX/bitfield-access-empty.cpp
index 96047ce472997..460fe6eef4b90 100644
--- a/clang/test/CodeGenCXX/bitfield-access-empty.cpp
+++ b/clang/test/CodeGenCXX/bitfield-access-empty.cpp
@@ -83,8 +83,8 @@ struct P3 {
unsigned b : 16;
} p3;
// CHECK-LABEL: LLVMType:%struct.P3 =
-// LAYOUT-SAME: type { i16, %struct.Empty, i16, [2 x i8] }
-// LAYOUT-DWN32-SAME: type <{ i16, %struct.Empty, i16 }>
+// LAYOUT-SAME: type { i16, [2 x i8], i16, [2 x i8] }
+// LAYOUT-DWN32-SAME: type <{ i16, i8, i16 }>
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P3 =
// CHECK: BitFields:[
// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
@@ -137,13 +137,13 @@ struct P7 {
unsigned c;
} p7;
// CHECK-LABEL: LLVMType:%struct.P7 =
-// LAYOUT-SAME: type { i16, i8, %struct.Empty, i32 }
-// LAYOUT-DWN32-SAME: type { i16, i8, %struct.Empty, i32 }
+// LAYOUT-SAME: type { i32, i32 }
+// LAYOUT-DWN32-SAME: type { i32, i32 }
// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P7 =
// CHECK: BitFields:[
-// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
-// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2
+// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:32 StorageOffset:0
+// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:32 StorageOffset:0
-// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0
-// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2
+// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:32 StorageOffset:0
+// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:32 StorageOffset:0
// CHECK-NEXT: ]>
diff --git a/clang/test/CodeGenCXX/class-layout.cpp b/clang/test/CodeGenCXX/class-layout.cpp
index 84b0f887876ac..90617d25b254e 100644
--- a/clang/test/CodeGenCXX/class-layout.cpp
+++ b/clang/test/CodeGenCXX/class-layout.cpp
@@ -83,7 +83,7 @@ namespace Test6 {
namespace Test7 {
#pragma pack (1)
class A {};
- // CHECK: %"class.Test7::B" = type <{ ptr, %"class.Test7::A" }>
+ // CHECK: %"class.Test7::B" = type <{ ptr, i8 }>
class B {
virtual ~B();
A a;
diff --git a/clang/test/CodeGenCXX/compound-literals.cpp b/clang/test/CodeGenCXX/compound-literals.cpp
index fcec2d19e2def..1b4a1d4445123 100644
--- a/clang/test/CodeGenCXX/compound-literals.cpp
+++ b/clang/test/CodeGenCXX/compound-literals.cpp
@@ -20,7 +20,7 @@ int f() {
// CHECK: [[LVALUE:%[a-z0-9.]+]] = alloca
// CHECK-NEXT: [[I:%[a-z0-9]+]] = getelementptr inbounds {{.*}}, ptr [[LVALUE]], i32 0, i32 0
// CHECK-NEXT: store i32 17, ptr [[I]]
- // CHECK-NEXT: [[X:%[a-z0-9]+]] = getelementptr inbounds {{.*}} [[LVALUE]], i32 0, i32 1
+ // CHECK-NEXT: [[X:%[a-z0-9]+]] = getelementptr inbounds {{.*}} [[LVALUE]], i32 4
// CHECK-NEXT: call noundef ptr @_ZN1XC1EPKc({{.*}}[[X]]
// CHECK-NEXT: [[I:%[a-z0-9]+]] = getelementptr inbounds {{.*}} [[LVALUE]], i32 0, i32 0
// CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = load i32, ptr
diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp
index e8179f9828fb6..1f4d2f061a43d 100644
--- a/clang/test/CodeGenCXX/exceptions.cpp
+++ b/clang/test/CodeGenCXX/exceptions.cpp
@@ -513,8 +513,7 @@ namespace test11 {
// CHECK-LABEL: define{{.*}} void @_ZN6test111CC2Ev(
// CHECK: [[THIS:%.*]] = load ptr, ptr {{%.*}}
// Construct single.
- // CHECK-NEXT: [[SINGLE:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[THIS]], i32 0, i32 0
- // CHECK-NEXT: call void @_ZN6test111AC1Ev(ptr {{[^,]*}} [[SINGLE]])
+ // CHECK-NEXT: call void @_ZN6test111AC1Ev(ptr {{[^,]*}} [[THIS]])
// Construct array.
// CHECK-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[C:%.*]], ptr [[THIS]], i32 0, i32 1
// CHECK-NEXT: [[ARRAYBEGIN:%.*]] = getelementptr inbounds [2 x [3 x [[A:%.*]]]], ptr [[ARRAY]], i32 0, i32 0, i32 0
@@ -560,8 +559,8 @@ namespace test11 {
// CHECK: br label
// Finally, the cleanup for single.
- // CHECK98: invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[SINGLE]])
- // CHECK11: call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[SINGLE]])
+ // CHECK98: invoke void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[THIS]])
+ // CHECK11: call void @_ZN6test111AD1Ev(ptr {{[^,]*}} [[THIS]])
// CHECK: br label
// CHECK: resume
diff --git a/clang/test/CodeGenCXX/lambda-deterministic-captures.cpp b/clang/test/CodeGenCXX/lambda-deterministic-captures.cpp
index 6236ff2ca66cb..5f14e3977db00 100644
--- a/clang/test/CodeGenCXX/lambda-deterministic-captures.cpp
+++ b/clang/test/CodeGenCXX/lambda-deterministic-captures.cpp
@@ -16,8 +16,7 @@ void foo() {
}
// CHECK: define{{.*}} void @_Z3foov
-// CHECK: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 0
-// CHECK-NEXT: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 1
+// CHECK: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 1
// CHECK-NEXT: store float 0.000
// CHECK-NEXT: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 2
// CHECK-NEXT: store float 1.000
@@ -27,7 +26,6 @@ void foo() {
// The lambda body. Reverse iteration when the captures aren't deterministic
// causes these to be laid out
diff erently in the lambda.
// CHECK: define internal void
-// CHECK: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 0
// CHECK: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 1
// CHECK: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 2
// CHECK: getelementptr inbounds %{{.+}}, ptr %{{.+}}, i32 0, i32 3
diff --git a/clang/test/CodeGenCXX/partial-destruction.cpp b/clang/test/CodeGenCXX/partial-destruction.cpp
index 8ceb4b9bbedea..ab6155e6f6a71 100644
--- a/clang/test/CodeGenCXX/partial-destruction.cpp
+++ b/clang/test/CodeGenCXX/partial-destruction.cpp
@@ -107,13 +107,12 @@ namespace test1 {
// CHECK: [[V:%.*]] = alloca [[B:%.*]], align 4
// CHECK-NEXT: alloca ptr
// CHECK-NEXT: alloca i32
- // CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[B]], ptr [[V]], i32 0, i32 0
- // CHECK-NEXT: call void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[X]], i32 noundef 5)
- // CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds [[B]], ptr [[V]], i32 0, i32 1
+ // CHECK-NEXT: call void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[V]], i32 noundef 5)
+ // CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds i8, ptr [[V]], i64 1
// CHECK-NEXT: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[Y]], i32 noundef 6)
- // CHECK: [[Z:%.*]] = getelementptr inbounds [[B]], ptr [[V]], i32 0, i32 2
+ // CHECK: [[Z:%.*]] = getelementptr inbounds i8, ptr [[V]], i64 2
// CHECK-NEXT: invoke void @_ZN5test11AC1Ei(ptr {{[^,]*}} [[Z]], i32 noundef 7)
- // CHECK: [[W:%.*]] = getelementptr inbounds [[B]], ptr [[V]], i32 0, i32 3
+ // CHECK: [[W:%.*]] = getelementptr inbounds [[B]], ptr [[V]], i32 0, i32 1
// CHECK-NEXT: store i32 8, ptr [[W]], align 4
// CHECK-NEXT: call void @_ZN5test11BD1Ev(ptr {{[^,]*}} [[V]])
// CHECK-NEXT: ret void
@@ -124,9 +123,9 @@ namespace test1 {
// CHECK: landingpad { ptr, i32 }
// CHECK-NEXT: cleanup
// CHECKv03: invoke void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[Y]])
- // CHECKv03: invoke void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[X]])
+ // CHECKv03: invoke void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[V]])
// CHECKv11: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[Y]])
- // CHECKv11: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[X]])
+ // CHECKv11: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[V]])
}
namespace test2 {
diff --git a/clang/test/CodeGenCXX/pod-member-memcpys.cpp b/clang/test/CodeGenCXX/pod-member-memcpys.cpp
index 16d3d45a8179b..8efec6184a3da 100644
--- a/clang/test/CodeGenCXX/pod-member-memcpys.cpp
+++ b/clang/test/CodeGenCXX/pod-member-memcpys.cpp
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-apple-darwin10 -emit-llvm -std=c++03 -fexceptions -fcxx-exceptions -o - %s | FileCheck %s
// RUN: %clang_cc1 -no-enable-noundef-analysis -triple i386-apple-darwin10 -emit-llvm -std=c++03 -o - %s | FileCheck --check-prefix=CHECK-2 %s
+struct Empty {};
+
struct POD {
int w, x, y, z;
};
@@ -106,6 +108,20 @@ struct __attribute__((packed)) PackedMembers {
int w, x, y, z;
};
+struct WithEmptyField {
+ int a;
+ Empty e;
+ NonPOD np;
+ int b;
+};
+
+struct WithEmptyNUAField {
+ int a;
+ [[no_unique_address]] Empty e;
+ NonPOD np;
+ int b;
+};
+
// COPY-ASSIGNMENT OPERATORS:
// Assignment operators are output in the order they're encountered.
@@ -121,6 +137,8 @@ CALL_AO(VolatileMember)
CALL_AO(BitfieldMember)
CALL_AO(InnerClassMember)
CALL_AO(PackedMembers)
+CALL_AO(WithEmptyField)
+CALL_AO(WithEmptyNUAField)
// Basic copy-assignment:
// CHECK-LABEL: define linkonce_odr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN5BasicaSERKS_(ptr {{[^,]*}} %this, ptr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %0)
@@ -185,6 +203,18 @@ CALL_AO(PackedMembers)
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.*}} align 1 {{.*}} align 1 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret ptr
+// WithEmptyField copy-assignment:
+// CHECK-LABEL: define linkonce_odr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN14WithEmptyFieldaSERKS_
+// CHECK: call void @llvm.memcpy.p0.p0.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 4, i1 {{.*}})
+// CHECK: call nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN6NonPODaSERKS_
+// CHECK: ret ptr
+
+// WithEmptyNUAField copy-assignment:
+// CHECK-LABEL: define linkonce_odr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN17WithEmptyNUAFieldaSERKS_
+// CHECK: call void @llvm.memcpy.p0.p0.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 4, i1 {{.*}})
+// CHECK: call nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN6NonPODaSERKS_
+// CHECK: ret ptr
+
// COPY-CONSTRUCTORS:
// Clang outputs copy-constructors in the reverse of the order that
@@ -280,3 +310,15 @@ CALL_CC(Basic)
// CHECK: call void @_ZN6NonPODC1ERKS_
// CHECK: call void @llvm.memcpy.p0.p0.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 16, i1 {{.*}})
// CHECK: ret void
+
+CALL_CC(WithEmptyField)
+// WithEmptyField copy-constructor:
+// CHECK-LABEL: define linkonce_odr void @_ZN14WithEmptyFieldC2ERKS_
+// CHECK: call void @llvm.memcpy.p0.p0.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 4, i1 {{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
+
+CALL_CC(WithEmptyNUAField)
+// WithEmptyNUAField copy-constructor:
+// CHECK-LABEL: define linkonce_odr void @_ZN17WithEmptyNUAFieldC2ERKS_(ptr {{[^,]*}} %this, ptr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %0)
+// CHECK: call void @llvm.memcpy.p0.p0.i64({{.*}} align 4 {{.*}} align 4 {{.*}}i64 4, i1 {{.*}})
+// CHECK: call void @_ZN6NonPODC1ERKS_
diff --git a/clang/test/CodeGenCXX/pr18962.cpp b/clang/test/CodeGenCXX/pr18962.cpp
index b564a7b9a73af..9ac87003c94c5 100644
--- a/clang/test/CodeGenCXX/pr18962.cpp
+++ b/clang/test/CodeGenCXX/pr18962.cpp
@@ -23,7 +23,6 @@ D p3;
// We end up using an opaque type for 'append' to avoid circular references.
// CHECK: %class.A = type { ptr }
-// CHECK: %class.C = type <{ ptr, %class.B, [3 x i8] }>
-// CHECK: %class.B = type { i8 }
+// CHECK: %class.C = type <{ ptr, [4 x i8] }>
// CHECK: %class.D = type { %class.C.base, [3 x i8] }
-// CHECK: %class.C.base = type <{ ptr, %class.B }>
+// CHECK: %class.C.base = type <{ ptr, i8 }>
diff --git a/clang/test/CodeGenCXX/references.cpp b/clang/test/CodeGenCXX/references.cpp
index 0fca5e76659c2..b84cb788d161c 100644
--- a/clang/test/CodeGenCXX/references.cpp
+++ b/clang/test/CodeGenCXX/references.cpp
@@ -191,7 +191,6 @@ namespace N2 {
// CHECK-LABEL: define{{.*}} void @_ZN2N21fEi
// CHECK: call void @_ZN2N24getPEv
- // CHECK: getelementptr inbounds
// CHECK: store i32 17
// CHECK: call void @_ZN2N21PD1Ev
void f(int i) {
@@ -220,8 +219,7 @@ namespace N2 {
// CHECK-LABEL: define{{.*}} void @_ZN2N21gEi
// CHECK: call void @_ZN2N24getZEv
- // CHECK: {{getelementptr inbounds.*i32 0, i32 0}}
- // CHECK: {{getelementptr inbounds.*i32 0, i32 0}}
+ // CHECK: {{getelementptr inbounds.*i64 16}}
// CHECK: store i32 19
// CHECK: call void @_ZN2N21ZD1Ev
// CHECK: ret void
diff --git a/clang/test/CodeGenCXX/temporaries.cpp b/clang/test/CodeGenCXX/temporaries.cpp
index f992ce206c581..9f697bd9bf3ef 100644
--- a/clang/test/CodeGenCXX/temporaries.cpp
+++ b/clang/test/CodeGenCXX/temporaries.cpp
@@ -715,7 +715,7 @@ namespace MultipleExtension {
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev, {{.*}} @[[TEMPA]]
// CHECK: store {{.*}} @[[TEMPA]], {{.*}} @[[TEMPE:_ZGRN17MultipleExtension2e1E.*]],
- // CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i32 0, i32 1))
+ // CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i64 8))
// CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e1E.*]])
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev, {{.*}} @[[TEMPD]]
@@ -729,7 +729,7 @@ namespace MultipleExtension {
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev, {{.*}} @[[TEMPA]]
// CHECK: store {{.*}} @[[TEMPA]], {{.*}} @[[E:_ZN17MultipleExtension2e2E]]
- // CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[E]], i32 0, i32 1))
+ // CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[E]], i64 8))
// CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e2E.*]])
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev, {{.*}} @[[TEMPD]]
@@ -744,11 +744,11 @@ namespace MultipleExtension {
// CHECK: %[[TEMPE1_A:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1:.*]], i32 0, i32 0
// CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA1:.*]])
// CHECK: store {{.*}} %[[TEMPA1]], {{.*}} %[[TEMPE1_A]]
- // CHECK: %[[TEMPE1_B:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 1
+ // CHECK: %[[TEMPE1_B:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i64 8
// CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE1_B]])
// CHECK: %[[TEMPE1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 2
// CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD1:.*]])
- // CHECK: %[[TEMPD1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD1]], i32 0, i32 1
+ // CHECK: %[[TEMPD1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD1]], i64 4
// CHECK: store {{.*}} %[[TEMPD1_C]], {{.*}} %[[TEMPE1_C]]
// CHECK: store {{.*}} %[[TEMPE1]], {{.*}} %[[E1:.*]]
@@ -759,11 +759,11 @@ namespace MultipleExtension {
// CHECK: %[[TEMPE2_A:.*]] = getelementptr inbounds {{.*}} %[[E2:.*]], i32 0, i32 0
// CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA2:.*]])
// CHECK: store {{.*}} %[[TEMPA2]], {{.*}} %[[TEMPE2_A]]
- // CHECK: %[[TEMPE2_B:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 1
+ // CHECK: %[[TEMPE2_B:.*]] = getelementptr inbounds {{.*}} %[[E2]], i64 8
// CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE2_B]])
// CHECK: %[[TEMPE2_C:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 2
// CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD2:.*]])
- // CHECK: %[[TEMPD2_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD2]], i32 0, i32 1
+ // CHECK: %[[TEMPD2_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD2]], i64 4
// CHECK: store {{.*}} %[[TEMPD2_C]], ptr %[[TEMPE2_C]]
g();
diff --git a/clang/test/CodeGenCXX/zero-init-empty-virtual.cpp b/clang/test/CodeGenCXX/zero-init-empty-virtual.cpp
new file mode 100644
index 0000000000000..98eb01454c1e3
--- /dev/null
+++ b/clang/test/CodeGenCXX/zero-init-empty-virtual.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK
+
+struct polymorphic_base {
+ virtual void func() {}
+ virtual ~polymorphic_base() {}
+};
+
+struct Empty {};
+struct derived_virtual : virtual Empty {};
+struct derived : polymorphic_base {};
+
+// CHECK: %struct.Holder1 = type { %struct.polymorphic_base }
+// CHECK: %struct.polymorphic_base = type { ptr }
+// CHECK: %struct.Holder2 = type { %struct.derived_virtual }
+// CHECK: %struct.derived_virtual = type { ptr }
+// CHECK: %struct.Holder3 = type { %struct.derived }
+// CHECK: %struct.derived = type { %struct.polymorphic_base }
+
+struct Holder1 {
+ polymorphic_base a{};
+} g_holder1;
+
+// CHECK: @{{.*}} = {{.*}}global %struct.Holder1 { %struct.polymorphic_base { ptr {{.*}} } }
+
+struct Holder2 {
+ derived_virtual a{};
+} g_holder2;
+
+// CHECK: @{{.*}} = {{.*}}global %struct.Holder2 zeroinitializer, align 8
+
+struct Holder3 {
+ derived a{};
+} g_holder3;
+
+// CHECK: @{{.*}} = {{.*}}global { { ptr } } { { ptr } { ptr {{.*}} } }
diff --git a/clang/test/CodeGenObjCXX/lambda-to-block.mm b/clang/test/CodeGenObjCXX/lambda-to-block.mm
index e3ce7104d97bf..86b540ed52e9e 100644
--- a/clang/test/CodeGenObjCXX/lambda-to-block.mm
+++ b/clang/test/CodeGenObjCXX/lambda-to-block.mm
@@ -2,11 +2,10 @@
// Shouldn't crash!
-// CHECK: %[[CLASS_ANON:.*]] = type { %[[STRUCT_COPYABLE:.*]] }
-// CHECK: %[[STRUCT_COPYABLE]] = type { i8 }
-// CHECK: %[[CLASS_ANON_0:.*]] = type { %[[STRUCT_COPYABLE]] }
-// CHECK: %[[CLASS_ANON_1:.*]] = type { %[[STRUCT_COPYABLE]] }
-// CHECK: %[[CLASS_ANON_2:.*]] = type { %[[STRUCT_COPYABLE]] }
+// CHECK: %[[CLASS_ANON:.*]] = type { i8 }
+// CHECK: %[[CLASS_ANON_0:.*]] = type { i8 }
+// CHECK: %[[CLASS_ANON_1:.*]] = type { i8 }
+// CHECK: %[[CLASS_ANON_2:.*]] = type { i8 }
// CHECK: @[[BLOCK_DESC0:.*]] = internal constant { i64, i64, ptr, ptr, ptr, ptr } { i64 0, i64 33, ptr @[[COPY_HELPER0:.*__copy_helper_block_.*]], ptr @__destroy_helper_block{{.*}}, {{.*}}}, align 8
// CHECK: @[[BLOCK_DESC1:.*]] = internal constant { i64, i64, ptr, ptr, ptr, ptr } { i64 0, i64 33, ptr @[[COPY_HELPER1:.*__copy_helper_block_.*]], ptr @__destroy_helper_block{{.*}}, {{.*}}}, align 8
diff --git a/clang/test/OpenMP/irbuilder_for_iterator.cpp b/clang/test/OpenMP/irbuilder_for_iterator.cpp
index b88416b36c4fa..99469d62a9fc1 100644
--- a/clang/test/OpenMP/irbuilder_for_iterator.cpp
+++ b/clang/test/OpenMP/irbuilder_for_iterator.cpp
@@ -48,8 +48,7 @@ extern "C" void workshareloop_iterator(float *a, float *b, float *c) {
// CHECK-NEXT: call void @_ZN10MyIteratorC1Ej(ptr noundef nonnull align 1 dereferenceable(1) [[IT]], i32 noundef 7)
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[AGG_CAPTURED]], i32 0, i32 0
// CHECK-NEXT: store ptr [[IT]], ptr [[TMP0]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[AGG_CAPTURED1]], i32 0, i32 0
-// CHECK-NEXT: call void @_ZN10MyIteratorC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]], ptr noundef nonnull align 1 dereferenceable(1) [[IT]])
+// CHECK-NEXT: call void @_ZN10MyIteratorC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_CAPTURED1]], ptr noundef nonnull align 1 dereferenceable(1) [[IT]])
// CHECK-NEXT: call void @__captured_stmt(ptr [[DOTCOUNT_ADDR]], ptr [[AGG_CAPTURED]])
// CHECK-NEXT: [[DOTCOUNT:%.*]] = load i64, ptr [[DOTCOUNT_ADDR]], align 8
// CHECK-NEXT: br label [[OMP_LOOP_PREHEADER:%.*]]
@@ -155,11 +154,10 @@ extern "C" void workshareloop_iterator(float *a, float *b, float *c) {
// CHECK-NEXT: store i64 [[LOGICAL]], ptr [[LOGICAL_ADDR]], align 8
// CHECK-NEXT: store ptr [[__CONTEXT]], ptr [[__CONTEXT_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__CONTEXT_ADDR]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], ptr [[TMP0]], i32 0, i32 0
-// CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[LOGICAL_ADDR]], align 8
-// CHECK-NEXT: [[MUL:%.*]] = mul i64 1, [[TMP2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[LOGICAL_ADDR]], align 8
+// CHECK-NEXT: [[MUL:%.*]] = mul i64 1, [[TMP1]]
// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[MUL]] to i32
-// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]], i32 noundef [[CONV]])
+// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP0]], i32 noundef [[CONV]])
// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[LOOPVAR_ADDR]], align 8
// CHECK-NEXT: [[CALL:%.*]] = call noundef nonnull align 1 dereferenceable(1) ptr @_ZN10MyIteratoraSERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[TMP3]], ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]])
// CHECK-NEXT: ret void
diff --git a/clang/test/OpenMP/irbuilder_for_rangefor.cpp b/clang/test/OpenMP/irbuilder_for_rangefor.cpp
index 6bf91bfda138a..6bf44e2ee4153 100644
--- a/clang/test/OpenMP/irbuilder_for_rangefor.cpp
+++ b/clang/test/OpenMP/irbuilder_for_rangefor.cpp
@@ -66,8 +66,7 @@ extern "C" void workshareloop_rangefor(float *a, float *b, float *c) {
// CHECK-NEXT: store ptr [[__BEGIN2]], ptr [[TMP2]], align 8
// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[AGG_CAPTURED]], i32 0, i32 1
// CHECK-NEXT: store ptr [[__END2]], ptr [[TMP3]], align 8
-// CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_ANON_0]], ptr [[AGG_CAPTURED1]], i32 0, i32 0
-// CHECK-NEXT: call void @_ZN10MyIteratorC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[TMP4]], ptr noundef nonnull align 1 dereferenceable(1) [[__BEGIN2]])
+// CHECK-NEXT: call void @_ZN10MyIteratorC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_CAPTURED1]], ptr noundef nonnull align 1 dereferenceable(1) [[__BEGIN2]])
// CHECK-NEXT: call void @__captured_stmt(ptr [[DOTCOUNT_ADDR]], ptr [[AGG_CAPTURED]])
// CHECK-NEXT: [[DOTCOUNT:%.*]] = load i64, ptr [[DOTCOUNT_ADDR]], align 8
// CHECK-NEXT: br label [[OMP_LOOP_PREHEADER:%.*]]
@@ -173,13 +172,12 @@ extern "C" void workshareloop_rangefor(float *a, float *b, float *c) {
// CHECK-NEXT: store i64 [[LOGICAL]], ptr [[LOGICAL_ADDR]], align 8
// CHECK-NEXT: store ptr [[__CONTEXT]], ptr [[__CONTEXT_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[__CONTEXT_ADDR]], align 8
-// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_ANON_0:%.*]], ptr [[TMP0]], i32 0, i32 0
-// CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[LOGICAL_ADDR]], align 8
-// CHECK-NEXT: [[MUL:%.*]] = mul i64 1, [[TMP2]]
+// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[LOGICAL_ADDR]], align 8
+// CHECK-NEXT: [[MUL:%.*]] = mul i64 1, [[TMP1]]
// CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[MUL]] to i32
-// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP1]], i32 noundef [[CONV]])
+// CHECK-NEXT: call void @_ZNK10MyIteratorplEj(ptr dead_on_unwind writable sret([[STRUCT_MYITERATOR]]) align 1 [[REF_TMP]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP0]], i32 noundef [[CONV]])
// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK10MyIteratordeEv(ptr noundef nonnull align 1 dereferenceable(1) [[REF_TMP]])
-// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[LOOPVAR_ADDR]], align 8
-// CHECK-NEXT: store i32 [[CALL]], ptr [[TMP3]], align 4
+// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[LOOPVAR_ADDR]], align 8
+// CHECK-NEXT: store i32 [[CALL]], ptr [[TMP2]], align 4
// CHECK-NEXT: ret void
//
diff --git a/clang/test/OpenMP/task_member_call_codegen.cpp b/clang/test/OpenMP/task_member_call_codegen.cpp
index b7e0b41b291ec..c2ab3317ea9bd 100644
--- a/clang/test/OpenMP/task_member_call_codegen.cpp
+++ b/clang/test/OpenMP/task_member_call_codegen.cpp
@@ -32,9 +32,8 @@ void c() {
// CHECK1-NEXT: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]])
// CHECK1-NEXT: [[TMP1:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP0]], i32 1, i64 48, i64 1, ptr @.omp_task_entry.)
// CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP1]], i32 0, i32 0
-// CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP1]], i32 0, i32 1
-// CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP3]], i32 0, i32 0
-// CHECK1-NEXT: [[TMP5:%.*]] = call i32 @__kmpc_omp_task(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP1]])
+// CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 40
+// CHECK1-NEXT: [[TMP4:%.*]] = call i32 @__kmpc_omp_task(ptr @[[GLOB1]], i32 [[TMP0]], ptr [[TMP1]])
// CHECK1-NEXT: ret void
//
//
@@ -46,9 +45,8 @@ void c() {
// CHECK1-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
// CHECK1-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
// CHECK1-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8
-// CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP2]], i32 0, i32 0
-// CHECK1-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
-// CHECK1-NEXT: store ptr [[TMP3]], ptr [[TMP4]], align 8
+// CHECK1-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
+// CHECK1-NEXT: store ptr [[TMP2]], ptr [[TMP3]], align 8
// CHECK1-NEXT: ret void
//
//
@@ -72,7 +70,7 @@ void c() {
// CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2
// CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0
// CHECK1-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
-// CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1
+// CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 40
// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
// CHECK1-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
@@ -100,8 +98,7 @@ void c() {
// CHECK3-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB3:[0-9]+]])
// CHECK3-NEXT: [[TMP0:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1:[0-9]+]], i32 [[OMP_GLOBAL_THREAD_NUM]], i32 1, i64 48, i64 1, ptr @.omp_task_entry.)
// CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP0]], i32 0, i32 0
-// CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP0]], i32 0, i32 1
-// CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP2]], i32 0, i32 0
+// CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 40
// CHECK3-NEXT: [[OMP_GLOBAL_THREAD_NUM1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB3]])
// CHECK3-NEXT: [[TMP4:%.*]] = call i32 @__kmpc_omp_task(ptr @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM1]], ptr [[TMP0]])
// CHECK3-NEXT: ret void
@@ -115,9 +112,8 @@ void c() {
// CHECK3-NEXT: store ptr [[TMP0]], ptr [[DOTADDR]], align 8
// CHECK3-NEXT: store ptr [[TMP1]], ptr [[DOTADDR1]], align 8
// CHECK3-NEXT: [[TMP2:%.*]] = load ptr, ptr [[DOTADDR]], align 8
-// CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT__KMP_PRIVATES_T:%.*]], ptr [[TMP2]], i32 0, i32 0
-// CHECK3-NEXT: [[TMP4:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
-// CHECK3-NEXT: store ptr [[TMP3]], ptr [[TMP4]], align 8
+// CHECK3-NEXT: [[TMP3:%.*]] = load ptr, ptr [[DOTADDR1]], align 8
+// CHECK3-NEXT: store ptr [[TMP2]], ptr [[TMP3]], align 8
// CHECK3-NEXT: ret void
//
//
@@ -141,7 +137,7 @@ void c() {
// CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP4]], i32 0, i32 2
// CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T]], ptr [[TMP4]], i32 0, i32 0
// CHECK3-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP6]], align 8
-// CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT_KMP_TASK_T_WITH_PRIVATES]], ptr [[TMP3]], i32 0, i32 1
+// CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 40
// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
// CHECK3-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
More information about the cfe-commits
mailing list