r337744 - Do not try to perform lifetime-extension through conditional
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 23 14:21:24 PDT 2018
Author: rsmith
Date: Mon Jul 23 14:21:24 2018
New Revision: 337744
URL: http://llvm.org/viewvc/llvm-project?rev=337744&view=rev
Log:
Do not try to perform lifetime-extension through conditional
expressions.
CodeGen can't cope with that yet. Instead, produce a "not supported"
warning for now and don't extend lifetime.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/SemaCXX/conditional-expr.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337744&r1=337743&r2=337744&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jul 23 14:21:24 2018
@@ -7895,13 +7895,16 @@ def warn_new_dangling_initializer_list :
"the allocated initializer list}0 "
"will be destroyed at the end of the full-expression">,
InGroup<DanglingInitializerList>;
-def warn_default_member_init_temporary_not_extended : Warning<
- "sorry, lifetime extension of temporary created by aggregate initialization "
- "using default member initializer is not supported; lifetime of temporary "
+def warn_unsupported_temporary_not_extended : Warning<
+ "sorry, lifetime extension of temporary created "
+ "%select{by aggregate initialization using default member initializer|"
+ "within conditional expression}0 "
+ "is not supported; lifetime of temporary "
"will end at the end of the full-expression">, InGroup<DanglingField>;
-def warn_default_member_init_init_list_not_extended : Warning<
- "sorry, lifetime extension of backing array of initializer list "
- "created by aggregate initialization using default member initializer "
+def warn_unsupported_init_list_not_extended : Warning<
+ "sorry, lifetime extension of backing array of initializer list created "
+ "%select{by aggregate initialization using default member initializer|"
+ "within conditional expression}0 "
"is not supported; lifetime of backing array will end at the end of the "
"full-expression">, InGroup<DanglingInitializerList>;
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=337744&r1=337743&r2=337744&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Jul 23 14:21:24 2018
@@ -6362,6 +6362,7 @@ using Local = Expr*;
struct IndirectLocalPathEntry {
enum EntryKind {
DefaultInit,
+ Conditional,
AddressOf,
VarInit,
LValToRVal,
@@ -6497,6 +6498,7 @@ static void visitLocalsRetainedByReferen
case Stmt::ConditionalOperatorClass:
case Stmt::BinaryConditionalOperatorClass: {
+ Path.push_back({IndirectLocalPathEntry::Conditional, Init});
auto *C = cast<AbstractConditionalOperator>(Init);
if (!C->getTrueExpr()->getType()->isVoidType())
visitLocalsRetainedByReferenceBinding(Path, C->getTrueExpr(), RK, Visit);
@@ -6683,6 +6685,7 @@ static void visitLocalsRetainedByInitial
case Stmt::ConditionalOperatorClass:
case Stmt::BinaryConditionalOperatorClass: {
+ Path.push_back({IndirectLocalPathEntry::Conditional, Init});
auto *C = cast<AbstractConditionalOperator>(Init);
// In C++, we can have a throw-expression operand, which has 'void' type
// and isn't interesting from a lifetime perspective.
@@ -6714,12 +6717,33 @@ static void visitLocalsRetainedByInitial
/// supposed to lifetime-extend along (but don't).
static bool shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
for (auto Elem : Path) {
- if (Elem.Kind != IndirectLocalPathEntry::DefaultInit)
+ if (Elem.Kind != IndirectLocalPathEntry::DefaultInit &&
+ Elem.Kind != IndirectLocalPathEntry::Conditional)
return false;
}
return true;
}
+/// Find the range for the first interesting entry in the path at or after I.
+static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
+ Expr *E) {
+ for (unsigned N = Path.size(); I != N; ++I) {
+ switch (Path[I].Kind) {
+ case IndirectLocalPathEntry::AddressOf:
+ case IndirectLocalPathEntry::LValToRVal:
+ case IndirectLocalPathEntry::Conditional:
+ // These exist primarily to mark the path as not permitting or
+ // supporting lifetime extension.
+ break;
+
+ case IndirectLocalPathEntry::DefaultInit:
+ case IndirectLocalPathEntry::VarInit:
+ return Path[I].E->getSourceRange();
+ }
+ }
+ return E->getSourceRange();
+}
+
void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
Expr *Init) {
LifetimeResult LR = getEntityLifetime(&Entity);
@@ -6733,9 +6757,8 @@ void Sema::checkInitializerLifetime(cons
auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
ReferenceKind RK) -> bool {
- Expr *First = Path.empty() ? L : Path.front().E;
- SourceLocation DiagLoc = First->getLocStart();
- SourceRange DiagRange = First->getSourceRange();
+ SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
+ SourceLocation DiagLoc = DiagRange.getBegin();
switch (LK) {
case LK_FullExpression:
@@ -6761,13 +6784,14 @@ void Sema::checkInitializerLifetime(cons
// We're supposed to lifetime-extend the temporary along this path (per
// the resolution of DR1815), but we don't support that yet.
//
- // FIXME: Properly handle this situation. Perhaps the easiest approach
+ // FIXME: Properly handle these situations.
+ // For the default member initializer case, perhaps the easiest approach
// would be to clone the initializer expression on each use that would
// lifetime extend its temporaries.
- Diag(DiagLoc,
- RK == RK_ReferenceBinding
- ? diag::warn_default_member_init_temporary_not_extended
- : diag::warn_default_member_init_init_list_not_extended)
+ Diag(DiagLoc, RK == RK_ReferenceBinding
+ ? diag::warn_unsupported_temporary_not_extended
+ : diag::warn_unsupported_init_list_not_extended)
+ << (Path.front().Kind == IndirectLocalPathEntry::Conditional)
<< DiagRange;
} else {
// FIXME: Warn on this.
@@ -6871,31 +6895,26 @@ void Sema::checkInitializerLifetime(cons
for (unsigned I = 0; I != Path.size(); ++I) {
auto Elem = Path[I];
- // Highlight the range of the next step within this path element.
- SourceRange Range;
- if (I < Path.size() - 1)
- Range = Path[I + 1].E->getSourceRange();
- else
- Range = L->getSourceRange();
-
switch (Elem.Kind) {
case IndirectLocalPathEntry::AddressOf:
case IndirectLocalPathEntry::LValToRVal:
- // These exist primarily to mark the path as not permitting lifetime
- // extension.
+ case IndirectLocalPathEntry::Conditional:
+ // These exist primarily to mark the path as not permitting or
+ // supporting lifetime extension.
break;
case IndirectLocalPathEntry::DefaultInit: {
auto *FD = cast<FieldDecl>(Elem.D);
Diag(FD->getLocation(), diag::note_init_with_default_member_initalizer)
- << FD << Range;
+ << FD << nextPathEntryRange(Path, I + 1, L);
break;
}
case IndirectLocalPathEntry::VarInit:
const VarDecl *VD = cast<VarDecl>(Elem.D);
Diag(VD->getLocation(), diag::note_local_var_initializer)
- << VD->getType()->isReferenceType() << VD->getDeclName() << Range;
+ << VD->getType()->isReferenceType() << VD->getDeclName()
+ << nextPathEntryRange(Path, I + 1, L);
break;
}
}
Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=337744&r1=337743&r2=337744&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Mon Jul 23 14:21:24 2018
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -Wsign-conversion %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++17 -Wsign-conversion %s
// C++ rules for ?: are a lot stricter than C rules, and have to take into
// account more conversion options.
@@ -228,7 +229,7 @@ void test()
// be properly tested at runtime, though.
const Abstract &abstract1 = true ? static_cast<const Abstract&>(Derived1()) : Derived2(); // expected-error {{allocating an object of abstract class type 'const Abstract'}}
- const Abstract &abstract2 = true ? static_cast<const Abstract&>(Derived1()) : throw 3; // ok
+ const Abstract &abstract2 = true ? static_cast<const Abstract&>(Derived1()) : throw 3; // expected-warning-re {{sorry, lifetime extension {{.*}} not supported}}
}
namespace PR6595 {
@@ -393,3 +394,22 @@ Derived d;
typedef decltype(true ? static_cast<Base&&>(b) : static_cast<Derived&&>(d)) x;
typedef Base &&x;
}
+
+namespace lifetime_extension {
+ struct A {};
+ struct B : A { B(); ~B(); };
+ struct C : A { C(); ~C(); };
+
+ void f(bool b) {
+ // expected-warning at +1 2{{sorry, lifetime extension of temporary created within conditional expression is not supported}}
+ A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
+ }
+
+ struct D { A &&a; };
+ void f_indirect(bool b) {
+#if __cplusplus >= 201702L
+ // expected-warning at +2 2{{sorry, lifetime extension of temporary created within conditional expression is not supported}}
+#endif
+ D d = b ? D{B()} : D{C()};
+ }
+}
More information about the cfe-commits
mailing list