diff options
Diffstat (limited to 'clang/lib/AST/ExprClassification.cpp')
| -rw-r--r-- | clang/lib/AST/ExprClassification.cpp | 35 |
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()) |
