1bc5858b8SEugene Zelenko //===- ExprClassification.cpp - Expression AST Node Implementation --------===//
2f9463106SSebastian Redl //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f9463106SSebastian Redl //
7f9463106SSebastian Redl //===----------------------------------------------------------------------===//
8f9463106SSebastian Redl //
9f9463106SSebastian Redl // This file implements Expr::classify.
10f9463106SSebastian Redl //
11f9463106SSebastian Redl //===----------------------------------------------------------------------===//
12f9463106SSebastian Redl 
13f9463106SSebastian Redl #include "clang/AST/Expr.h"
143a02247dSChandler Carruth #include "clang/AST/ASTContext.h"
153a02247dSChandler Carruth #include "clang/AST/DeclCXX.h"
163a02247dSChandler Carruth #include "clang/AST/DeclObjC.h"
173a02247dSChandler Carruth #include "clang/AST/DeclTemplate.h"
18f9463106SSebastian Redl #include "clang/AST/ExprCXX.h"
19f9463106SSebastian Redl #include "clang/AST/ExprObjC.h"
203a02247dSChandler Carruth #include "llvm/Support/ErrorHandling.h"
21bc5858b8SEugene Zelenko 
22f9463106SSebastian Redl using namespace clang;
23f9463106SSebastian Redl 
24bc5858b8SEugene Zelenko using Cl = Expr::Classification;
25f9463106SSebastian Redl 
26f9463106SSebastian Redl static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E);
27f9463106SSebastian Redl static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D);
28f9463106SSebastian Redl static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T);
29f9463106SSebastian Redl static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E);
30f9463106SSebastian Redl static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E);
31f9463106SSebastian Redl static Cl::Kinds ClassifyConditional(ASTContext &Ctx,
32c07a0c7eSJohn McCall                                      const Expr *trueExpr,
33c07a0c7eSJohn McCall                                      const Expr *falseExpr);
34f9463106SSebastian Redl static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
35f9463106SSebastian Redl                                        Cl::Kinds Kind, SourceLocation &Loc);
36f9463106SSebastian Redl 
ClassifyImpl(ASTContext & Ctx,SourceLocation * Loc) const37f9463106SSebastian Redl Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
38f9463106SSebastian Redl   assert(!TR->isReferenceType() && "Expressions can't have reference type.");
39f9463106SSebastian Redl 
40f9463106SSebastian Redl   Cl::Kinds kind = ClassifyInternal(Ctx, this);
41f9463106SSebastian Redl   // C99 6.3.2.1: An lvalue is an expression with an object type or an
42f9463106SSebastian Redl   //   incomplete type other than void.
43bbafb8a7SDavid Blaikie   if (!Ctx.getLangOpts().CPlusPlus) {
44f9463106SSebastian Redl     // Thus, no functions.
45f9463106SSebastian Redl     if (TR->isFunctionType() || TR == Ctx.OverloadTy)
46f9463106SSebastian Redl       kind = Cl::CL_Function;
47f9463106SSebastian Redl     // No void either, but qualified void is OK because it is "other than void".
48133587f0SPeter Collingbourne     // Void "lvalues" are classified as addressable void values, which are void
49133587f0SPeter Collingbourne     // expressions whose address can be taken.
50133587f0SPeter Collingbourne     else if (TR->isVoidType() && !TR.hasQualifiers())
51133587f0SPeter Collingbourne       kind = (kind == Cl::CL_LValue ? Cl::CL_AddressableVoid : Cl::CL_Void);
52f9463106SSebastian Redl   }
53f9463106SSebastian Redl 
544bc41aeeSJohn McCall   // Enable this assertion for testing.
554bc41aeeSJohn McCall   switch (kind) {
564819b751SMatheus Izvekov   case Cl::CL_LValue:
574819b751SMatheus Izvekov     assert(isLValue());
584819b751SMatheus Izvekov     break;
594819b751SMatheus Izvekov   case Cl::CL_XValue:
604819b751SMatheus Izvekov     assert(isXValue());
614819b751SMatheus Izvekov     break;
624bc41aeeSJohn McCall   case Cl::CL_Function:
634bc41aeeSJohn McCall   case Cl::CL_Void:
64133587f0SPeter Collingbourne   case Cl::CL_AddressableVoid:
654bc41aeeSJohn McCall   case Cl::CL_DuplicateVectorComponents:
664bc41aeeSJohn McCall   case Cl::CL_MemberFunction:
674bc41aeeSJohn McCall   case Cl::CL_SubObjCPropertySetting:
684bc41aeeSJohn McCall   case Cl::CL_ClassTemporary:
69eb3cad53SRichard Smith   case Cl::CL_ArrayTemporary:
70071caefeSFariborz Jahanian   case Cl::CL_ObjCMessageRValue:
71aef5d8fdSMatheus Izvekov   case Cl::CL_PRValue:
724819b751SMatheus Izvekov     assert(isPRValue());
73aef5d8fdSMatheus Izvekov     break;
744bc41aeeSJohn McCall   }
754bc41aeeSJohn McCall 
76f9463106SSebastian Redl   Cl::ModifiableType modifiable = Cl::CM_Untested;
77f9463106SSebastian Redl   if (Loc)
78f9463106SSebastian Redl     modifiable = IsModifiable(Ctx, this, kind, *Loc);
79f9463106SSebastian Redl   return Classification(kind, modifiable);
80f9463106SSebastian Redl }
81f9463106SSebastian Redl 
82eb3cad53SRichard Smith /// Classify an expression which creates a temporary, based on its type.
ClassifyTemporary(QualType T)83eb3cad53SRichard Smith static Cl::Kinds ClassifyTemporary(QualType T) {
84eb3cad53SRichard Smith   if (T->isRecordType())
85eb3cad53SRichard Smith     return Cl::CL_ClassTemporary;
86eb3cad53SRichard Smith   if (T->isArrayType())
87eb3cad53SRichard Smith     return Cl::CL_ArrayTemporary;
88eb3cad53SRichard Smith 
89eb3cad53SRichard Smith   // No special classification: these don't behave differently from normal
90eb3cad53SRichard Smith   // prvalues.
91eb3cad53SRichard Smith   return Cl::CL_PRValue;
92eb3cad53SRichard Smith }
93eb3cad53SRichard Smith 
ClassifyExprValueKind(const LangOptions & Lang,const Expr * E,ExprValueKind Kind)944be2c369SRichard Smith static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang,
954be2c369SRichard Smith                                        const Expr *E,
964be2c369SRichard Smith                                        ExprValueKind Kind) {
974be2c369SRichard Smith   switch (Kind) {
98aef5d8fdSMatheus Izvekov   case VK_PRValue:
994be2c369SRichard Smith     return Lang.CPlusPlus ? ClassifyTemporary(E->getType()) : Cl::CL_PRValue;
1004be2c369SRichard Smith   case VK_LValue:
1014be2c369SRichard Smith     return Cl::CL_LValue;
1024be2c369SRichard Smith   case VK_XValue:
1034be2c369SRichard Smith     return Cl::CL_XValue;
1044be2c369SRichard Smith   }
1054be2c369SRichard Smith   llvm_unreachable("Invalid value category of implicit cast.");
1064be2c369SRichard Smith }
1074be2c369SRichard Smith 
ClassifyInternal(ASTContext & Ctx,const Expr * E)108f9463106SSebastian Redl static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
109f9463106SSebastian Redl   // This function takes the first stab at classifying expressions.
110bbafb8a7SDavid Blaikie   const LangOptions &Lang = Ctx.getLangOpts();
111f9463106SSebastian Redl 
112f9463106SSebastian Redl   switch (E->getStmtClass()) {
1134e442503SDouglas Gregor   case Stmt::NoStmtClass:
114bd066789SJohn McCall #define ABSTRACT_STMT(Kind)
1154e442503SDouglas Gregor #define STMT(Kind, Base) case Expr::Kind##Class:
1164e442503SDouglas Gregor #define EXPR(Kind, Base)
1174e442503SDouglas Gregor #include "clang/AST/StmtNodes.inc"
1184e442503SDouglas Gregor     llvm_unreachable("cannot classify a statement");
11929526f09SSebastian Redl 
12029526f09SSebastian Redl     // First come the expressions that are always lvalues, unconditionally.
121f9463106SSebastian Redl   case Expr::ObjCIsaExprClass:
122f9463106SSebastian Redl     // C++ [expr.prim.general]p1: A string literal is an lvalue.
123f9463106SSebastian Redl   case Expr::StringLiteralClass:
124f9463106SSebastian Redl     // @encode is equivalent to its string
125f9463106SSebastian Redl   case Expr::ObjCEncodeExprClass:
126f9463106SSebastian Redl     // __func__ and friends are too.
127f9463106SSebastian Redl   case Expr::PredefinedExprClass:
128f9463106SSebastian Redl     // Property references are lvalues
129e65b086eSTed Kremenek   case Expr::ObjCSubscriptRefExprClass:
130f9463106SSebastian Redl   case Expr::ObjCPropertyRefExprClass:
131f9463106SSebastian Redl     // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of...
132f9463106SSebastian Redl   case Expr::CXXTypeidExprClass:
133bab6df86SRichard Smith   case Expr::CXXUuidofExprClass:
134e1f49d54SKaelyn Takata     // Unresolved lookups and uncorrected typos get classified as lvalues.
135f9463106SSebastian Redl     // FIXME: Is this wise? Should they get their own kind?
136f9463106SSebastian Redl   case Expr::UnresolvedLookupExprClass:
137f9463106SSebastian Redl   case Expr::UnresolvedMemberExprClass:
138e1f49d54SKaelyn Takata   case Expr::TypoExprClass:
13920f25cb6SEric Fiselier   case Expr::DependentCoawaitExprClass:
1404e442503SDouglas Gregor   case Expr::CXXDependentScopeMemberExprClass:
1414e442503SDouglas Gregor   case Expr::DependentScopeDeclRefExprClass:
142f9463106SSebastian Redl     // ObjC instance variables are lvalues
143f9463106SSebastian Redl     // FIXME: ObjC++0x might have different rules
144f9463106SSebastian Redl   case Expr::ObjCIvarRefExprClass:
145b15fe3a5SRichard Smith   case Expr::FunctionParmPackExprClass:
1465e77d76cSJohn McCall   case Expr::MSPropertyRefExprClass:
147f763027fSAlexey Bataev   case Expr::MSPropertySubscriptExprClass:
1481a3320e4SAlexey Bataev   case Expr::OMPArraySectionExprClass:
1497ac9efb0SAlexey Bataev   case Expr::OMPArrayShapingExprClass:
15013a1504fSAlexey Bataev   case Expr::OMPIteratorExprClass:
151f9463106SSebastian Redl     return Cl::CL_LValue;
15229526f09SSebastian Redl 
1534e442503SDouglas Gregor     // C99 6.5.2.5p5 says that compound literals are lvalues.
154b3189a18SRichard Smith     // In C++, they're prvalue temporaries, except for file-scope arrays.
1554e442503SDouglas Gregor   case Expr::CompoundLiteralExprClass:
156b3189a18SRichard Smith     return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue;
1574e442503SDouglas Gregor 
1584e442503SDouglas Gregor     // Expressions that are prvalues.
1594e442503SDouglas Gregor   case Expr::CXXBoolLiteralExprClass:
1604e442503SDouglas Gregor   case Expr::CXXPseudoDestructorExprClass:
161e190dee7SPeter Collingbourne   case Expr::UnaryExprOrTypeTraitExprClass:
1624e442503SDouglas Gregor   case Expr::CXXNewExprClass:
1634e442503SDouglas Gregor   case Expr::CXXThisExprClass:
1644e442503SDouglas Gregor   case Expr::CXXNullPtrLiteralExprClass:
1654e442503SDouglas Gregor   case Expr::ImaginaryLiteralClass:
1664e442503SDouglas Gregor   case Expr::GNUNullExprClass:
1674e442503SDouglas Gregor   case Expr::OffsetOfExprClass:
1684e442503SDouglas Gregor   case Expr::CXXThrowExprClass:
1694e442503SDouglas Gregor   case Expr::ShuffleVectorExprClass:
170c4d7c82cSHal Finkel   case Expr::ConvertVectorExprClass:
1714e442503SDouglas Gregor   case Expr::IntegerLiteralClass:
172db01c3adSLeonard Chan   case Expr::FixedPointLiteralClass:
1734e442503SDouglas Gregor   case Expr::CharacterLiteralClass:
1744e442503SDouglas Gregor   case Expr::AddrLabelExprClass:
1754e442503SDouglas Gregor   case Expr::CXXDeleteExprClass:
1764e442503SDouglas Gregor   case Expr::ImplicitValueInitExprClass:
1774e442503SDouglas Gregor   case Expr::BlockExprClass:
1784e442503SDouglas Gregor   case Expr::FloatingLiteralClass:
1794e442503SDouglas Gregor   case Expr::CXXNoexceptExprClass:
1804e442503SDouglas Gregor   case Expr::CXXScalarValueInitExprClass:
18129c42f2aSDouglas Gregor   case Expr::TypeTraitExprClass:
1826242b6a6SJohn Wiegley   case Expr::ArrayTypeTraitExprClass:
183f9f6584eSJohn Wiegley   case Expr::ExpressionTraitExprClass:
1844e442503SDouglas Gregor   case Expr::ObjCSelectorExprClass:
1854e442503SDouglas Gregor   case Expr::ObjCProtocolExprClass:
1864e442503SDouglas Gregor   case Expr::ObjCStringLiteralClass:
1870caa3947SPatrick Beard   case Expr::ObjCBoxedExprClass:
188e65b086eSTed Kremenek   case Expr::ObjCArrayLiteralClass:
189e65b086eSTed Kremenek   case Expr::ObjCDictionaryLiteralClass:
190e65b086eSTed Kremenek   case Expr::ObjCBoolLiteralExprClass:
19129099dedSErik Pilkington   case Expr::ObjCAvailabilityCheckExprClass:
1924e442503SDouglas Gregor   case Expr::ParenListExprClass:
193820ba7baSDouglas Gregor   case Expr::SizeOfPackExprClass:
194cdbc539aSDouglas Gregor   case Expr::SubstNonTypeTemplateParmPackExprClass:
19555808c10STanya Lattner   case Expr::AsTypeExprClass:
19631168b07SJohn McCall   case Expr::ObjCIndirectCopyRestoreExprClass:
197df14b3a8SEli Friedman   case Expr::AtomicExprClass:
1980f0af19bSRichard Smith   case Expr::CXXFoldExprClass:
199410306bfSRichard Smith   case Expr::ArrayInitLoopExprClass:
200410306bfSRichard Smith   case Expr::ArrayInitIndexExprClass:
201cb77930dSYunzhong Gao   case Expr::NoInitExprClass:
202cb77930dSYunzhong Gao   case Expr::DesignatedInitUpdateExprClass:
203708afb56SEric Fiselier   case Expr::SourceLocExprClass:
2045d98ba60SSaar Raz   case Expr::ConceptSpecializationExprClass:
205a0f50d73SSaar Raz   case Expr::RequiresExprClass:
2064e442503SDouglas Gregor     return Cl::CL_PRValue;
207f9463106SSebastian Redl 
2087c44da27SBill Wendling   case Expr::ConstantExprClass:
2097c44da27SBill Wendling     return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr());
2107c44da27SBill Wendling 
211f9463106SSebastian Redl     // Next come the complicated cases.
2127c454bb8SJohn McCall   case Expr::SubstNonTypeTemplateParmExprClass:
2137c454bb8SJohn McCall     return ClassifyInternal(Ctx,
2147c454bb8SJohn McCall                  cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
215f9463106SSebastian Redl 
216b3189a18SRichard Smith     // C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
217b3189a18SRichard Smith     // C++11 (DR1213): in the case of an array operand, the result is an lvalue
218b3189a18SRichard Smith     //                 if that operand is an lvalue and an xvalue otherwise.
219b3189a18SRichard Smith     // Subscripting vector types is more like member access.
220f9463106SSebastian Redl   case Expr::ArraySubscriptExprClass:
221f9463106SSebastian Redl     if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType())
222f9463106SSebastian Redl       return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase());
223b3189a18SRichard Smith     if (Lang.CPlusPlus11) {
224b3189a18SRichard Smith       // Step over the array-to-pointer decay if present, but not over the
225b3189a18SRichard Smith       // temporary materialization.
226b3189a18SRichard Smith       auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts();
227b3189a18SRichard Smith       if (Base->getType()->isArrayType())
228b3189a18SRichard Smith         return ClassifyInternal(Ctx, Base);
229b3189a18SRichard Smith     }
230f9463106SSebastian Redl     return Cl::CL_LValue;
231f9463106SSebastian Redl 
2328f3f88d2SFlorian Hahn   // Subscripting matrix types behaves like member accesses.
2338f3f88d2SFlorian Hahn   case Expr::MatrixSubscriptExprClass:
2348f3f88d2SFlorian Hahn     return ClassifyInternal(Ctx, cast<MatrixSubscriptExpr>(E)->getBase());
2358f3f88d2SFlorian Hahn 
236f9463106SSebastian Redl     // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
237f9463106SSebastian Redl     //   function or variable and a prvalue otherwise.
238f9463106SSebastian Redl   case Expr::DeclRefExprClass:
2392979fe01SJohn McCall     if (E->getType() == Ctx.UnknownAnyTy)
2402979fe01SJohn McCall       return isa<FunctionDecl>(cast<DeclRefExpr>(E)->getDecl())
2412979fe01SJohn McCall                ? Cl::CL_PRValue : Cl::CL_LValue;
242f9463106SSebastian Redl     return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl());
243f9463106SSebastian Redl 
244f9463106SSebastian Redl     // Member access is complex.
245f9463106SSebastian Redl   case Expr::MemberExprClass:
246f9463106SSebastian Redl     return ClassifyMemberExpr(Ctx, cast<MemberExpr>(E));
247f9463106SSebastian Redl 
248f9463106SSebastian Redl   case Expr::UnaryOperatorClass:
249f9463106SSebastian Redl     switch (cast<UnaryOperator>(E)->getOpcode()) {
250f9463106SSebastian Redl       // C++ [expr.unary.op]p1: The unary * operator performs indirection:
251f9463106SSebastian Redl       //   [...] the result is an lvalue referring to the object or function
252f9463106SSebastian Redl       //   to which the expression points.
253e302792bSJohn McCall     case UO_Deref:
254f9463106SSebastian Redl       return Cl::CL_LValue;
255f9463106SSebastian Redl 
256f9463106SSebastian Redl       // GNU extensions, simply look through them.
257e302792bSJohn McCall     case UO_Extension:
258f9463106SSebastian Redl       return ClassifyInternal(Ctx, cast<UnaryOperator>(E)->getSubExpr());
259f9463106SSebastian Redl 
26007bb1966SJohn McCall     // Treat _Real and _Imag basically as if they were member
26107bb1966SJohn McCall     // expressions:  l-value only if the operand is a true l-value.
26207bb1966SJohn McCall     case UO_Real:
26307bb1966SJohn McCall     case UO_Imag: {
26407bb1966SJohn McCall       const Expr *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
26507bb1966SJohn McCall       Cl::Kinds K = ClassifyInternal(Ctx, Op);
26607bb1966SJohn McCall       if (K != Cl::CL_LValue) return K;
26707bb1966SJohn McCall 
268b7bd14faSJohn McCall       if (isa<ObjCPropertyRefExpr>(Op))
26907bb1966SJohn McCall         return Cl::CL_SubObjCPropertySetting;
27007bb1966SJohn McCall       return Cl::CL_LValue;
27107bb1966SJohn McCall     }
27207bb1966SJohn McCall 
273f9463106SSebastian Redl       // C++ [expr.pre.incr]p1: The result is the updated operand; it is an
274f9463106SSebastian Redl       //   lvalue, [...]
275f9463106SSebastian Redl       // Not so in C.
276e302792bSJohn McCall     case UO_PreInc:
277e302792bSJohn McCall     case UO_PreDec:
278f9463106SSebastian Redl       return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue;
279f9463106SSebastian Redl 
280f9463106SSebastian Redl     default:
281f9463106SSebastian Redl       return Cl::CL_PRValue;
282f9463106SSebastian Redl     }
283f9463106SSebastian Redl 
28496a5cfffSHaojian Wu   case Expr::RecoveryExprClass:
2858d69a216SJohn McCall   case Expr::OpaqueValueExprClass:
28629526f09SSebastian Redl     return ClassifyExprValueKind(Lang, E, E->getValueKind());
2878d69a216SJohn McCall 
288fe96e0b6SJohn McCall     // Pseudo-object expressions can produce l-values with reference magic.
289fe96e0b6SJohn McCall   case Expr::PseudoObjectExprClass:
290fe96e0b6SJohn McCall     return ClassifyExprValueKind(Lang, E,
291fe96e0b6SJohn McCall                                  cast<PseudoObjectExpr>(E)->getValueKind());
292fe96e0b6SJohn McCall 
293f9463106SSebastian Redl     // Implicit casts are lvalues if they're lvalue casts. Other than that, we
294f9463106SSebastian Redl     // only specifically record class temporaries.
295f9463106SSebastian Redl   case Expr::ImplicitCastExprClass:
29629526f09SSebastian Redl     return ClassifyExprValueKind(Lang, E, E->getValueKind());
297f9463106SSebastian Redl 
298f9463106SSebastian Redl     // C++ [expr.prim.general]p4: The presence of parentheses does not affect
299f9463106SSebastian Redl     //   whether the expression is an lvalue.
300f9463106SSebastian Redl   case Expr::ParenExprClass:
301f9463106SSebastian Redl     return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr());
302f9463106SSebastian Redl 
303e56f3932SBenjamin Kramer     // C11 6.5.1.1p4: [A generic selection] is an lvalue, a function designator,
30491147596SPeter Collingbourne     // or a void expression if its result expression is, respectively, an
30591147596SPeter Collingbourne     // lvalue, a function designator, or a void expression.
30691147596SPeter Collingbourne   case Expr::GenericSelectionExprClass:
30791147596SPeter Collingbourne     if (cast<GenericSelectionExpr>(E)->isResultDependent())
30891147596SPeter Collingbourne       return Cl::CL_PRValue;
30991147596SPeter Collingbourne     return ClassifyInternal(Ctx,cast<GenericSelectionExpr>(E)->getResultExpr());
31091147596SPeter Collingbourne 
311f9463106SSebastian Redl   case Expr::BinaryOperatorClass:
312f9463106SSebastian Redl   case Expr::CompoundAssignOperatorClass:
313f9463106SSebastian Redl     // C doesn't have any binary expressions that are lvalues.
314f9463106SSebastian Redl     if (Lang.CPlusPlus)
315f9463106SSebastian Redl       return ClassifyBinaryOp(Ctx, cast<BinaryOperator>(E));
316f9463106SSebastian Redl     return Cl::CL_PRValue;
317f9463106SSebastian Redl 
318f9463106SSebastian Redl   case Expr::CallExprClass:
319f9463106SSebastian Redl   case Expr::CXXOperatorCallExprClass:
320f9463106SSebastian Redl   case Expr::CXXMemberCallExprClass:
321c67fdd4eSRichard Smith   case Expr::UserDefinedLiteralClass:
32241f85462SPeter Collingbourne   case Expr::CUDAKernelCallExprClass:
323ced8bdf7SDavid Majnemer     return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType(Ctx));
324f9463106SSebastian Redl 
325778dc0f1SRichard Smith   case Expr::CXXRewrittenBinaryOperatorClass:
326778dc0f1SRichard Smith     return ClassifyInternal(
327778dc0f1SRichard Smith         Ctx, cast<CXXRewrittenBinaryOperator>(E)->getSemanticForm());
328778dc0f1SRichard Smith 
329f9463106SSebastian Redl     // __builtin_choose_expr is equivalent to the chosen expression.
330f9463106SSebastian Redl   case Expr::ChooseExprClass:
33175807f23SEli Friedman     return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr());
332f9463106SSebastian Redl 
333f9463106SSebastian Redl     // Extended vector element access is an lvalue unless there are duplicates
334f9463106SSebastian Redl     // in the shuffle expression.
335f9463106SSebastian Redl   case Expr::ExtVectorElementExprClass:
33666b9e9e9SEli Friedman     if (cast<ExtVectorElementExpr>(E)->containsDuplicateElements())
33766b9e9e9SEli Friedman       return Cl::CL_DuplicateVectorComponents;
33866b9e9e9SEli Friedman     if (cast<ExtVectorElementExpr>(E)->isArrow())
33966b9e9e9SEli Friedman       return Cl::CL_LValue;
34066b9e9e9SEli Friedman     return ClassifyInternal(Ctx, cast<ExtVectorElementExpr>(E)->getBase());
341f9463106SSebastian Redl 
342f9463106SSebastian Redl     // Simply look at the actual default argument.
343f9463106SSebastian Redl   case Expr::CXXDefaultArgExprClass:
344f9463106SSebastian Redl     return ClassifyInternal(Ctx, cast<CXXDefaultArgExpr>(E)->getExpr());
345f9463106SSebastian Redl 
346852c9db7SRichard Smith     // Same idea for default initializers.
347852c9db7SRichard Smith   case Expr::CXXDefaultInitExprClass:
348852c9db7SRichard Smith     return ClassifyInternal(Ctx, cast<CXXDefaultInitExpr>(E)->getExpr());
349852c9db7SRichard Smith 
350f9463106SSebastian Redl     // Same idea for temporary binding.
351f9463106SSebastian Redl   case Expr::CXXBindTemporaryExprClass:
352f9463106SSebastian Redl     return ClassifyInternal(Ctx, cast<CXXBindTemporaryExpr>(E)->getSubExpr());
353f9463106SSebastian Redl 
3545d413781SJohn McCall     // And the cleanups guard.
3555d413781SJohn McCall   case Expr::ExprWithCleanupsClass:
3565d413781SJohn McCall     return ClassifyInternal(Ctx, cast<ExprWithCleanups>(E)->getSubExpr());
357f9463106SSebastian Redl 
358f9463106SSebastian Redl     // Casts depend completely on the target type. All casts work the same.
359f9463106SSebastian Redl   case Expr::CStyleCastExprClass:
360f9463106SSebastian Redl   case Expr::CXXFunctionalCastExprClass:
361f9463106SSebastian Redl   case Expr::CXXStaticCastExprClass:
362f9463106SSebastian Redl   case Expr::CXXDynamicCastExprClass:
363f9463106SSebastian Redl   case Expr::CXXReinterpretCastExprClass:
364f9463106SSebastian Redl   case Expr::CXXConstCastExprClass:
365a6a237f2SAnastasia Stulova   case Expr::CXXAddrspaceCastExprClass:
36631168b07SJohn McCall   case Expr::ObjCBridgedCastExprClass:
367eee944e7SErik Pilkington   case Expr::BuiltinBitCastExprClass:
368f9463106SSebastian Redl     // Only in C++ can casts be interesting at all.
369f9463106SSebastian Redl     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
370f9463106SSebastian Redl     return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());
371f9463106SSebastian Redl 
3726336f296SDouglas Gregor   case Expr::CXXUnresolvedConstructExprClass:
3736336f296SDouglas Gregor     return ClassifyUnnamed(Ctx,
3746336f296SDouglas Gregor                       cast<CXXUnresolvedConstructExpr>(E)->getTypeAsWritten());
3756336f296SDouglas Gregor 
376c07a0c7eSJohn McCall   case Expr::BinaryConditionalOperatorClass: {
377c07a0c7eSJohn McCall     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
378bc5858b8SEugene Zelenko     const auto *co = cast<BinaryConditionalOperator>(E);
379c07a0c7eSJohn McCall     return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
380c07a0c7eSJohn McCall   }
381c07a0c7eSJohn McCall 
382c07a0c7eSJohn McCall   case Expr::ConditionalOperatorClass: {
383f9463106SSebastian Redl     // Once again, only C++ is interesting.
384f9463106SSebastian Redl     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
385bc5858b8SEugene Zelenko     const auto *co = cast<ConditionalOperator>(E);
386c07a0c7eSJohn McCall     return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
387c07a0c7eSJohn McCall   }
388f9463106SSebastian Redl 
389f9463106SSebastian Redl     // ObjC message sends are effectively function calls, if the target function
390f9463106SSebastian Redl     // is known.
391f9463106SSebastian Redl   case Expr::ObjCMessageExprClass:
392f9463106SSebastian Redl     if (const ObjCMethodDecl *Method =
393f9463106SSebastian Redl           cast<ObjCMessageExpr>(E)->getMethodDecl()) {
394314cc81bSAlp Toker       Cl::Kinds kind = ClassifyUnnamed(Ctx, Method->getReturnType());
395071caefeSFariborz Jahanian       return (kind == Cl::CL_PRValue) ? Cl::CL_ObjCMessageRValue : kind;
396f9463106SSebastian Redl     }
3974e442503SDouglas Gregor     return Cl::CL_PRValue;
398f9463106SSebastian Redl 
399f9463106SSebastian Redl     // Some C++ expressions are always class temporaries.
400f9463106SSebastian Redl   case Expr::CXXConstructExprClass:
4015179eb78SRichard Smith   case Expr::CXXInheritedCtorInitExprClass:
402f9463106SSebastian Redl   case Expr::CXXTemporaryObjectExprClass:
403e31e606fSDouglas Gregor   case Expr::LambdaExprClass:
404cc1b96d3SRichard Smith   case Expr::CXXStdInitializerListExprClass:
405f9463106SSebastian Redl     return Cl::CL_ClassTemporary;
406f9463106SSebastian Redl 
4074e442503SDouglas Gregor   case Expr::VAArgExprClass:
4084e442503SDouglas Gregor     return ClassifyUnnamed(Ctx, E->getType());
4094e442503SDouglas Gregor 
4104e442503SDouglas Gregor   case Expr::DesignatedInitExprClass:
4114e442503SDouglas Gregor     return ClassifyInternal(Ctx, cast<DesignatedInitExpr>(E)->getInit());
4124e442503SDouglas Gregor 
4134e442503SDouglas Gregor   case Expr::StmtExprClass: {
4144e442503SDouglas Gregor     const CompoundStmt *S = cast<StmtExpr>(E)->getSubStmt();
415bc5858b8SEugene Zelenko     if (const auto *LastExpr = dyn_cast_or_null<Expr>(S->body_back()))
416e572b068SDouglas Gregor       return ClassifyUnnamed(Ctx, LastExpr->getType());
417f9463106SSebastian Redl     return Cl::CL_PRValue;
418f9463106SSebastian Redl   }
4194e442503SDouglas Gregor 
420e8e9dd62SDouglas Gregor   case Expr::PackExpansionExprClass:
421e8e9dd62SDouglas Gregor     return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());
422fe31481fSDouglas Gregor 
423fe31481fSDouglas Gregor   case Expr::MaterializeTemporaryExprClass:
424d410c08eSDouglas Gregor     return cast<MaterializeTemporaryExpr>(E)->isBoundToLvalueReference()
425fe31481fSDouglas Gregor               ? Cl::CL_LValue
426fe31481fSDouglas Gregor               : Cl::CL_XValue;
42729526f09SSebastian Redl 
42829526f09SSebastian Redl   case Expr::InitListExprClass:
42929526f09SSebastian Redl     // An init list can be an lvalue if it is bound to a reference and
43029526f09SSebastian Redl     // contains only one element. In that case, we look at that element
43129526f09SSebastian Redl     // for an exact classification. Init list creation takes care of the
43229526f09SSebastian Redl     // value kind for us, so we only need to fine-tune.
433aef5d8fdSMatheus Izvekov     if (E->isPRValue())
43429526f09SSebastian Redl       return ClassifyExprValueKind(Lang, E, E->getValueKind());
43529526f09SSebastian Redl     assert(cast<InitListExpr>(E)->getNumInits() == 1 &&
43629526f09SSebastian Redl            "Only 1-element init lists can be glvalues.");
43729526f09SSebastian Redl     return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0));
4389f690bd8SRichard Smith 
4399f690bd8SRichard Smith   case Expr::CoawaitExprClass:
440cddaf872SEric Fiselier   case Expr::CoyieldExprClass:
441cddaf872SEric Fiselier     return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr());
442eba69b59SErich Keane   case Expr::SYCLUniqueStableNameExprClass:
443eba69b59SErich Keane     return Cl::CL_PRValue;
444eba69b59SErich Keane     break;
4454e442503SDouglas Gregor   }
4464e442503SDouglas Gregor 
4474e442503SDouglas Gregor   llvm_unreachable("unhandled expression kind in classification");
448f9463106SSebastian Redl }
449f9463106SSebastian Redl 
450f9463106SSebastian Redl /// ClassifyDecl - Return the classification of an expression referencing the
451f9463106SSebastian Redl /// given declaration.
ClassifyDecl(ASTContext & Ctx,const Decl * D)452f9463106SSebastian Redl static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
453f9463106SSebastian Redl   // C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
454f9463106SSebastian Redl   //   function, variable, or data member and a prvalue otherwise.
455f9463106SSebastian Redl   // In C, functions are not lvalues.
456f9463106SSebastian Redl   // In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
457f9463106SSebastian Redl   // lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
458f9463106SSebastian Redl   // special-case this.
4598d08b9b4SJohn McCall 
4608d08b9b4SJohn McCall   if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
4618d08b9b4SJohn McCall     return Cl::CL_MemberFunction;
4628d08b9b4SJohn McCall 
463f9463106SSebastian Redl   bool islvalue;
464bc5858b8SEugene Zelenko   if (const auto *NTTParm = dyn_cast<NonTypeTemplateParmDecl>(D))
465ba4768c9SRichard Smith     islvalue = NTTParm->getType()->isReferenceType() ||
466ba4768c9SRichard Smith                NTTParm->getType()->isRecordType();
467f9463106SSebastian Redl   else
468*d6148749SJames Y Knight     islvalue =
469*d6148749SJames Y Knight         isa<VarDecl, FieldDecl, IndirectFieldDecl, BindingDecl, MSGuidDecl,
470*d6148749SJames Y Knight             UnnamedGlobalConstantDecl, TemplateParamObjectDecl>(D) ||
471bbafb8a7SDavid Blaikie         (Ctx.getLangOpts().CPlusPlus &&
472*d6148749SJames Y Knight          (isa<FunctionDecl, MSPropertyDecl, FunctionTemplateDecl>(D)));
473f9463106SSebastian Redl 
474f9463106SSebastian Redl   return islvalue ? Cl::CL_LValue : Cl::CL_PRValue;
475f9463106SSebastian Redl }
476f9463106SSebastian Redl 
477f9463106SSebastian Redl /// ClassifyUnnamed - Return the classification of an expression yielding an
478f9463106SSebastian Redl /// unnamed value of the given type. This applies in particular to function
479f9463106SSebastian Redl /// calls and casts.
ClassifyUnnamed(ASTContext & Ctx,QualType T)480f9463106SSebastian Redl static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) {
481f9463106SSebastian Redl   // In C, function calls are always rvalues.
482bbafb8a7SDavid Blaikie   if (!Ctx.getLangOpts().CPlusPlus) return Cl::CL_PRValue;
483f9463106SSebastian Redl 
484f9463106SSebastian Redl   // C++ [expr.call]p10: A function call is an lvalue if the result type is an
485f9463106SSebastian Redl   //   lvalue reference type or an rvalue reference to function type, an xvalue
48622653bacSSebastian Redl   //   if the result type is an rvalue reference to object type, and a prvalue
487f9463106SSebastian Redl   //   otherwise.
488f9463106SSebastian Redl   if (T->isLValueReferenceType())
489f9463106SSebastian Redl     return Cl::CL_LValue;
490bc5858b8SEugene Zelenko   const auto *RV = T->getAs<RValueReferenceType>();
491f9463106SSebastian Redl   if (!RV) // Could still be a class temporary, though.
492eb3cad53SRichard Smith     return ClassifyTemporary(T);
493f9463106SSebastian Redl 
494f9463106SSebastian Redl   return RV->getPointeeType()->isFunctionType() ? Cl::CL_LValue : Cl::CL_XValue;
495f9463106SSebastian Redl }
496f9463106SSebastian Redl 
ClassifyMemberExpr(ASTContext & Ctx,const MemberExpr * E)497f9463106SSebastian Redl static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) {
4982979fe01SJohn McCall   if (E->getType() == Ctx.UnknownAnyTy)
4992979fe01SJohn McCall     return (isa<FunctionDecl>(E->getMemberDecl())
5002979fe01SJohn McCall               ? Cl::CL_PRValue : Cl::CL_LValue);
5012979fe01SJohn McCall 
502f9463106SSebastian Redl   // Handle C first, it's easier.
503bbafb8a7SDavid Blaikie   if (!Ctx.getLangOpts().CPlusPlus) {
504f9463106SSebastian Redl     // C99 6.5.2.3p3
505f9463106SSebastian Redl     // For dot access, the expression is an lvalue if the first part is. For
506f9463106SSebastian Redl     // arrow access, it always is an lvalue.
507f9463106SSebastian Redl     if (E->isArrow())
508f9463106SSebastian Redl       return Cl::CL_LValue;
509f9463106SSebastian Redl     // ObjC property accesses are not lvalues, but get special treatment.
51007bb1966SJohn McCall     Expr *Base = E->getBase()->IgnoreParens();
511b7bd14faSJohn McCall     if (isa<ObjCPropertyRefExpr>(Base))
512f9463106SSebastian Redl       return Cl::CL_SubObjCPropertySetting;
513f9463106SSebastian Redl     return ClassifyInternal(Ctx, Base);
514f9463106SSebastian Redl   }
515f9463106SSebastian Redl 
516f9463106SSebastian Redl   NamedDecl *Member = E->getMemberDecl();
517f9463106SSebastian Redl   // C++ [expr.ref]p3: E1->E2 is converted to the equivalent form (*(E1)).E2.
518f9463106SSebastian Redl   // C++ [expr.ref]p4: If E2 is declared to have type "reference to T", then
519f9463106SSebastian Redl   //   E1.E2 is an lvalue.
520bc5858b8SEugene Zelenko   if (const auto *Value = dyn_cast<ValueDecl>(Member))
521f9463106SSebastian Redl     if (Value->getType()->isReferenceType())
522f9463106SSebastian Redl       return Cl::CL_LValue;
523f9463106SSebastian Redl 
524f9463106SSebastian Redl   //   Otherwise, one of the following rules applies.
525f9463106SSebastian Redl   //   -- If E2 is a static member [...] then E1.E2 is an lvalue.
526f9463106SSebastian Redl   if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord())
527f9463106SSebastian Redl     return Cl::CL_LValue;
528f9463106SSebastian Redl 
529f9463106SSebastian Redl   //   -- If E2 is a non-static data member [...]. If E1 is an lvalue, then
530f9463106SSebastian Redl   //      E1.E2 is an lvalue; if E1 is an xvalue, then E1.E2 is an xvalue;
531f9463106SSebastian Redl   //      otherwise, it is a prvalue.
532f9463106SSebastian Redl   if (isa<FieldDecl>(Member)) {
533f9463106SSebastian Redl     // *E1 is an lvalue
534f9463106SSebastian Redl     if (E->isArrow())
535f9463106SSebastian Redl       return Cl::CL_LValue;
5364bc41aeeSJohn McCall     Expr *Base = E->getBase()->IgnoreParenImpCasts();
537b7bd14faSJohn McCall     if (isa<ObjCPropertyRefExpr>(Base))
5384bc41aeeSJohn McCall       return Cl::CL_SubObjCPropertySetting;
539f9463106SSebastian Redl     return ClassifyInternal(Ctx, E->getBase());
540f9463106SSebastian Redl   }
541f9463106SSebastian Redl 
542f9463106SSebastian Redl   //   -- If E2 is a [...] member function, [...]
543f9463106SSebastian Redl   //      -- If it refers to a static member function [...], then E1.E2 is an
544f9463106SSebastian Redl   //         lvalue; [...]
545f9463106SSebastian Redl   //      -- Otherwise [...] E1.E2 is a prvalue.
546bc5858b8SEugene Zelenko   if (const auto *Method = dyn_cast<CXXMethodDecl>(Member))
547f9463106SSebastian Redl     return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction;
548f9463106SSebastian Redl 
549f9463106SSebastian Redl   //   -- If E2 is a member enumerator [...], the expression E1.E2 is a prvalue.
550f9463106SSebastian Redl   // So is everything else we haven't handled yet.
551f9463106SSebastian Redl   return Cl::CL_PRValue;
552f9463106SSebastian Redl }
553f9463106SSebastian Redl 
ClassifyBinaryOp(ASTContext & Ctx,const BinaryOperator * E)554f9463106SSebastian Redl static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
555bbafb8a7SDavid Blaikie   assert(Ctx.getLangOpts().CPlusPlus &&
556f9463106SSebastian Redl          "This is only relevant for C++.");
557f9463106SSebastian Redl   // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand.
55834376a68SJohn McCall   // Except we override this for writes to ObjC properties.
559f9463106SSebastian Redl   if (E->isAssignmentOp())
56034376a68SJohn McCall     return (E->getLHS()->getObjectKind() == OK_ObjCProperty
56134376a68SJohn McCall               ? Cl::CL_PRValue : Cl::CL_LValue);
562f9463106SSebastian Redl 
563f9463106SSebastian Redl   // C++ [expr.comma]p1: the result is of the same value category as its right
564f9463106SSebastian Redl   //   operand, [...].
565e302792bSJohn McCall   if (E->getOpcode() == BO_Comma)
566f9463106SSebastian Redl     return ClassifyInternal(Ctx, E->getRHS());
567f9463106SSebastian Redl 
568f9463106SSebastian Redl   // C++ [expr.mptr.oper]p6: The result of a .* expression whose second operand
569f9463106SSebastian Redl   //   is a pointer to a data member is of the same value category as its first
570f9463106SSebastian Redl   //   operand.
571e302792bSJohn McCall   if (E->getOpcode() == BO_PtrMemD)
572e314e27cSJohn McCall     return (E->getType()->isFunctionType() ||
573e314e27cSJohn McCall             E->hasPlaceholderType(BuiltinType::BoundMember))
574b7c36f6cSDouglas Gregor              ? Cl::CL_MemberFunction
575b7c36f6cSDouglas Gregor              : ClassifyInternal(Ctx, E->getLHS());
576f9463106SSebastian Redl 
577f9463106SSebastian Redl   // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its
578f9463106SSebastian Redl   //   second operand is a pointer to data member and a prvalue otherwise.
579e302792bSJohn McCall   if (E->getOpcode() == BO_PtrMemI)
580e314e27cSJohn McCall     return (E->getType()->isFunctionType() ||
581e314e27cSJohn McCall             E->hasPlaceholderType(BuiltinType::BoundMember))
582b7c36f6cSDouglas Gregor              ? Cl::CL_MemberFunction
583b7c36f6cSDouglas Gregor              : Cl::CL_LValue;
584f9463106SSebastian Redl 
585f9463106SSebastian Redl   // All other binary operations are prvalues.
586f9463106SSebastian Redl   return Cl::CL_PRValue;
587f9463106SSebastian Redl }
588f9463106SSebastian Redl 
ClassifyConditional(ASTContext & Ctx,const Expr * True,const Expr * False)589c07a0c7eSJohn McCall static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True,
590c07a0c7eSJohn McCall                                      const Expr *False) {
591bbafb8a7SDavid Blaikie   assert(Ctx.getLangOpts().CPlusPlus &&
592f9463106SSebastian Redl          "This is only relevant for C++.");
593f9463106SSebastian Redl 
594f9463106SSebastian Redl   // C++ [expr.cond]p2
5956a6a4bbdSRichard Smith   //   If either the second or the third operand has type (cv) void,
5966a6a4bbdSRichard Smith   //   one of the following shall hold:
5976a6a4bbdSRichard Smith   if (True->getType()->isVoidType() || False->getType()->isVoidType()) {
5986a6a4bbdSRichard Smith     // The second or the third operand (but not both) is a (possibly
5996a6a4bbdSRichard Smith     // parenthesized) throw-expression; the result is of the [...] value
6006a6a4bbdSRichard Smith     // category of the other.
6016a6a4bbdSRichard Smith     bool TrueIsThrow = isa<CXXThrowExpr>(True->IgnoreParenImpCasts());
6026a6a4bbdSRichard Smith     bool FalseIsThrow = isa<CXXThrowExpr>(False->IgnoreParenImpCasts());
60336250ad6SCraig Topper     if (const Expr *NonThrow = TrueIsThrow ? (FalseIsThrow ? nullptr : False)
60436250ad6SCraig Topper                                            : (FalseIsThrow ? True : nullptr))
6056a6a4bbdSRichard Smith       return ClassifyInternal(Ctx, NonThrow);
6066a6a4bbdSRichard Smith 
6076a6a4bbdSRichard Smith     //   [Otherwise] the result [...] is a prvalue.
608f9463106SSebastian Redl     return Cl::CL_PRValue;
6096a6a4bbdSRichard Smith   }
610f9463106SSebastian Redl 
611f9463106SSebastian Redl   // Note that at this point, we have already performed all conversions
612f9463106SSebastian Redl   // according to [expr.cond]p3.
613f9463106SSebastian Redl   // C++ [expr.cond]p4: If the second and third operands are glvalues of the
614f9463106SSebastian Redl   //   same value category [...], the result is of that [...] value category.
615f9463106SSebastian Redl   // C++ [expr.cond]p5: Otherwise, the result is a prvalue.
616f9463106SSebastian Redl   Cl::Kinds LCl = ClassifyInternal(Ctx, True),
617f9463106SSebastian Redl             RCl = ClassifyInternal(Ctx, False);
618f9463106SSebastian Redl   return LCl == RCl ? LCl : Cl::CL_PRValue;
619f9463106SSebastian Redl }
620f9463106SSebastian Redl 
IsModifiable(ASTContext & Ctx,const Expr * E,Cl::Kinds Kind,SourceLocation & Loc)621f9463106SSebastian Redl static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
622f9463106SSebastian Redl                                        Cl::Kinds Kind, SourceLocation &Loc) {
623f9463106SSebastian Redl   // As a general rule, we only care about lvalues. But there are some rvalues
624f9463106SSebastian Redl   // for which we want to generate special results.
625f9463106SSebastian Redl   if (Kind == Cl::CL_PRValue) {
626f9463106SSebastian Redl     // For the sake of better diagnostics, we want to specifically recognize
627f9463106SSebastian Redl     // use of the GCC cast-as-lvalue extension.
628bc5858b8SEugene Zelenko     if (const auto *CE = dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) {
62934376a68SJohn McCall       if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) {
63034376a68SJohn McCall         Loc = CE->getExprLoc();
631f9463106SSebastian Redl         return Cl::CM_LValueCast;
632f9463106SSebastian Redl       }
633f9463106SSebastian Redl     }
634f9463106SSebastian Redl   }
635f9463106SSebastian Redl   if (Kind != Cl::CL_LValue)
636f9463106SSebastian Redl     return Cl::CM_RValue;
637f9463106SSebastian Redl 
638f9463106SSebastian Redl   // This is the lvalue case.
639f9463106SSebastian Redl   // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6)
640bbafb8a7SDavid Blaikie   if (Ctx.getLangOpts().CPlusPlus && E->getType()->isFunctionType())
641f9463106SSebastian Redl     return Cl::CM_Function;
642f9463106SSebastian Redl 
643f9463106SSebastian Redl   // Assignment to a property in ObjC is an implicit setter access. But a
644f9463106SSebastian Redl   // setter might not exist.
645bc5858b8SEugene Zelenko   if (const auto *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) {
64636250ad6SCraig Topper     if (Expr->isImplicitProperty() &&
64736250ad6SCraig Topper         Expr->getImplicitPropertySetter() == nullptr)
648f9463106SSebastian Redl       return Cl::CM_NoSetterProperty;
649f9463106SSebastian Redl   }
650f9463106SSebastian Redl 
651f9463106SSebastian Redl   CanQualType CT = Ctx.getCanonicalType(E->getType());
652f9463106SSebastian Redl   // Const stuff is obviously not modifiable.
6535fa2ef44SJohn McCall   if (CT.isConstQualified())
654f9463106SSebastian Redl     return Cl::CM_ConstQualified;
655b34ec829SYaxun Liu   if (Ctx.getLangOpts().OpenCL &&
656b34ec829SYaxun Liu       CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant)
657a7bd4582SRichard Smith     return Cl::CM_ConstAddrSpace;
65860226ea0SEli Friedman 
659f9463106SSebastian Redl   // Arrays are not modifiable, only their elements are.
660f9463106SSebastian Redl   if (CT->isArrayType())
661f9463106SSebastian Redl     return Cl::CM_ArrayType;
662f9463106SSebastian Redl   // Incomplete types are not modifiable.
663f9463106SSebastian Redl   if (CT->isIncompleteType())
664f9463106SSebastian Redl     return Cl::CM_IncompleteType;
665f9463106SSebastian Redl 
666f9463106SSebastian Redl   // Records with any const fields (recursively) are not modifiable.
66799b98f07SDavid Majnemer   if (const RecordType *R = CT->getAs<RecordType>())
668f9463106SSebastian Redl     if (R->hasConstFields())
6699cf0e12aSBjorn Pettersson       return Cl::CM_ConstQualifiedField;
670f9463106SSebastian Redl 
671f9463106SSebastian Redl   return Cl::CM_Modifiable;
672f9463106SSebastian Redl }
673f9463106SSebastian Redl 
ClassifyLValue(ASTContext & Ctx) const674086a464eSJohn McCall Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const {
675f9463106SSebastian Redl   Classification VC = Classify(Ctx);
676f9463106SSebastian Redl   switch (VC.getKind()) {
677f9463106SSebastian Redl   case Cl::CL_LValue: return LV_Valid;
678f9463106SSebastian Redl   case Cl::CL_XValue: return LV_InvalidExpression;
679f9463106SSebastian Redl   case Cl::CL_Function: return LV_NotObjectType;
680133587f0SPeter Collingbourne   case Cl::CL_Void: return LV_InvalidExpression;
681133587f0SPeter Collingbourne   case Cl::CL_AddressableVoid: return LV_IncompleteVoidType;
682f9463106SSebastian Redl   case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents;
683f9463106SSebastian Redl   case Cl::CL_MemberFunction: return LV_MemberFunction;
684f9463106SSebastian Redl   case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting;
685f9463106SSebastian Redl   case Cl::CL_ClassTemporary: return LV_ClassTemporary;
686eb3cad53SRichard Smith   case Cl::CL_ArrayTemporary: return LV_ArrayTemporary;
687071caefeSFariborz Jahanian   case Cl::CL_ObjCMessageRValue: return LV_InvalidMessageExpression;
688f9463106SSebastian Redl   case Cl::CL_PRValue: return LV_InvalidExpression;
689f9463106SSebastian Redl   }
6908337ba63SChandler Carruth   llvm_unreachable("Unhandled kind");
691f9463106SSebastian Redl }
692f9463106SSebastian Redl 
693f9463106SSebastian Redl Expr::isModifiableLvalueResult
isModifiableLvalue(ASTContext & Ctx,SourceLocation * Loc) const694f9463106SSebastian Redl Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
695f9463106SSebastian Redl   SourceLocation dummy;
696f9463106SSebastian Redl   Classification VC = ClassifyModifiable(Ctx, Loc ? *Loc : dummy);
697f9463106SSebastian Redl   switch (VC.getKind()) {
698f9463106SSebastian Redl   case Cl::CL_LValue: break;
699f9463106SSebastian Redl   case Cl::CL_XValue: return MLV_InvalidExpression;
700f9463106SSebastian Redl   case Cl::CL_Function: return MLV_NotObjectType;
701133587f0SPeter Collingbourne   case Cl::CL_Void: return MLV_InvalidExpression;
702133587f0SPeter Collingbourne   case Cl::CL_AddressableVoid: return MLV_IncompleteVoidType;
703f9463106SSebastian Redl   case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
704f9463106SSebastian Redl   case Cl::CL_MemberFunction: return MLV_MemberFunction;
705f9463106SSebastian Redl   case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
706f9463106SSebastian Redl   case Cl::CL_ClassTemporary: return MLV_ClassTemporary;
707eb3cad53SRichard Smith   case Cl::CL_ArrayTemporary: return MLV_ArrayTemporary;
708071caefeSFariborz Jahanian   case Cl::CL_ObjCMessageRValue: return MLV_InvalidMessageExpression;
709f9463106SSebastian Redl   case Cl::CL_PRValue:
710f9463106SSebastian Redl     return VC.getModifiable() == Cl::CM_LValueCast ?
711f9463106SSebastian Redl       MLV_LValueCast : MLV_InvalidExpression;
712f9463106SSebastian Redl   }
713f9463106SSebastian Redl   assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind");
714f9463106SSebastian Redl   switch (VC.getModifiable()) {
7158337ba63SChandler Carruth   case Cl::CM_Untested: llvm_unreachable("Did not test modifiability");
716f9463106SSebastian Redl   case Cl::CM_Modifiable: return MLV_Valid;
7178337ba63SChandler Carruth   case Cl::CM_RValue: llvm_unreachable("CM_RValue and CL_LValue don't match");
718f9463106SSebastian Redl   case Cl::CM_Function: return MLV_NotObjectType;
719f9463106SSebastian Redl   case Cl::CM_LValueCast:
7208337ba63SChandler Carruth     llvm_unreachable("CM_LValueCast and CL_LValue don't match");
721f9463106SSebastian Redl   case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
722f9463106SSebastian Redl   case Cl::CM_ConstQualified: return MLV_ConstQualified;
7239cf0e12aSBjorn Pettersson   case Cl::CM_ConstQualifiedField: return MLV_ConstQualifiedField;
724a7bd4582SRichard Smith   case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace;
725f9463106SSebastian Redl   case Cl::CM_ArrayType: return MLV_ArrayType;
726f9463106SSebastian Redl   case Cl::CM_IncompleteType: return MLV_IncompleteType;
727f9463106SSebastian Redl   }
7288337ba63SChandler Carruth   llvm_unreachable("Unhandled modifiable type");
729f9463106SSebastian Redl }
730