summaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprClassification.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ExprClassification.cpp')
-rw-r--r--clang/lib/AST/ExprClassification.cpp35
1 files changed, 25 insertions, 10 deletions
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 6482cb6d39ac..1f1b8abc09b9 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -119,12 +119,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
// First come the expressions that are always lvalues, unconditionally.
case Expr::ObjCIsaExprClass:
- // C++ [expr.prim.general]p1: A string literal is an lvalue.
- case Expr::StringLiteralClass:
- // @encode is equivalent to its string
- case Expr::ObjCEncodeExprClass:
- // __func__ and friends are too.
- case Expr::PredefinedExprClass:
// Property references are lvalues
case Expr::ObjCSubscriptRefExprClass:
case Expr::ObjCPropertyRefExprClass:
@@ -150,6 +144,26 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::OMPIteratorExprClass:
return Cl::CL_LValue;
+ // C++ [expr.prim.general]p1: A string literal is an lvalue.
+ case Expr::StringLiteralClass:
+ // @encode is equivalent to its string
+ case Expr::ObjCEncodeExprClass:
+ // Except we special case them as prvalues when they are used to
+ // initialize a char array.
+ return E->isLValue() ? Cl::CL_LValue : Cl::CL_PRValue;
+
+ // __func__ and friends are too.
+ // The char array initialization special case also applies
+ // when they are transparent.
+ case Expr::PredefinedExprClass: {
+ auto *PE = cast<PredefinedExpr>(E);
+ const StringLiteral *SL = PE->getFunctionName();
+ if (PE->isTransparent())
+ return SL ? ClassifyInternal(Ctx, SL) : Cl::CL_LValue;
+ assert(!SL || SL->isLValue());
+ return Cl::CL_LValue;
+ }
+
// C99 6.5.2.5p5 says that compound literals are lvalues.
// In C++, they're prvalue temporaries, except for file-scope arrays.
case Expr::CompoundLiteralExprClass:
@@ -471,12 +485,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
/// ClassifyDecl - Return the classification of an expression referencing the
/// given declaration.
static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
- // C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
- // function, variable, or data member and a prvalue otherwise.
+ // C++ [expr.prim.id.unqual]p3: The result is an lvalue if the entity is a
+ // function, variable, or data member, or a template parameter object and a
+ // prvalue otherwise.
// In C, functions are not lvalues.
// In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
- // lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
- // special-case this.
+ // lvalue unless it's a reference type or a class type (C++ [temp.param]p8),
+ // so we need to special-case this.
if (const auto *M = dyn_cast<CXXMethodDecl>(D)) {
if (M->isImplicitObjectMemberFunction())