aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/Sema.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-12-05 07:49:14 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-12-05 07:49:14 +0000
commitb3189a1802e493fd819b766c2051bda04f18617c (patch)
treef2f4135e179e717581ffdc0ad34d708376db62bd /clang/lib/Sema/Sema.cpp
parent215ff84b4082bea94dbf065d5fbac3cdd7f69516 (diff)
downloadllvm-b3189a1802e493fd819b766c2051bda04f18617c.zip
llvm-b3189a1802e493fd819b766c2051bda04f18617c.tar.gz
llvm-b3189a1802e493fd819b766c2051bda04f18617c.tar.bz2
DR1213: element access on an array xvalue or prvalue produces an xvalue. In the
latter case, a temporary array object is materialized, and can be lifetime-extended by binding a reference to the member access. Likewise, in an array-to-pointer decay, an rvalue array is materialized before being converted into a pointer. This caused IR generation to stop treating file-scope array compound literals as having static storage duration in some cases in C++; that has been rectified by modeling such a compound literal as an lvalue. This also improves clang's compatibility with GCC for those cases. llvm-svn: 288654
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r--clang/lib/Sema/Sema.cpp12
1 files changed, 12 insertions, 0 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index fd1a94e..fc76a86 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -390,6 +390,18 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
if (ExprTy == TypeTy)
return E;
+ // C++1z [conv.array]: The temporary materialization conversion is applied.
+ // We also use this to fuel C++ DR1213, which applies to C++11 onwards.
+ if (Kind == CK_ArrayToPointerDecay && getLangOpts().CPlusPlus &&
+ E->getValueKind() == VK_RValue) {
+ // The temporary is an lvalue in C++98 and an xvalue otherwise.
+ ExprResult Materialized = CreateMaterializeTemporaryExpr(
+ E->getType(), E, !getLangOpts().CPlusPlus11);
+ if (Materialized.isInvalid())
+ return ExprError();
+ E = Materialized.get();
+ }
+
if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
ImpCast->setType(Ty);