summaryrefslogtreecommitdiff
path: root/lib/AST/ExprClassification.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:18:08 +0000
commitbab175ec4b075c8076ba14c762900392533f6ee4 (patch)
tree01f4f29419a2cb10abe13c1e63cd2a66068b0137 /lib/AST/ExprClassification.cpp
parent8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff)
Notes
Diffstat (limited to 'lib/AST/ExprClassification.cpp')
-rw-r--r--lib/AST/ExprClassification.cpp21
1 files changed, 16 insertions, 5 deletions
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 89cc9bc18ef0..adb74b80b198 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -141,10 +141,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
- // In C++, they're prvalue temporaries.
+ // In C++, they're prvalue temporaries, except for file-scope arrays.
case Expr::CompoundLiteralExprClass:
- return Ctx.getLangOpts().CPlusPlus ? ClassifyTemporary(E->getType())
- : Cl::CL_LValue;
+ return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue;
// Expressions that are prvalues.
case Expr::CXXBoolLiteralExprClass:
@@ -186,6 +185,8 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::ObjCIndirectCopyRestoreExprClass:
case Expr::AtomicExprClass:
case Expr::CXXFoldExprClass:
+ case Expr::ArrayInitLoopExprClass:
+ case Expr::ArrayInitIndexExprClass:
case Expr::NoInitExprClass:
case Expr::DesignatedInitUpdateExprClass:
case Expr::CoyieldExprClass:
@@ -196,11 +197,20 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyInternal(Ctx,
cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
- // C++ [expr.sub]p1: The result is an lvalue of type "T".
- // However, subscripting vector types is more like member access.
+ // C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
+ // C++11 (DR1213): in the case of an array operand, the result is an lvalue
+ // if that operand is an lvalue and an xvalue otherwise.
+ // Subscripting vector types is more like member access.
case Expr::ArraySubscriptExprClass:
if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType())
return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase());
+ if (Lang.CPlusPlus11) {
+ // Step over the array-to-pointer decay if present, but not over the
+ // temporary materialization.
+ auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts();
+ if (Base->getType()->isArrayType())
+ return ClassifyInternal(Ctx, Base);
+ }
return Cl::CL_LValue;
// C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
@@ -429,6 +439,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
else
islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) ||
isa<IndirectFieldDecl>(D) ||
+ isa<BindingDecl>(D) ||
(Ctx.getLangOpts().CPlusPlus &&
(isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) ||
isa<FunctionTemplateDecl>(D)));