diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-05 07:49:14 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-05 07:49:14 +0000 |
commit | b3189a1802e493fd819b766c2051bda04f18617c (patch) | |
tree | f2f4135e179e717581ffdc0ad34d708376db62bd /clang/lib/AST/ExprClassification.cpp | |
parent | 215ff84b4082bea94dbf065d5fbac3cdd7f69516 (diff) | |
download | bcm5719-llvm-b3189a1802e493fd819b766c2051bda04f18617c.tar.gz bcm5719-llvm-b3189a1802e493fd819b766c2051bda04f18617c.zip |
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/AST/ExprClassification.cpp')
-rw-r--r-- | clang/lib/AST/ExprClassification.cpp | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 8388013d668..aa4651d6f43 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/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: @@ -196,11 +195,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 |