summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp38
1 files changed, 33 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 4415100ab45..5182e164538 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4376,6 +4376,16 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *LHSExp = Base;
Expr *RHSExp = Idx;
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_Ordinary;
+
+ // Per C++ core issue 1213, the result is an xvalue if either operand is
+ // a non-lvalue array, and an lvalue otherwise.
+ if (getLangOpts().CPlusPlus11 &&
+ ((LHSExp->getType()->isArrayType() && !LHSExp->isLValue()) ||
+ (RHSExp->getType()->isArrayType() && !RHSExp->isLValue())))
+ VK = VK_XValue;
+
// Perform default conversions.
if (!LHSExp->getType()->getAs<VectorType>()) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp);
@@ -4389,8 +4399,6 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
RHSExp = Result.get();
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
- ExprValueKind VK = VK_LValue;
- ExprObjectKind OK = OK_Ordinary;
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
@@ -5587,11 +5595,31 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
}
// In C, compound literals are l-values for some reason.
- ExprValueKind VK = getLangOpts().CPlusPlus ? VK_RValue : VK_LValue;
+ // For GCC compatibility, in C++, file-scope array compound literals with
+ // constant initializers are also l-values, and compound literals are
+ // otherwise prvalues.
+ //
+ // (GCC also treats C++ list-initialized file-scope array prvalues with
+ // constant initializers as l-values, but that's non-conforming, so we don't
+ // follow it there.)
+ //
+ // FIXME: It would be better to handle the lvalue cases as materializing and
+ // lifetime-extending a temporary object, but our materialized temporaries
+ // representation only supports lifetime extension from a variable, not "out
+ // of thin air".
+ // FIXME: For C++, we might want to instead lifetime-extend only if a pointer
+ // is bound to the result of applying array-to-pointer decay to the compound
+ // literal.
+ // FIXME: GCC supports compound literals of reference type, which should
+ // obviously have a value kind derived from the kind of reference involved.
+ ExprValueKind VK =
+ (getLangOpts().CPlusPlus && !(isFileScope && literalType->isArrayType()))
+ ? VK_RValue
+ : VK_LValue;
return MaybeBindToTemporary(
- new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
- VK, LiteralExpr, isFileScope));
+ new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+ VK, LiteralExpr, isFileScope));
}
ExprResult
OpenPOWER on IntegriCloud