/// temporary. When either happens, the expression will also track the
/// declaration which is responsible for the lifetime extension.
class MaterializeTemporaryExpr : public Expr {
-public:
- /// \brief The temporary-generating expression whose value will be
- /// materialized.
- Stmt *Temporary;
+private:
+ struct ExtraState {
+ /// \brief The temporary-generating expression whose value will be
+ /// materialized.
+ Stmt *Temporary;
- /// \brief The declaration which lifetime-extended this reference, if any.
- /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
- const ValueDecl *ExtendingDecl;
+ /// \brief The declaration which lifetime-extended this reference, if any.
+ /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl.
+ const ValueDecl *ExtendingDecl;
+
+ unsigned ManglingNumber;
+ };
+ llvm::PointerUnion<Stmt *, ExtraState *> State;
friend class ASTStmtReader;
friend class ASTStmtWriter;
+ void initializeExtraState(const ValueDecl *ExtendedBy,
+ unsigned ManglingNumber);
+
public:
MaterializeTemporaryExpr(QualType T, Expr *Temporary,
- bool BoundToLvalueReference,
- const ValueDecl *ExtendedBy)
+ bool BoundToLvalueReference)
: Expr(MaterializeTemporaryExprClass, T,
BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary,
Temporary->isTypeDependent(), Temporary->isValueDependent(),
Temporary->isInstantiationDependent(),
Temporary->containsUnexpandedParameterPack()),
- Temporary(Temporary), ExtendingDecl(ExtendedBy) {
- }
+ State(Temporary) {}
MaterializeTemporaryExpr(EmptyShell Empty)
: Expr(MaterializeTemporaryExprClass, Empty) { }
+ Stmt *getTemporary() const {
+ return State.is<Stmt *>() ? State.get<Stmt *>()
+ : State.get<ExtraState *>()->Temporary;
+ }
+
/// \brief Retrieve the temporary-generating subexpression whose value will
/// be materialized into a glvalue.
- Expr *GetTemporaryExpr() const { return static_cast<Expr *>(Temporary); }
+ Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); }
/// \brief Retrieve the storage duration for the materialized temporary.
StorageDuration getStorageDuration() const {
+ const ValueDecl *ExtendingDecl = getExtendingDecl();
if (!ExtendingDecl)
return SD_FullExpression;
// FIXME: This is not necessarily correct for a temporary materialized
/// \brief Get the declaration which triggered the lifetime-extension of this
/// temporary, if any.
- const ValueDecl *getExtendingDecl() const { return ExtendingDecl; }
+ const ValueDecl *getExtendingDecl() const {
+ return State.is<Stmt *>() ? nullptr
+ : State.get<ExtraState *>()->ExtendingDecl;
+ }
+
+ void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber);
- void setExtendingDecl(const ValueDecl *ExtendedBy) {
- ExtendingDecl = ExtendedBy;
+ unsigned getManglingNumber() const {
+ return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber;
}
/// \brief Determine whether this materialized temporary is bound to an
}
SourceLocation getLocStart() const LLVM_READONLY {
- return Temporary->getLocStart();
+ return getTemporary()->getLocStart();
}
SourceLocation getLocEnd() const LLVM_READONLY {
- return Temporary->getLocEnd();
+ return getTemporary()->getLocEnd();
}
static bool classof(const Stmt *T) {
}
// Iterators
- child_range children() { return child_range(&Temporary, &Temporary + 1); }
+ child_range children() {
+ if (State.is<Stmt *>())
+ return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1);
+
+ auto ES = State.get<ExtraState *>();
+ return child_range(&ES->Temporary, &ES->Temporary + 1);
+ }
};
} // end namespace clang
const ThisAdjustment &ThisAdjustment,
raw_ostream &) = 0;
virtual void mangleReferenceTemporary(const VarDecl *D,
+ unsigned ManglingNumber,
raw_ostream &) = 0;
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
/// \brief The type of the object or reference being initialized.
QualType Type;
+ /// \brief The mangling number for the next reference temporary to be created.
+ mutable unsigned ManglingNumber;
+
struct LN {
/// \brief When Kind == EK_Result, EK_Exception, EK_New, the
/// location of the 'return', 'throw', or 'new' keyword,
struct C Capture;
};
- InitializedEntity() { }
+ InitializedEntity() : ManglingNumber(0) {}
/// \brief Create the initialization entity for a variable.
InitializedEntity(VarDecl *Var)
- : Kind(EK_Variable), Parent(0), Type(Var->getType()),
+ : Kind(EK_Variable), Parent(0), Type(Var->getType()), ManglingNumber(0),
VariableOrMember(Var) { }
/// \brief Create the initialization entity for the result of a
/// initializing a parameter for which there is no declaration.
InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
bool NRVO = false)
- : Kind(Kind), Parent(0), Type(Type)
+ : Kind(Kind), Parent(0), Type(Type), ManglingNumber(0)
{
LocAndNRVO.Location = Loc.getRawEncoding();
LocAndNRVO.NRVO = NRVO;
/// \brief Create the initialization entity for a member subobject.
InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent)
: Kind(EK_Member), Parent(Parent), Type(Member->getType()),
- VariableOrMember(Member) { }
+ ManglingNumber(0), VariableOrMember(Member) { }
/// \brief Create the initialization entity for an array element.
InitializedEntity(ASTContext &Context, unsigned Index,
/// \brief Create the initialization entity for a lambda capture.
InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
- : Kind(EK_LambdaCapture), Parent(0), Type(FieldType)
+ : Kind(EK_LambdaCapture), Parent(0), Type(FieldType), ManglingNumber(0)
{
Capture.VarID = VarID;
Capture.Location = Loc.getRawEncoding();
Kind = EK_Parameter_CF_Audited;
}
+ unsigned allocateManglingNumber() const { return ++ManglingNumber; }
+
/// Dump a representation of the initialized entity to standard error,
/// for debugging purposes.
void dump() const;
FunctionParmPackExpr(QualType(), 0, SourceLocation(), 0, 0);
}
+void MaterializeTemporaryExpr::setExtendingDecl(const ValueDecl *ExtendedBy,
+ unsigned ManglingNumber) {
+ // We only need extra state if we have to remember more than just the Stmt.
+ if (!ExtendedBy)
+ return;
+
+ // We may need to allocate extra storage for the mangling number and the
+ // extended-by ValueDecl.
+ if (!State.is<ExtraState *>()) {
+ auto ES = new (ExtendedBy->getASTContext()) ExtraState;
+ ES->Temporary = State.get<Stmt *>();
+ State = ES;
+ }
+
+ auto ES = State.get<ExtraState *>();
+ ES->ExtendingDecl = ExtendedBy;
+ ES->ManglingNumber = ManglingNumber;
+}
+
TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc,
void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
const ThisAdjustment &ThisAdjustment,
raw_ostream &) override;
- void mangleReferenceTemporary(const VarDecl *D, raw_ostream &) override;
+ void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber,
+ raw_ostream &) override;
void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) override;
void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) override;
void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
}
void ItaniumMangleContextImpl::mangleReferenceTemporary(const VarDecl *D,
+ unsigned ManglingNumber,
raw_ostream &Out) {
// We match the GCC mangling here.
// <special-name> ::= GR <object name>
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZGR";
Mangler.mangleName(D);
+ assert(ManglingNumber > 0 && "Reference temporary mangling number is zero!");
+ if (ManglingNumber > 1)
+ Mangler.mangleNumber(ManglingNumber - 2);
}
void ItaniumMangleContextImpl::mangleCXXVTable(const CXXRecordDecl *RD,
raw_ostream &) override;
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
raw_ostream &) override;
- void mangleReferenceTemporary(const VarDecl *, raw_ostream &) override;
+ void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
+ raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
}
void MicrosoftMangleContextImpl::mangleReferenceTemporary(const VarDecl *VD,
+ unsigned,
raw_ostream &) {
unsigned DiagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"cannot mangle this reference temporary yet");
// we also need to make the temporaries externally-visible).
SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
- getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out);
+ getCXXABI().getMangleContext().mangleReferenceTemporary(
+ VD, E->getManglingNumber(), Out);
Out.flush();
APValue *Value = 0;
// This is a const_cast from a class prvalue to an rvalue reference type.
// Materialize a temporary to store the result of the conversion.
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
- SrcType, SrcExpr.take(), /*IsLValueReference*/ false,
- /*ExtendingDecl*/ 0);
+ SrcType, SrcExpr.take(), /*IsLValueReference*/ false);
return TC_Success;
}
return QualType();
// Materialize the temporary as an lvalue so that we can take its address.
OrigOp = op = new (Context)
- MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true, 0);
+ MaterializeTemporaryExpr(op->getType(), OrigOp.take(), true);
} else if (isa<ObjCSelectorExpr>(op)) {
return Context.getPointerType(op->getType());
} else if (lval == Expr::LV_MemberFunction) {
/// Determine the declaration which an initialized entity ultimately refers to,
/// for the purpose of lifetime-extending a temporary bound to a reference in
/// the initialization of \p Entity.
-static const ValueDecl *
-getDeclForTemporaryLifetimeExtension(const InitializedEntity &Entity,
- const ValueDecl *FallbackDecl = 0) {
+static const InitializedEntity *getEntityForTemporaryLifetimeExtension(
+ const InitializedEntity *Entity,
+ const InitializedEntity *FallbackDecl = 0) {
// C++11 [class.temporary]p5:
- switch (Entity.getKind()) {
+ switch (Entity->getKind()) {
case InitializedEntity::EK_Variable:
// The temporary [...] persists for the lifetime of the reference
- return Entity.getDecl();
+ return Entity;
case InitializedEntity::EK_Member:
// For subobjects, we look at the complete object.
- if (Entity.getParent())
- return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
- Entity.getDecl());
+ if (Entity->getParent())
+ return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+ Entity);
// except:
// -- A temporary bound to a reference member in a constructor's
// ctor-initializer persists until the constructor exits.
- return Entity.getDecl();
+ return Entity;
case InitializedEntity::EK_Parameter:
case InitializedEntity::EK_Parameter_CF_Audited:
// -- A temporary bound to a reference in a new-initializer persists
// until the completion of the full-expression containing the
// new-initializer.
- return 0;
+ return nullptr;
case InitializedEntity::EK_Temporary:
case InitializedEntity::EK_CompoundLiteralInit:
// We don't yet know the storage duration of the surrounding temporary.
// Assume it's got full-expression duration for now, it will patch up our
// storage duration if that's not correct.
- return 0;
+ return nullptr;
case InitializedEntity::EK_ArrayElement:
// For subobjects, we look at the complete object.
- return getDeclForTemporaryLifetimeExtension(*Entity.getParent(),
- FallbackDecl);
+ return getEntityForTemporaryLifetimeExtension(Entity->getParent(),
+ FallbackDecl);
case InitializedEntity::EK_Base:
case InitializedEntity::EK_Delegating:
case InitializedEntity::EK_Exception:
case InitializedEntity::EK_VectorElement:
case InitializedEntity::EK_ComplexElement:
- return 0;
+ return nullptr;
}
llvm_unreachable("unknown entity kind");
}
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD);
+static void performLifetimeExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity);
/// Update a glvalue expression that is used as the initializer of a reference
/// to note that its lifetime is extended.
/// \return \c true if any temporary had its lifetime extended.
-static bool performReferenceExtension(Expr *Init, const ValueDecl *ExtendingD) {
+static bool
+performReferenceExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity) {
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
if (ILE->getNumInits() == 1 && ILE->isGLValue()) {
// This is just redundant braces around an initializer. Step over it.
if (MaterializeTemporaryExpr *ME = dyn_cast<MaterializeTemporaryExpr>(Init)) {
// Update the storage duration of the materialized temporary.
// FIXME: Rebuild the expression instead of mutating it.
- ME->setExtendingDecl(ExtendingD);
- performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingD);
+ ME->setExtendingDecl(ExtendingEntity->getDecl(),
+ ExtendingEntity->allocateManglingNumber());
+ performLifetimeExtension(ME->GetTemporaryExpr(), ExtendingEntity);
return true;
}
/// Update a prvalue expression that is going to be materialized as a
/// lifetime-extended temporary.
-static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
+static void performLifetimeExtension(Expr *Init,
+ const InitializedEntity *ExtendingEntity) {
// Dig out the expression which constructs the extended temporary.
SmallVector<const Expr *, 2> CommaLHSs;
SmallVector<SubobjectAdjustment, 2> Adjustments;
if (CXXStdInitializerListExpr *ILE =
dyn_cast<CXXStdInitializerListExpr>(Init)) {
- performReferenceExtension(ILE->getSubExpr(), ExtendingD);
+ performReferenceExtension(ILE->getSubExpr(), ExtendingEntity);
return;
}
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
if (ILE->getType()->isArrayType()) {
for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
- performLifetimeExtension(ILE->getInit(I), ExtendingD);
+ performLifetimeExtension(ILE->getInit(I), ExtendingEntity);
return;
}
// bound to temporaries, those temporaries are also lifetime-extended.
if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
- performReferenceExtension(ILE->getInit(0), ExtendingD);
+ performReferenceExtension(ILE->getInit(0), ExtendingEntity);
else {
unsigned Index = 0;
for (const auto *I : RD->fields()) {
continue;
Expr *SubInit = ILE->getInit(Index);
if (I->getType()->isReferenceType())
- performReferenceExtension(SubInit, ExtendingD);
+ performReferenceExtension(SubInit, ExtendingEntity);
else if (isa<InitListExpr>(SubInit) ||
isa<CXXStdInitializerListExpr>(SubInit))
// This may be either aggregate-initialization of a member or
// initialization of a std::initializer_list object. Either way,
// we should recursively lifetime-extend that initializer.
- performLifetimeExtension(SubInit, ExtendingD);
+ performLifetimeExtension(SubInit, ExtendingEntity);
++Index;
}
}
// Even though we didn't materialize a temporary, the binding may still
// extend the lifetime of a temporary. This happens if we bind a reference
// to the result of a cast to reference type.
- if (const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity)) {
- if (performReferenceExtension(CurInit.get(), ExtendingDecl))
- warnOnLifetimeExtension(S, Entity, CurInit.get(), false,
- ExtendingDecl);
- }
+ if (const InitializedEntity *ExtendingEntity =
+ getEntityForTemporaryLifetimeExtension(&Entity))
+ if (performReferenceExtension(CurInit.get(), ExtendingEntity))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),
+ /*IsInitializerList=*/false,
+ ExtendingEntity->getDecl());
break;
if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
- // Maybe lifetime-extend the temporary's subobjects to match the
- // entity's lifetime.
- const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity);
- if (ExtendingDecl) {
- performLifetimeExtension(CurInit.get(), ExtendingDecl);
- warnOnLifetimeExtension(S, Entity, CurInit.get(), false, ExtendingDecl);
- }
-
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr(
Entity.getType().getNonReferenceType(), CurInit.get(),
- Entity.getType()->isLValueReferenceType(), ExtendingDecl);
+ Entity.getType()->isLValueReferenceType());
+
+ // Maybe lifetime-extend the temporary's subobjects to match the
+ // entity's lifetime.
+ if (const InitializedEntity *ExtendingEntity =
+ getEntityForTemporaryLifetimeExtension(&Entity))
+ if (performReferenceExtension(MTE, ExtendingEntity))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(), /*IsInitializerList=*/false,
+ ExtendingEntity->getDecl());
// If we're binding to an Objective-C object that has lifetime, we
// need cleanups. Likewise if we're extending this temporary to automatic
diag::warn_cxx98_compat_initializer_list_init)
<< CurInit.get()->getSourceRange();
- // Maybe lifetime-extend the array temporary's subobjects to match the
- // entity's lifetime.
- const ValueDecl *ExtendingDecl =
- getDeclForTemporaryLifetimeExtension(Entity);
- if (ExtendingDecl) {
- performLifetimeExtension(CurInit.get(), ExtendingDecl);
- warnOnLifetimeExtension(S, Entity, CurInit.get(), true, ExtendingDecl);
- }
-
// Materialize the temporary into memory.
MaterializeTemporaryExpr *MTE = new (S.Context)
MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(),
- /*lvalue reference*/ false, ExtendingDecl);
+ /*BoundToLvalueReference=*/false);
+
+ // Maybe lifetime-extend the array temporary's subobjects to match the
+ // entity's lifetime.
+ if (const InitializedEntity *ExtendingEntity =
+ getEntityForTemporaryLifetimeExtension(&Entity))
+ if (performReferenceExtension(MTE, ExtendingEntity))
+ warnOnLifetimeExtension(S, Entity, CurInit.get(),
+ /*IsInitializerList=*/true,
+ ExtendingEntity->getDecl());
// Wrap it in a construction of a std::initializer_list<T>.
CurInit = S.Owned(
void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
VisitExpr(E);
- E->Temporary = Reader.ReadSubExpr();
- E->ExtendingDecl = ReadDeclAs<ValueDecl>(Record, Idx);
+ E->State = Reader.ReadSubExpr();
+ auto VD = ReadDeclAs<ValueDecl>(Record, Idx);
+ unsigned ManglingNumber = Record[Idx++];
+ E->setExtendingDecl(VD, ManglingNumber);
}
void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) {
void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) {
VisitExpr(E);
- Writer.AddStmt(E->Temporary);
- Writer.AddDeclRef(E->ExtendingDecl, Record);
+ Writer.AddStmt(E->getTemporary());
+ Writer.AddDeclRef(E->getExtendingDecl(), Record);
+ Record.push_back(E->getManglingNumber());
Code = serialization::EXPR_MATERIALIZE_TEMPORARY;
}
const int &use = i<void>;
}
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE = linkonce_odr constant i32 1
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1 = linkonce_odr constant i32 1
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE1 }
// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 = linkonce_odr constant i32 2
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE3 }
// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 = linkonce_odr constant i32 3
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE5 }
// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 = linkonce_odr constant i32 4
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 }
-// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9 = linkonce_odr global {{.*}} { {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6, {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE8 }
-// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE9
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 = linkonce_odr global {{.*}} { i32* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE7 }
+// CHECK: @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE = linkonce_odr global %"struct.VariableTemplateWithPack::S" { {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE0, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE2, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE4, {{.*}}* @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE6 }
+// CHECK: @_ZN24VariableTemplateWithPack1pE = global {{.*}} @_ZGRN24VariableTemplateWithPack1sIJLi1ELi2ELi3ELi4EEEE
namespace VariableTemplateWithPack {
struct A {
const int &r;
{1, a}, {3, b}, {5, c}
};
-// CHECK-STATIC-BL: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4
+// CHECK-STATIC-BL: @_ZGR6nested0 = private constant [2 x i32] [i32 1, i32 2], align 4
// CHECK-STATIC-BL: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4
// CHECK-STATIC-BL: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4
-// CHECK-STATIC-BL: @_ZGR6nested3 = private constant [3 x {{.*}}] [
-// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0), i64 2 },
+// CHECK-STATIC-BL: @_ZGR6nested = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i32 0, i32 0), i64 2 },
// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0), i64 2 },
// CHECK-STATIC-BL: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0), i64 2 }
// CHECK-STATIC-BL: ], align 8
-// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0), i64 3 }, align 8
+// CHECK-STATIC-BL: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i32 0, i32 0), i64 3 }, align 8
// CHECK-DYNAMIC-BL: @nested = global
// CHECK-DYNAMIC-BL: @_ZGR6nested = private global [3 x
+// CHECK-DYNAMIC-BL: @_ZGR6nested0 = private global [2 x i32] zeroinitializer
// CHECK-DYNAMIC-BL: @_ZGR6nested1 = private global [2 x i32] zeroinitializer
// CHECK-DYNAMIC-BL: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BL: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
-// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0),
// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
-// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
-// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
-// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
-// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
-// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
+// CHECK-DYNAMIC-BL: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
+// CHECK-DYNAMIC-BL: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
+// CHECK-DYNAMIC-BL: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
// CHECK-DYNAMIC-BL: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
// CHECK-DYNAMIC-BL: store i64 2, i64* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
// CHECK-DYNAMIC-BL: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0),
// CHECK-DYNAMIC-BL: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8
// CHECK-DYNAMIC-BL: store i64 3, i64* getelementptr inbounds ({{.*}}* @nested, i32 0, i32 1), align 8
-// CHECK-STATIC-BE: @_ZGR6nested = private constant [2 x i32] [i32 1, i32 2], align 4
+// CHECK-STATIC-BE: @_ZGR6nested0 = private constant [2 x i32] [i32 1, i32 2], align 4
// CHECK-STATIC-BE: @_ZGR6nested1 = private constant [2 x i32] [i32 3, i32 4], align 4
// CHECK-STATIC-BE: @_ZGR6nested2 = private constant [2 x i32] [i32 5, i32 6], align 4
-// CHECK-STATIC-BE: @_ZGR6nested3 = private constant [3 x {{.*}}] [
-// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested, i32 0, i32 0),
-// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested to i8*), i64 8) to i32*) }
+// CHECK-STATIC-BE: @_ZGR6nested = private constant [3 x {{.*}}] [
+// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i32 0, i32 0),
+// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested0 to i8*), i64 8) to i32*) }
// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i32 0, i32 0),
// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested1 to i8*), i64 8) to i32*) }
// CHECK-STATIC-BE: {{.*}} { i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i32 0, i32 0),
// CHECK-STATIC-BE: i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @_ZGR6nested2 to i8*), i64 8) to i32*) }
// CHECK-STATIC-BE: ], align 8
-// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested3, i32 0, i32 0),
-// CHECK-STATIC-BE: {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested3 to i8*), i64 48) to {{.*}}*) }
+// CHECK-STATIC-BE: @nested = global {{.*}} { {{.*}} getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i32 0, i32 0),
+// CHECK-STATIC-BE: {{.*}} bitcast ({{.*}}* getelementptr (i8* bitcast ([3 x {{.*}}]* @_ZGR6nested to i8*), i64 48) to {{.*}}*) }
// CHECK-DYNAMIC-BE: @nested = global
// CHECK-DYNAMIC-BE: @_ZGR6nested = private global [3 x
+// CHECK-DYNAMIC-BE: @_ZGR6nested0 = private global [2 x i32] zeroinitializer
// CHECK-DYNAMIC-BE: @_ZGR6nested1 = private global [2 x i32] zeroinitializer
// CHECK-DYNAMIC-BE: @_ZGR6nested2 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BE: @_ZGR6nested3 = private global [2 x i32] zeroinitializer
-// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 1, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 1)
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 0, i64 0),
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested0, i64 1, i64 0),
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
+// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0)
// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 1)
// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 0, i64 0),
-// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 0), align 8
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested1, i64 1, i64 0),
-// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0, i32 1), align 8
-// CHECK-DYNAMIC-BE: store i32 3, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
+// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
+// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0)
// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 1)
// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 0, i64 0),
-// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 0), align 8
-// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 1, i64 0),
-// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 1, i32 1), align 8
-// CHECK-DYNAMIC-BE: store i32 5, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0)
-// CHECK-DYNAMIC-BE: store i32 {{.*}}, i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 1)
-// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 0, i64 0),
// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 0), align 8
-// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested3, i64 1, i64 0),
+// CHECK-DYNAMIC-BE: store i32* getelementptr inbounds ([2 x i32]* @_ZGR6nested2, i64 1, i64 0),
// CHECK-DYNAMIC-BE: i32** getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 2, i32 1), align 8
// CHECK-DYNAMIC-BE: store {{.*}}* getelementptr inbounds ([3 x {{.*}}]* @_ZGR6nested, i64 0, i64 0),
// CHECK-DYNAMIC-BE: {{.*}}** getelementptr inbounds ({{.*}}* @nested, i32 0, i32 0), align 8