Author: ibiryukov Date: Sun Jul 22 23:32:36 2018 New Revision: 337671 URL: http://llvm.org/viewvc/llvm-project?rev=337671&view=rev Log: Revert "Fold dangling-field warning into general initialization lifetime checks."
This reverts commit r337627. After the change, clang started producing invalid warning on the following code: struct foo { foo(char *x) : x_(&x[10]) {} private: char *x_; }; 1.cpp:2:21: warning: initializing pointer member 'x_' with the stack address of parameter 'x' [-Wdangling-field] Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337671&r1=337670&r2=337671&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Jul 22 23:32:36 2018 @@ -7870,11 +7870,11 @@ def note_ref_var_local_bind : Note< // Check for initializing a member variable with the address or a reference to // a constructor parameter. def warn_bind_ref_member_to_parameter : Warning< - "binding reference member %0 to stack allocated " - "%select{variable|parameter}2 %1">, InGroup<DanglingField>; + "binding reference member %0 to stack allocated parameter %1">, + InGroup<DanglingField>; def warn_init_ptr_member_to_parameter_addr : Warning< - "initializing pointer member %0 with the stack address of " - "%select{variable|parameter}2 %1">, InGroup<DanglingField>; + "initializing pointer member %0 with the stack address of parameter %1">, + InGroup<DanglingField>; def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=337671&r1=337670&r2=337671&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Jul 22 23:32:36 2018 @@ -3946,6 +3946,53 @@ Sema::BuildMemInitializer(Decl *Construc return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } +/// Checks a member initializer expression for cases where reference (or +/// pointer) members are bound to by-value parameters (or their addresses). +static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, + Expr *Init, + SourceLocation IdLoc) { + QualType MemberTy = Member->getType(); + + // We only handle pointers and references currently. + // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? + if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) + return; + + const bool IsPointer = MemberTy->isPointerType(); + if (IsPointer) { + if (const UnaryOperator *Op + = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) { + // The only case we're worried about with pointers requires taking the + // address. + if (Op->getOpcode() != UO_AddrOf) + return; + + Init = Op->getSubExpr(); + } else { + // We only handle address-of expression initializers for pointers. + return; + } + } + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) { + // We only warn when referring to a non-reference parameter declaration. + const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl()); + if (!Parameter || Parameter->getType()->isReferenceType()) + return; + + S.Diag(Init->getExprLoc(), + IsPointer ? diag::warn_init_ptr_member_to_parameter_addr + : diag::warn_bind_ref_member_to_parameter) + << Member << Parameter << Init->getSourceRange(); + } else { + // Other initializers are fine. + return; + } + + S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) + << (unsigned)IsPointer; +} + MemInitResult Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { @@ -4000,6 +4047,8 @@ Sema::BuildMemberInitializer(ValueDecl * if (MemberInit.isInvalid()) return true; + CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=337671&r1=337670&r2=337671&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Sun Jul 22 23:32:36 2018 @@ -6227,7 +6227,7 @@ using LifetimeResult = /// 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 LifetimeResult getEntityLifetime( +static LifetimeResult getEntityForTemporaryLifetimeExtension( const InitializedEntity *Entity, const InitializedEntity *InitField = nullptr) { // C++11 [class.temporary]p5: @@ -6239,7 +6239,8 @@ static LifetimeResult getEntityLifetime( case InitializedEntity::EK_Member: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityLifetime(Entity->getParent(), Entity); + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + Entity); // except: // C++17 [class.base.init]p8: @@ -6290,12 +6291,14 @@ static LifetimeResult getEntityLifetime( case InitializedEntity::EK_ArrayElement: // For subobjects, we look at the complete object. - return getEntityLifetime(Entity->getParent(), InitField); + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + InitField); case InitializedEntity::EK_Base: // For subobjects, we look at the complete object. if (Entity->getParent()) - return getEntityLifetime(Entity->getParent(), InitField); + return getEntityForTemporaryLifetimeExtension(Entity->getParent(), + InitField); return {InitField, LK_MemInitializer}; case InitializedEntity::EK_Delegating: @@ -6308,61 +6311,46 @@ static LifetimeResult getEntityLifetime( case InitializedEntity::EK_BlockElement: case InitializedEntity::EK_LambdaToBlockConversionBlockElement: case InitializedEntity::EK_LambdaCapture: + case InitializedEntity::EK_Exception: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_ComplexElement: return {nullptr, LK_FullExpression}; - - case InitializedEntity::EK_Exception: - // FIXME: Can we diagnose lifetime problems with exceptions? - return {nullptr, LK_FullExpression}; } llvm_unreachable("unknown entity kind"); } namespace { -enum ReferenceKind { +enum ExtensionKind { /// Lifetime would be extended by a reference binding to a temporary. - RK_ReferenceBinding, + EK_ReferenceBinding, /// Lifetime would be extended by a std::initializer_list object binding to /// its backing array. - RK_StdInitializerList, + EK_StdInitializerList, }; - -/// A temporary or local variable. -using Local = llvm::PointerUnion<MaterializeTemporaryExpr*, ValueDecl*>; - -/// Expressions we stepped over when looking for the local state. Any steps -/// that would inhibit lifetime extension or take us out of subexpressions of -/// the initializer are included. -struct IndirectLocalPathEntry { - enum { - DefaultInit, - AddressOf, - } Kind; - Expr *E; -}; - -using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>; +using IndirectTemporaryPathEntry = + llvm::PointerUnion<CXXDefaultInitExpr *, ValueDecl *>; +using IndirectTemporaryPath = llvm::SmallVectorImpl<IndirectTemporaryPathEntry>; struct RevertToOldSizeRAII { - IndirectLocalPath &Path; + IndirectTemporaryPath &Path; unsigned OldSize = Path.size(); - RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {} + RevertToOldSizeRAII(IndirectTemporaryPath &Path) : Path(Path) {} ~RevertToOldSizeRAII() { Path.resize(OldSize); } }; } -template <typename LocalVisitor> -static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, - Expr *Init, LocalVisitor Visit, - bool RevisitSubinits); - -/// Visit the locals that would be reachable through a reference bound to the -/// glvalue expression \c Init. -template <typename LocalVisitor> -static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, - Expr *Init, ReferenceKind RK, - LocalVisitor Visit) { +template <typename TemporaryVisitor> +static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, + Expr *Init, + TemporaryVisitor Visit); + +/// Visit the temporaries whose lifetimes would be extended by binding a +/// reference to the glvalue expression \c Init. +template <typename TemporaryVisitor> +static void +visitTemporariesExtendedByReferenceBinding(IndirectTemporaryPath &Path, + Expr *Init, ExtensionKind EK, + TemporaryVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Walk past any constructs which we can lifetime-extend across. @@ -6394,7 +6382,7 @@ static void visitLocalsRetainedByReferen // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) { - Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); + Path.push_back(DIE); Init = DIE->getExpr(); if (auto *EWC = dyn_cast<ExprWithCleanups>(Init)) @@ -6403,36 +6391,25 @@ static void visitLocalsRetainedByReferen } while (Init != Old); if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Init)) { - if (Visit(Path, Local(MTE), RK)) - visitLocalsRetainedByInitializer(Path, MTE->GetTemporaryExpr(), Visit, - true); - } - - // If we find the name of a local non-reference parameter, we could have a - // lifetime problem. - if (auto *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) { - auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); - if (VD && VD->hasLocalStorage() && - !DRE->refersToEnclosingVariableOrCapture()) { - // FIXME: Recurse to the initializer of a local reference. - if (!VD->getType()->isReferenceType()) - Visit(Path, Local(VD), RK); - } + if (Visit(Path, MTE, EK)) + visitTemporariesExtendedByInitializer(Path, MTE->GetTemporaryExpr(), + Visit); } } -/// Visit the locals that would be reachable through an object initialized by -/// the prvalue expression \c Init. -template <typename LocalVisitor> -static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, - Expr *Init, LocalVisitor Visit, - bool RevisitSubinits) { +/// Visit the temporaries whose lifetimes would be extended by +/// lifetime-extending the object initialized by the prvalue expression \c +/// Init. +template <typename TemporaryVisitor> +static void visitTemporariesExtendedByInitializer(IndirectTemporaryPath &Path, + Expr *Init, + TemporaryVisitor Visit) { RevertToOldSizeRAII RAII(Path); // Step into CXXDefaultInitExprs so we can diagnose cases where a // constructor inherits one as an implicit mem-initializer. if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Init)) { - Path.push_back({IndirectLocalPathEntry::DefaultInit, DIE}); + Path.push_back(DIE); Init = DIE->getExpr(); if (auto *EWC = dyn_cast<ExprWithCleanups>(Init)) @@ -6449,24 +6426,17 @@ static void visitLocalsRetainedByInitial // initializing an initializer_list object from the array extends the // lifetime of the array exactly like binding a reference to a temporary. if (auto *ILE = dyn_cast<CXXStdInitializerListExpr>(Init)) - return visitLocalsRetainedByReferenceBinding(Path, ILE->getSubExpr(), - RK_StdInitializerList, Visit); + return visitTemporariesExtendedByReferenceBinding( + Path, ILE->getSubExpr(), EK_StdInitializerList, Visit); if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { - // We already visited the elements of this initializer list while - // performing the initialization. Don't visit them again unless we've - // changed the lifetime of the initialized entity. - if (!RevisitSubinits) - return; - if (ILE->isTransparent()) - return visitLocalsRetainedByInitializer(Path, ILE->getInit(0), Visit, - RevisitSubinits); + return visitTemporariesExtendedByInitializer(Path, ILE->getInit(0), + Visit); if (ILE->getType()->isArrayType()) { for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I) - visitLocalsRetainedByInitializer(Path, ILE->getInit(I), Visit, - RevisitSubinits); + visitTemporariesExtendedByInitializer(Path, ILE->getInit(I), Visit); return; } @@ -6478,8 +6448,8 @@ static void visitLocalsRetainedByInitial // bound to temporaries, those temporaries are also lifetime-extended. if (RD->isUnion() && ILE->getInitializedFieldInUnion() && ILE->getInitializedFieldInUnion()->getType()->isReferenceType()) - visitLocalsRetainedByReferenceBinding(Path, ILE->getInit(0), - RK_ReferenceBinding, Visit); + visitTemporariesExtendedByReferenceBinding(Path, ILE->getInit(0), + EK_ReferenceBinding, Visit); else { unsigned Index = 0; for (const auto *I : RD->fields()) { @@ -6489,38 +6459,25 @@ static void visitLocalsRetainedByInitial continue; Expr *SubInit = ILE->getInit(Index); if (I->getType()->isReferenceType()) - visitLocalsRetainedByReferenceBinding(Path, SubInit, - RK_ReferenceBinding, Visit); + visitTemporariesExtendedByReferenceBinding( + Path, SubInit, EK_ReferenceBinding, Visit); else // This might be either aggregate-initialization of a member or // initialization of a std::initializer_list object. Regardless, // we should recursively lifetime-extend that initializer. - visitLocalsRetainedByInitializer(Path, SubInit, Visit, - RevisitSubinits); + visitTemporariesExtendedByInitializer(Path, SubInit, Visit); ++Index; } } } - return; - } - - // If the initializer is the address of a local, we could have a lifetime - // problem. - if (auto *Op = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) { - if (Op->getOpcode() == UO_AddrOf) { - Path.push_back({IndirectLocalPathEntry::AddressOf, Op}); - Init = Op->getSubExpr(); - return visitLocalsRetainedByReferenceBinding(Path, Init, - RK_ReferenceBinding, Visit); - } } } /// Determine whether this is an indirect path to a temporary that we are /// supposed to lifetime-extend along (but don't). -static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { +static bool shouldLifetimeExtendThroughPath(const IndirectTemporaryPath &Path) { for (auto Elem : Path) { - if (Elem.Kind != IndirectLocalPathEntry::DefaultInit) + if (!Elem.is<CXXDefaultInitExpr*>()) return false; } return true; @@ -6528,7 +6485,7 @@ static bool shouldLifetimeExtendThroughP void Sema::checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init) { - LifetimeResult LR = getEntityLifetime(&Entity); + LifetimeResult LR = getEntityForTemporaryLifetimeExtension(&Entity); LifetimeKind LK = LR.getInt(); const InitializedEntity *ExtendingEntity = LR.getPointer(); @@ -6537,54 +6494,9 @@ void Sema::checkInitializerLifetime(cons if (LK == LK_FullExpression) return; - auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L, - ReferenceKind RK) -> bool { - // If we found a path to a local variable or similar, check whether the - // initialized object will outlive it. - if (auto *VD = L.dyn_cast<ValueDecl*>()) { - switch (LK) { - case LK_FullExpression: - llvm_unreachable("already handled this"); - - case LK_Extended: - break; - - case LK_MemInitializer: { - // Paths via a default initializer can only occur during error recovery - // (there's no other way that a default initializer can refer to a - // local). Don't produce a bogus warning on those cases. - if (std::any_of(Path.begin(), Path.end(), [](IndirectLocalPathEntry E) { - return E.Kind == IndirectLocalPathEntry::DefaultInit; - })) - break; - - if (auto *Member = - ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { - bool AddressTaken = - !Path.empty() && - Path.back().Kind == IndirectLocalPathEntry::AddressOf; - Diag(Init->getExprLoc(), - AddressTaken ? diag::warn_init_ptr_member_to_parameter_addr - : diag::warn_bind_ref_member_to_parameter) - << Member << VD << isa<ParmVarDecl>(VD) << Init->getSourceRange(); - Diag(Member->getLocation(), - diag::note_ref_or_ptr_member_declared_here) - << (unsigned)AddressTaken; - } - break; - } - - case LK_New: - break; - - case LK_Return: - // FIXME: Move -Wreturn-stack-address checks here. - return false; - } - return false; - } - - auto *MTE = L.get<MaterializeTemporaryExpr*>(); + auto TemporaryVisitor = [&](IndirectTemporaryPath &Path, + MaterializeTemporaryExpr *MTE, + ExtensionKind EK) -> bool { switch (LK) { case LK_FullExpression: llvm_unreachable("already handled this"); @@ -6608,11 +6520,11 @@ void Sema::checkInitializerLifetime(cons // would be to clone the initializer expression on each use that would // lifetime extend its temporaries. Diag(MTE->getExprLoc(), - RK == RK_ReferenceBinding + EK == EK_ReferenceBinding ? diag::warn_default_member_init_temporary_not_extended : diag::warn_default_member_init_init_list_not_extended); } else { - // FIXME: Warn on this. + llvm_unreachable("unexpected indirect temporary path"); } break; @@ -6620,20 +6532,18 @@ void Sema::checkInitializerLifetime(cons // Under C++ DR1696, if a mem-initializer (or a default member // initializer used by the absence of one) would lifetime-extend a // temporary, the program is ill-formed. - if (auto *ExtendingDecl = - ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) { + if (auto *ExtendingDecl = ExtendingEntity->getDecl()) { bool IsSubobjectMember = ExtendingEntity != &Entity; Diag(MTE->getExprLoc(), diag::err_bind_ref_member_to_temporary) << ExtendingDecl << Init->getSourceRange() << IsSubobjectMember - << RK; + << EK; // Don't bother adding a note pointing to the field if we're inside its // default member initializer; our primary diagnostic points to the // same place in that case. - if (Path.empty() || - Path.back().Kind != IndirectLocalPathEntry::DefaultInit) { + if (Path.empty() || !Path.back().is<CXXDefaultInitExpr*>()) { Diag(ExtendingDecl->getLocation(), diag::note_lifetime_extending_member_declared_here) - << RK << IsSubobjectMember; + << EK << IsSubobjectMember; } } else { // We have a mem-initializer but no particular field within it; this @@ -6647,7 +6557,7 @@ void Sema::checkInitializerLifetime(cons break; case LK_New: - if (RK == RK_ReferenceBinding) { + if (EK == EK_ReferenceBinding) { Diag(MTE->getExprLoc(), diag::warn_new_dangling_reference); } else { Diag(MTE->getExprLoc(), diag::warn_new_dangling_initializer_list) @@ -6663,14 +6573,9 @@ void Sema::checkInitializerLifetime(cons // FIXME: Model these as CodeSynthesisContexts to fix the note emission // order. for (auto Elem : llvm::reverse(Path)) { - switch (Elem.Kind) { - case IndirectLocalPathEntry::DefaultInit: - Diag(Elem.E->getExprLoc(), diag::note_in_default_member_initalizer_here) - << cast<CXXDefaultInitExpr>(Elem.E)->getField(); - break; - - case IndirectLocalPathEntry::AddressOf: - break; + if (auto *DIE = Elem.dyn_cast<CXXDefaultInitExpr*>()) { + Diag(DIE->getExprLoc(), diag::note_in_default_member_initalizer_here) + << DIE->getField(); } } @@ -6679,12 +6584,12 @@ void Sema::checkInitializerLifetime(cons return false; }; - llvm::SmallVector<IndirectLocalPathEntry, 8> Path; + llvm::SmallVector<IndirectTemporaryPathEntry, 8> Path; if (Init->isGLValue()) - visitLocalsRetainedByReferenceBinding(Path, Init, RK_ReferenceBinding, - TemporaryVisitor); + visitTemporariesExtendedByReferenceBinding(Path, Init, EK_ReferenceBinding, + TemporaryVisitor); else - visitLocalsRetainedByInitializer(Path, Init, TemporaryVisitor, false); + visitTemporariesExtendedByInitializer(Path, Init, TemporaryVisitor); } static void DiagnoseNarrowingInInitList(Sema &S, @@ -6948,7 +6853,6 @@ InitializationSequence::Perform(Sema &S, // Diagnose cases where we initialize a pointer to an array temporary, and the // pointer obviously outlives the temporary. - // FIXME: Fold this into checkInitializerLifetime. if (Args.size() == 1 && Args[0]->getType()->isArrayType() && Entity.getType()->isPointerType() && InitializedEntityOutlivesFullExpression(Entity)) { @@ -7111,6 +7015,11 @@ InitializationSequence::Perform(Sema &S, } } + // 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. + S.checkInitializerLifetime(Entity, CurInit.get()); + CheckForNullPointerDereference(S, CurInit.get()); break; @@ -7127,6 +7036,10 @@ InitializationSequence::Perform(Sema &S, Step->Type, CurInit.get(), Entity.getType()->isLValueReferenceType()); CurInit = MTE; + // Maybe lifetime-extend the temporary's subobjects to match the + // entity's lifetime. + S.checkInitializerLifetime(Entity, CurInit.get()); + // If we're extending this temporary to automatic storage duration -- we // need to register its cleanup during the full-expression's cleanups. if (MTE->getStorageDuration() == SD_Automatic && @@ -7577,6 +7490,10 @@ InitializationSequence::Perform(Sema &S, // Wrap it in a construction of a std::initializer_list<T>. CurInit = new (S.Context) CXXStdInitializerListExpr(Step->Type, MTE); + // Maybe lifetime-extend the array temporary's subobjects to match the + // entity's lifetime. + S.checkInitializerLifetime(Entity, CurInit.get()); + // Bind the result, in case the library has given initializer_list a // non-trivial destructor. if (shouldBindAsTemporary(Entity)) @@ -7695,11 +7612,6 @@ InitializationSequence::Perform(Sema &S, } } - // Check whether the initializer has a shorter lifetime than the initialized - // entity, and if not, either lifetime-extend or warn as appropriate. - if (auto *Init = CurInit.get()) - S.checkInitializerLifetime(Entity, Init); - // Diagnose non-fatal problems with the completed initialization. if (Entity.getKind() == InitializedEntity::EK_Member && cast<FieldDecl>(Entity.getDecl())->isBitField()) Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=337671&r1=337670&r2=337671&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Sun Jul 22 23:32:36 2018 @@ -235,10 +235,10 @@ void fVoidPointerTest2() { } class VoidPointerRRefTest1 { - void *&&vptrrref; // expected-note {{here}} + void *&&vptrrref; public: - VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void *&&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} + VoidPointerRRefTest1(void *vptr, char) : vptrrref(static_cast<void *&&>(vptr)) { // All good! } }; @@ -249,10 +249,10 @@ void fVoidPointerRRefTest1() { } class VoidPointerRRefTest2 { - void **&&vpptrrref; // expected-note {{here}} + void **&&vpptrrref; public: - VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void **&&>(vptr)) { // expected-warning {{binding reference member 'vpptrrref' to stack allocated parameter 'vptr'}} + VoidPointerRRefTest2(void **vptr, char) : vpptrrref(static_cast<void **&&>(vptr)) { // All good! } }; @@ -263,10 +263,10 @@ void fVoidPointerRRefTest2() { } class VoidPointerLRefTest { - void *&vptrrref; // expected-note {{here}} + void *&vptrrref; public: - VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void *&>(vptr)) { // expected-warning {{binding reference member 'vptrrref' to stack allocated parameter 'vptr'}} + VoidPointerLRefTest(void *vptr, char) : vptrrref(static_cast<void *&>(vptr)) { // All good! } }; Modified: cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=337671&r1=337670&r2=337671&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp (original) +++ cfe/trunk/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp Sun Jul 22 23:32:36 2018 @@ -72,18 +72,18 @@ std::initializer_list<int> thread_local // X86: @_ZN15partly_constant1kE = global i32 0, align 4 // X86: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 -// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal global {{.*}} zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal global [3 x {{.*}}] zeroinitializer, align 8 -// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal global [2 x i32] zeroinitializer, align 4 -// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// X86: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal global {{.*}} zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal global [3 x {{.*}}] zeroinitializer, align 8 +// X86: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// X86: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal global [2 x i32] zeroinitializer, align 4 +// X86: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // AMDGCN: @_ZN15partly_constant1kE = addrspace(1) global i32 0, align 4 // AMDGCN: @_ZN15partly_constant2ilE = addrspace(4) global {{.*}} null, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE_]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE0_]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 -// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE1_]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 -// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE2_]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 -// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE3_]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global {{.*}} zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [3 x {{.*}}] zeroinitializer, align 8 +// AMDGCN: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// AMDGCN: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) global [2 x i32] zeroinitializer, align 4 +// AMDGCN: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = internal addrspace(4) constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 // X86: @[[REFTMP1:.*]] = private constant [2 x i32] [i32 42, i32 43], align 4 // X86: @[[REFTMP2:.*]] = private constant [3 x %{{.*}}] [%{{.*}} { i32 1 }, %{{.*}} { i32 2 }, %{{.*}} { i32 3 }], align 4 @@ -375,7 +375,7 @@ namespace partly_constant { // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // CHECK: store i32* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_THIRD]]{{.*}}, i64 0, i64 0), // CHECK: i32** getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 0) - // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@[[PARTLY_CONSTANT_INNER]]{{.*}}, i64 0, i64 2, i32 1) + // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}, {{.*}}* {{.*}}@_ZGRN15partly_constant2ilE4_{{.*}}, i64 0, i64 2, i32 1) // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], // // Outer init list. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits