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