xref: /openbsd-src/gnu/llvm/clang/lib/AST/ExprClassification.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- ExprClassification.cpp - Expression AST Node Implementation --------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements Expr::classify.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #include "clang/AST/Expr.h"
14e5dd7070Spatrick #include "clang/AST/ASTContext.h"
15e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
16e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
17e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
18e5dd7070Spatrick #include "clang/AST/ExprCXX.h"
19e5dd7070Spatrick #include "clang/AST/ExprObjC.h"
20e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
21e5dd7070Spatrick 
22e5dd7070Spatrick using namespace clang;
23e5dd7070Spatrick 
24e5dd7070Spatrick using Cl = Expr::Classification;
25e5dd7070Spatrick 
26e5dd7070Spatrick static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E);
27e5dd7070Spatrick static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D);
28e5dd7070Spatrick static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T);
29e5dd7070Spatrick static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E);
30e5dd7070Spatrick static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E);
31e5dd7070Spatrick static Cl::Kinds ClassifyConditional(ASTContext &Ctx,
32e5dd7070Spatrick                                      const Expr *trueExpr,
33e5dd7070Spatrick                                      const Expr *falseExpr);
34e5dd7070Spatrick static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
35e5dd7070Spatrick                                        Cl::Kinds Kind, SourceLocation &Loc);
36e5dd7070Spatrick 
ClassifyImpl(ASTContext & Ctx,SourceLocation * Loc) const37e5dd7070Spatrick Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const {
38e5dd7070Spatrick   assert(!TR->isReferenceType() && "Expressions can't have reference type.");
39e5dd7070Spatrick 
40e5dd7070Spatrick   Cl::Kinds kind = ClassifyInternal(Ctx, this);
41e5dd7070Spatrick   // C99 6.3.2.1: An lvalue is an expression with an object type or an
42e5dd7070Spatrick   //   incomplete type other than void.
43e5dd7070Spatrick   if (!Ctx.getLangOpts().CPlusPlus) {
44e5dd7070Spatrick     // Thus, no functions.
45e5dd7070Spatrick     if (TR->isFunctionType() || TR == Ctx.OverloadTy)
46e5dd7070Spatrick       kind = Cl::CL_Function;
47e5dd7070Spatrick     // No void either, but qualified void is OK because it is "other than void".
48e5dd7070Spatrick     // Void "lvalues" are classified as addressable void values, which are void
49e5dd7070Spatrick     // expressions whose address can be taken.
50e5dd7070Spatrick     else if (TR->isVoidType() && !TR.hasQualifiers())
51e5dd7070Spatrick       kind = (kind == Cl::CL_LValue ? Cl::CL_AddressableVoid : Cl::CL_Void);
52e5dd7070Spatrick   }
53e5dd7070Spatrick 
54e5dd7070Spatrick   // Enable this assertion for testing.
55e5dd7070Spatrick   switch (kind) {
56a9ac8606Spatrick   case Cl::CL_LValue:
57a9ac8606Spatrick     assert(isLValue());
58a9ac8606Spatrick     break;
59a9ac8606Spatrick   case Cl::CL_XValue:
60a9ac8606Spatrick     assert(isXValue());
61a9ac8606Spatrick     break;
62e5dd7070Spatrick   case Cl::CL_Function:
63e5dd7070Spatrick   case Cl::CL_Void:
64e5dd7070Spatrick   case Cl::CL_AddressableVoid:
65e5dd7070Spatrick   case Cl::CL_DuplicateVectorComponents:
66e5dd7070Spatrick   case Cl::CL_MemberFunction:
67e5dd7070Spatrick   case Cl::CL_SubObjCPropertySetting:
68e5dd7070Spatrick   case Cl::CL_ClassTemporary:
69e5dd7070Spatrick   case Cl::CL_ArrayTemporary:
70e5dd7070Spatrick   case Cl::CL_ObjCMessageRValue:
71a9ac8606Spatrick   case Cl::CL_PRValue:
72a9ac8606Spatrick     assert(isPRValue());
73a9ac8606Spatrick     break;
74e5dd7070Spatrick   }
75e5dd7070Spatrick 
76e5dd7070Spatrick   Cl::ModifiableType modifiable = Cl::CM_Untested;
77e5dd7070Spatrick   if (Loc)
78e5dd7070Spatrick     modifiable = IsModifiable(Ctx, this, kind, *Loc);
79e5dd7070Spatrick   return Classification(kind, modifiable);
80e5dd7070Spatrick }
81e5dd7070Spatrick 
82e5dd7070Spatrick /// Classify an expression which creates a temporary, based on its type.
ClassifyTemporary(QualType T)83e5dd7070Spatrick static Cl::Kinds ClassifyTemporary(QualType T) {
84e5dd7070Spatrick   if (T->isRecordType())
85e5dd7070Spatrick     return Cl::CL_ClassTemporary;
86e5dd7070Spatrick   if (T->isArrayType())
87e5dd7070Spatrick     return Cl::CL_ArrayTemporary;
88e5dd7070Spatrick 
89e5dd7070Spatrick   // No special classification: these don't behave differently from normal
90e5dd7070Spatrick   // prvalues.
91e5dd7070Spatrick   return Cl::CL_PRValue;
92e5dd7070Spatrick }
93e5dd7070Spatrick 
ClassifyExprValueKind(const LangOptions & Lang,const Expr * E,ExprValueKind Kind)94e5dd7070Spatrick static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang,
95e5dd7070Spatrick                                        const Expr *E,
96e5dd7070Spatrick                                        ExprValueKind Kind) {
97e5dd7070Spatrick   switch (Kind) {
98a9ac8606Spatrick   case VK_PRValue:
99e5dd7070Spatrick     return Lang.CPlusPlus ? ClassifyTemporary(E->getType()) : Cl::CL_PRValue;
100e5dd7070Spatrick   case VK_LValue:
101e5dd7070Spatrick     return Cl::CL_LValue;
102e5dd7070Spatrick   case VK_XValue:
103e5dd7070Spatrick     return Cl::CL_XValue;
104e5dd7070Spatrick   }
105e5dd7070Spatrick   llvm_unreachable("Invalid value category of implicit cast.");
106e5dd7070Spatrick }
107e5dd7070Spatrick 
ClassifyInternal(ASTContext & Ctx,const Expr * E)108e5dd7070Spatrick static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
109e5dd7070Spatrick   // This function takes the first stab at classifying expressions.
110e5dd7070Spatrick   const LangOptions &Lang = Ctx.getLangOpts();
111e5dd7070Spatrick 
112e5dd7070Spatrick   switch (E->getStmtClass()) {
113e5dd7070Spatrick   case Stmt::NoStmtClass:
114e5dd7070Spatrick #define ABSTRACT_STMT(Kind)
115e5dd7070Spatrick #define STMT(Kind, Base) case Expr::Kind##Class:
116e5dd7070Spatrick #define EXPR(Kind, Base)
117e5dd7070Spatrick #include "clang/AST/StmtNodes.inc"
118e5dd7070Spatrick     llvm_unreachable("cannot classify a statement");
119e5dd7070Spatrick 
120e5dd7070Spatrick     // First come the expressions that are always lvalues, unconditionally.
121e5dd7070Spatrick   case Expr::ObjCIsaExprClass:
122e5dd7070Spatrick     // C++ [expr.prim.general]p1: A string literal is an lvalue.
123e5dd7070Spatrick   case Expr::StringLiteralClass:
124e5dd7070Spatrick     // @encode is equivalent to its string
125e5dd7070Spatrick   case Expr::ObjCEncodeExprClass:
126e5dd7070Spatrick     // __func__ and friends are too.
127e5dd7070Spatrick   case Expr::PredefinedExprClass:
128e5dd7070Spatrick     // Property references are lvalues
129e5dd7070Spatrick   case Expr::ObjCSubscriptRefExprClass:
130e5dd7070Spatrick   case Expr::ObjCPropertyRefExprClass:
131e5dd7070Spatrick     // C++ [expr.typeid]p1: The result of a typeid expression is an lvalue of...
132e5dd7070Spatrick   case Expr::CXXTypeidExprClass:
133ec727ea7Spatrick   case Expr::CXXUuidofExprClass:
134e5dd7070Spatrick     // Unresolved lookups and uncorrected typos get classified as lvalues.
135e5dd7070Spatrick     // FIXME: Is this wise? Should they get their own kind?
136e5dd7070Spatrick   case Expr::UnresolvedLookupExprClass:
137e5dd7070Spatrick   case Expr::UnresolvedMemberExprClass:
138e5dd7070Spatrick   case Expr::TypoExprClass:
139e5dd7070Spatrick   case Expr::DependentCoawaitExprClass:
140e5dd7070Spatrick   case Expr::CXXDependentScopeMemberExprClass:
141e5dd7070Spatrick   case Expr::DependentScopeDeclRefExprClass:
142e5dd7070Spatrick     // ObjC instance variables are lvalues
143e5dd7070Spatrick     // FIXME: ObjC++0x might have different rules
144e5dd7070Spatrick   case Expr::ObjCIvarRefExprClass:
145e5dd7070Spatrick   case Expr::FunctionParmPackExprClass:
146e5dd7070Spatrick   case Expr::MSPropertyRefExprClass:
147e5dd7070Spatrick   case Expr::MSPropertySubscriptExprClass:
148e5dd7070Spatrick   case Expr::OMPArraySectionExprClass:
149ec727ea7Spatrick   case Expr::OMPArrayShapingExprClass:
150ec727ea7Spatrick   case Expr::OMPIteratorExprClass:
151e5dd7070Spatrick     return Cl::CL_LValue;
152e5dd7070Spatrick 
153e5dd7070Spatrick     // C99 6.5.2.5p5 says that compound literals are lvalues.
154e5dd7070Spatrick     // In C++, they're prvalue temporaries, except for file-scope arrays.
155e5dd7070Spatrick   case Expr::CompoundLiteralExprClass:
156e5dd7070Spatrick     return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue;
157e5dd7070Spatrick 
158e5dd7070Spatrick     // Expressions that are prvalues.
159e5dd7070Spatrick   case Expr::CXXBoolLiteralExprClass:
160e5dd7070Spatrick   case Expr::CXXPseudoDestructorExprClass:
161e5dd7070Spatrick   case Expr::UnaryExprOrTypeTraitExprClass:
162e5dd7070Spatrick   case Expr::CXXNewExprClass:
163e5dd7070Spatrick   case Expr::CXXNullPtrLiteralExprClass:
164e5dd7070Spatrick   case Expr::ImaginaryLiteralClass:
165e5dd7070Spatrick   case Expr::GNUNullExprClass:
166e5dd7070Spatrick   case Expr::OffsetOfExprClass:
167e5dd7070Spatrick   case Expr::CXXThrowExprClass:
168e5dd7070Spatrick   case Expr::ShuffleVectorExprClass:
169e5dd7070Spatrick   case Expr::ConvertVectorExprClass:
170e5dd7070Spatrick   case Expr::IntegerLiteralClass:
171e5dd7070Spatrick   case Expr::FixedPointLiteralClass:
172e5dd7070Spatrick   case Expr::CharacterLiteralClass:
173e5dd7070Spatrick   case Expr::AddrLabelExprClass:
174e5dd7070Spatrick   case Expr::CXXDeleteExprClass:
175e5dd7070Spatrick   case Expr::ImplicitValueInitExprClass:
176e5dd7070Spatrick   case Expr::BlockExprClass:
177e5dd7070Spatrick   case Expr::FloatingLiteralClass:
178e5dd7070Spatrick   case Expr::CXXNoexceptExprClass:
179e5dd7070Spatrick   case Expr::CXXScalarValueInitExprClass:
180e5dd7070Spatrick   case Expr::TypeTraitExprClass:
181e5dd7070Spatrick   case Expr::ArrayTypeTraitExprClass:
182e5dd7070Spatrick   case Expr::ExpressionTraitExprClass:
183e5dd7070Spatrick   case Expr::ObjCSelectorExprClass:
184e5dd7070Spatrick   case Expr::ObjCProtocolExprClass:
185e5dd7070Spatrick   case Expr::ObjCStringLiteralClass:
186e5dd7070Spatrick   case Expr::ObjCBoxedExprClass:
187e5dd7070Spatrick   case Expr::ObjCArrayLiteralClass:
188e5dd7070Spatrick   case Expr::ObjCDictionaryLiteralClass:
189e5dd7070Spatrick   case Expr::ObjCBoolLiteralExprClass:
190e5dd7070Spatrick   case Expr::ObjCAvailabilityCheckExprClass:
191e5dd7070Spatrick   case Expr::ParenListExprClass:
192e5dd7070Spatrick   case Expr::SizeOfPackExprClass:
193e5dd7070Spatrick   case Expr::SubstNonTypeTemplateParmPackExprClass:
194e5dd7070Spatrick   case Expr::AsTypeExprClass:
195e5dd7070Spatrick   case Expr::ObjCIndirectCopyRestoreExprClass:
196e5dd7070Spatrick   case Expr::AtomicExprClass:
197e5dd7070Spatrick   case Expr::CXXFoldExprClass:
198e5dd7070Spatrick   case Expr::ArrayInitLoopExprClass:
199e5dd7070Spatrick   case Expr::ArrayInitIndexExprClass:
200e5dd7070Spatrick   case Expr::NoInitExprClass:
201e5dd7070Spatrick   case Expr::DesignatedInitUpdateExprClass:
202e5dd7070Spatrick   case Expr::SourceLocExprClass:
203e5dd7070Spatrick   case Expr::ConceptSpecializationExprClass:
204e5dd7070Spatrick   case Expr::RequiresExprClass:
205e5dd7070Spatrick     return Cl::CL_PRValue;
206e5dd7070Spatrick 
207*12c85518Srobert   // Make HLSL this reference-like
208*12c85518Srobert   case Expr::CXXThisExprClass:
209*12c85518Srobert     return Lang.HLSL ? Cl::CL_LValue : Cl::CL_PRValue;
210*12c85518Srobert 
211e5dd7070Spatrick   case Expr::ConstantExprClass:
212e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr());
213e5dd7070Spatrick 
214e5dd7070Spatrick     // Next come the complicated cases.
215e5dd7070Spatrick   case Expr::SubstNonTypeTemplateParmExprClass:
216e5dd7070Spatrick     return ClassifyInternal(Ctx,
217e5dd7070Spatrick                  cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
218e5dd7070Spatrick 
219e5dd7070Spatrick     // C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
220e5dd7070Spatrick     // C++11 (DR1213): in the case of an array operand, the result is an lvalue
221e5dd7070Spatrick     //                 if that operand is an lvalue and an xvalue otherwise.
222e5dd7070Spatrick     // Subscripting vector types is more like member access.
223e5dd7070Spatrick   case Expr::ArraySubscriptExprClass:
224e5dd7070Spatrick     if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType())
225e5dd7070Spatrick       return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase());
226e5dd7070Spatrick     if (Lang.CPlusPlus11) {
227e5dd7070Spatrick       // Step over the array-to-pointer decay if present, but not over the
228e5dd7070Spatrick       // temporary materialization.
229e5dd7070Spatrick       auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts();
230e5dd7070Spatrick       if (Base->getType()->isArrayType())
231e5dd7070Spatrick         return ClassifyInternal(Ctx, Base);
232e5dd7070Spatrick     }
233e5dd7070Spatrick     return Cl::CL_LValue;
234e5dd7070Spatrick 
235ec727ea7Spatrick   // Subscripting matrix types behaves like member accesses.
236ec727ea7Spatrick   case Expr::MatrixSubscriptExprClass:
237ec727ea7Spatrick     return ClassifyInternal(Ctx, cast<MatrixSubscriptExpr>(E)->getBase());
238ec727ea7Spatrick 
239e5dd7070Spatrick     // C++ [expr.prim.general]p3: The result is an lvalue if the entity is a
240e5dd7070Spatrick     //   function or variable and a prvalue otherwise.
241e5dd7070Spatrick   case Expr::DeclRefExprClass:
242e5dd7070Spatrick     if (E->getType() == Ctx.UnknownAnyTy)
243e5dd7070Spatrick       return isa<FunctionDecl>(cast<DeclRefExpr>(E)->getDecl())
244e5dd7070Spatrick                ? Cl::CL_PRValue : Cl::CL_LValue;
245e5dd7070Spatrick     return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl());
246e5dd7070Spatrick 
247e5dd7070Spatrick     // Member access is complex.
248e5dd7070Spatrick   case Expr::MemberExprClass:
249e5dd7070Spatrick     return ClassifyMemberExpr(Ctx, cast<MemberExpr>(E));
250e5dd7070Spatrick 
251e5dd7070Spatrick   case Expr::UnaryOperatorClass:
252e5dd7070Spatrick     switch (cast<UnaryOperator>(E)->getOpcode()) {
253e5dd7070Spatrick       // C++ [expr.unary.op]p1: The unary * operator performs indirection:
254e5dd7070Spatrick       //   [...] the result is an lvalue referring to the object or function
255e5dd7070Spatrick       //   to which the expression points.
256e5dd7070Spatrick     case UO_Deref:
257e5dd7070Spatrick       return Cl::CL_LValue;
258e5dd7070Spatrick 
259e5dd7070Spatrick       // GNU extensions, simply look through them.
260e5dd7070Spatrick     case UO_Extension:
261e5dd7070Spatrick       return ClassifyInternal(Ctx, cast<UnaryOperator>(E)->getSubExpr());
262e5dd7070Spatrick 
263e5dd7070Spatrick     // Treat _Real and _Imag basically as if they were member
264e5dd7070Spatrick     // expressions:  l-value only if the operand is a true l-value.
265e5dd7070Spatrick     case UO_Real:
266e5dd7070Spatrick     case UO_Imag: {
267e5dd7070Spatrick       const Expr *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
268e5dd7070Spatrick       Cl::Kinds K = ClassifyInternal(Ctx, Op);
269e5dd7070Spatrick       if (K != Cl::CL_LValue) return K;
270e5dd7070Spatrick 
271e5dd7070Spatrick       if (isa<ObjCPropertyRefExpr>(Op))
272e5dd7070Spatrick         return Cl::CL_SubObjCPropertySetting;
273e5dd7070Spatrick       return Cl::CL_LValue;
274e5dd7070Spatrick     }
275e5dd7070Spatrick 
276e5dd7070Spatrick       // C++ [expr.pre.incr]p1: The result is the updated operand; it is an
277e5dd7070Spatrick       //   lvalue, [...]
278e5dd7070Spatrick       // Not so in C.
279e5dd7070Spatrick     case UO_PreInc:
280e5dd7070Spatrick     case UO_PreDec:
281e5dd7070Spatrick       return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue;
282e5dd7070Spatrick 
283e5dd7070Spatrick     default:
284e5dd7070Spatrick       return Cl::CL_PRValue;
285e5dd7070Spatrick     }
286e5dd7070Spatrick 
287ec727ea7Spatrick   case Expr::RecoveryExprClass:
288e5dd7070Spatrick   case Expr::OpaqueValueExprClass:
289e5dd7070Spatrick     return ClassifyExprValueKind(Lang, E, E->getValueKind());
290e5dd7070Spatrick 
291e5dd7070Spatrick     // Pseudo-object expressions can produce l-values with reference magic.
292e5dd7070Spatrick   case Expr::PseudoObjectExprClass:
293e5dd7070Spatrick     return ClassifyExprValueKind(Lang, E,
294e5dd7070Spatrick                                  cast<PseudoObjectExpr>(E)->getValueKind());
295e5dd7070Spatrick 
296e5dd7070Spatrick     // Implicit casts are lvalues if they're lvalue casts. Other than that, we
297e5dd7070Spatrick     // only specifically record class temporaries.
298e5dd7070Spatrick   case Expr::ImplicitCastExprClass:
299e5dd7070Spatrick     return ClassifyExprValueKind(Lang, E, E->getValueKind());
300e5dd7070Spatrick 
301e5dd7070Spatrick     // C++ [expr.prim.general]p4: The presence of parentheses does not affect
302e5dd7070Spatrick     //   whether the expression is an lvalue.
303e5dd7070Spatrick   case Expr::ParenExprClass:
304e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr());
305e5dd7070Spatrick 
306e5dd7070Spatrick     // C11 6.5.1.1p4: [A generic selection] is an lvalue, a function designator,
307e5dd7070Spatrick     // or a void expression if its result expression is, respectively, an
308e5dd7070Spatrick     // lvalue, a function designator, or a void expression.
309e5dd7070Spatrick   case Expr::GenericSelectionExprClass:
310e5dd7070Spatrick     if (cast<GenericSelectionExpr>(E)->isResultDependent())
311e5dd7070Spatrick       return Cl::CL_PRValue;
312e5dd7070Spatrick     return ClassifyInternal(Ctx,cast<GenericSelectionExpr>(E)->getResultExpr());
313e5dd7070Spatrick 
314e5dd7070Spatrick   case Expr::BinaryOperatorClass:
315e5dd7070Spatrick   case Expr::CompoundAssignOperatorClass:
316e5dd7070Spatrick     // C doesn't have any binary expressions that are lvalues.
317e5dd7070Spatrick     if (Lang.CPlusPlus)
318e5dd7070Spatrick       return ClassifyBinaryOp(Ctx, cast<BinaryOperator>(E));
319e5dd7070Spatrick     return Cl::CL_PRValue;
320e5dd7070Spatrick 
321e5dd7070Spatrick   case Expr::CallExprClass:
322e5dd7070Spatrick   case Expr::CXXOperatorCallExprClass:
323e5dd7070Spatrick   case Expr::CXXMemberCallExprClass:
324e5dd7070Spatrick   case Expr::UserDefinedLiteralClass:
325e5dd7070Spatrick   case Expr::CUDAKernelCallExprClass:
326e5dd7070Spatrick     return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType(Ctx));
327e5dd7070Spatrick 
328e5dd7070Spatrick   case Expr::CXXRewrittenBinaryOperatorClass:
329e5dd7070Spatrick     return ClassifyInternal(
330e5dd7070Spatrick         Ctx, cast<CXXRewrittenBinaryOperator>(E)->getSemanticForm());
331e5dd7070Spatrick 
332e5dd7070Spatrick     // __builtin_choose_expr is equivalent to the chosen expression.
333e5dd7070Spatrick   case Expr::ChooseExprClass:
334e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr());
335e5dd7070Spatrick 
336e5dd7070Spatrick     // Extended vector element access is an lvalue unless there are duplicates
337e5dd7070Spatrick     // in the shuffle expression.
338e5dd7070Spatrick   case Expr::ExtVectorElementExprClass:
339e5dd7070Spatrick     if (cast<ExtVectorElementExpr>(E)->containsDuplicateElements())
340e5dd7070Spatrick       return Cl::CL_DuplicateVectorComponents;
341e5dd7070Spatrick     if (cast<ExtVectorElementExpr>(E)->isArrow())
342e5dd7070Spatrick       return Cl::CL_LValue;
343e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<ExtVectorElementExpr>(E)->getBase());
344e5dd7070Spatrick 
345e5dd7070Spatrick     // Simply look at the actual default argument.
346e5dd7070Spatrick   case Expr::CXXDefaultArgExprClass:
347e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<CXXDefaultArgExpr>(E)->getExpr());
348e5dd7070Spatrick 
349e5dd7070Spatrick     // Same idea for default initializers.
350e5dd7070Spatrick   case Expr::CXXDefaultInitExprClass:
351e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<CXXDefaultInitExpr>(E)->getExpr());
352e5dd7070Spatrick 
353e5dd7070Spatrick     // Same idea for temporary binding.
354e5dd7070Spatrick   case Expr::CXXBindTemporaryExprClass:
355e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<CXXBindTemporaryExpr>(E)->getSubExpr());
356e5dd7070Spatrick 
357e5dd7070Spatrick     // And the cleanups guard.
358e5dd7070Spatrick   case Expr::ExprWithCleanupsClass:
359e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<ExprWithCleanups>(E)->getSubExpr());
360e5dd7070Spatrick 
361e5dd7070Spatrick     // Casts depend completely on the target type. All casts work the same.
362e5dd7070Spatrick   case Expr::CStyleCastExprClass:
363e5dd7070Spatrick   case Expr::CXXFunctionalCastExprClass:
364e5dd7070Spatrick   case Expr::CXXStaticCastExprClass:
365e5dd7070Spatrick   case Expr::CXXDynamicCastExprClass:
366e5dd7070Spatrick   case Expr::CXXReinterpretCastExprClass:
367e5dd7070Spatrick   case Expr::CXXConstCastExprClass:
368ec727ea7Spatrick   case Expr::CXXAddrspaceCastExprClass:
369e5dd7070Spatrick   case Expr::ObjCBridgedCastExprClass:
370e5dd7070Spatrick   case Expr::BuiltinBitCastExprClass:
371e5dd7070Spatrick     // Only in C++ can casts be interesting at all.
372e5dd7070Spatrick     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
373e5dd7070Spatrick     return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());
374e5dd7070Spatrick 
375e5dd7070Spatrick   case Expr::CXXUnresolvedConstructExprClass:
376e5dd7070Spatrick     return ClassifyUnnamed(Ctx,
377e5dd7070Spatrick                       cast<CXXUnresolvedConstructExpr>(E)->getTypeAsWritten());
378e5dd7070Spatrick 
379e5dd7070Spatrick   case Expr::BinaryConditionalOperatorClass: {
380e5dd7070Spatrick     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
381e5dd7070Spatrick     const auto *co = cast<BinaryConditionalOperator>(E);
382e5dd7070Spatrick     return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
383e5dd7070Spatrick   }
384e5dd7070Spatrick 
385e5dd7070Spatrick   case Expr::ConditionalOperatorClass: {
386e5dd7070Spatrick     // Once again, only C++ is interesting.
387e5dd7070Spatrick     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
388e5dd7070Spatrick     const auto *co = cast<ConditionalOperator>(E);
389e5dd7070Spatrick     return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr());
390e5dd7070Spatrick   }
391e5dd7070Spatrick 
392e5dd7070Spatrick     // ObjC message sends are effectively function calls, if the target function
393e5dd7070Spatrick     // is known.
394e5dd7070Spatrick   case Expr::ObjCMessageExprClass:
395e5dd7070Spatrick     if (const ObjCMethodDecl *Method =
396e5dd7070Spatrick           cast<ObjCMessageExpr>(E)->getMethodDecl()) {
397e5dd7070Spatrick       Cl::Kinds kind = ClassifyUnnamed(Ctx, Method->getReturnType());
398e5dd7070Spatrick       return (kind == Cl::CL_PRValue) ? Cl::CL_ObjCMessageRValue : kind;
399e5dd7070Spatrick     }
400e5dd7070Spatrick     return Cl::CL_PRValue;
401e5dd7070Spatrick 
402e5dd7070Spatrick     // Some C++ expressions are always class temporaries.
403e5dd7070Spatrick   case Expr::CXXConstructExprClass:
404e5dd7070Spatrick   case Expr::CXXInheritedCtorInitExprClass:
405e5dd7070Spatrick   case Expr::CXXTemporaryObjectExprClass:
406e5dd7070Spatrick   case Expr::LambdaExprClass:
407e5dd7070Spatrick   case Expr::CXXStdInitializerListExprClass:
408e5dd7070Spatrick     return Cl::CL_ClassTemporary;
409e5dd7070Spatrick 
410e5dd7070Spatrick   case Expr::VAArgExprClass:
411e5dd7070Spatrick     return ClassifyUnnamed(Ctx, E->getType());
412e5dd7070Spatrick 
413e5dd7070Spatrick   case Expr::DesignatedInitExprClass:
414e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<DesignatedInitExpr>(E)->getInit());
415e5dd7070Spatrick 
416e5dd7070Spatrick   case Expr::StmtExprClass: {
417e5dd7070Spatrick     const CompoundStmt *S = cast<StmtExpr>(E)->getSubStmt();
418e5dd7070Spatrick     if (const auto *LastExpr = dyn_cast_or_null<Expr>(S->body_back()))
419e5dd7070Spatrick       return ClassifyUnnamed(Ctx, LastExpr->getType());
420e5dd7070Spatrick     return Cl::CL_PRValue;
421e5dd7070Spatrick   }
422e5dd7070Spatrick 
423e5dd7070Spatrick   case Expr::PackExpansionExprClass:
424e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern());
425e5dd7070Spatrick 
426e5dd7070Spatrick   case Expr::MaterializeTemporaryExprClass:
427e5dd7070Spatrick     return cast<MaterializeTemporaryExpr>(E)->isBoundToLvalueReference()
428e5dd7070Spatrick               ? Cl::CL_LValue
429e5dd7070Spatrick               : Cl::CL_XValue;
430e5dd7070Spatrick 
431e5dd7070Spatrick   case Expr::InitListExprClass:
432e5dd7070Spatrick     // An init list can be an lvalue if it is bound to a reference and
433e5dd7070Spatrick     // contains only one element. In that case, we look at that element
434e5dd7070Spatrick     // for an exact classification. Init list creation takes care of the
435e5dd7070Spatrick     // value kind for us, so we only need to fine-tune.
436a9ac8606Spatrick     if (E->isPRValue())
437e5dd7070Spatrick       return ClassifyExprValueKind(Lang, E, E->getValueKind());
438e5dd7070Spatrick     assert(cast<InitListExpr>(E)->getNumInits() == 1 &&
439e5dd7070Spatrick            "Only 1-element init lists can be glvalues.");
440e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0));
441e5dd7070Spatrick 
442e5dd7070Spatrick   case Expr::CoawaitExprClass:
443e5dd7070Spatrick   case Expr::CoyieldExprClass:
444e5dd7070Spatrick     return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr());
445a9ac8606Spatrick   case Expr::SYCLUniqueStableNameExprClass:
446a9ac8606Spatrick     return Cl::CL_PRValue;
447a9ac8606Spatrick     break;
448*12c85518Srobert 
449*12c85518Srobert   case Expr::CXXParenListInitExprClass:
450*12c85518Srobert     if (isa<ArrayType>(E->getType()))
451*12c85518Srobert       return Cl::CL_ArrayTemporary;
452*12c85518Srobert     return Cl::CL_ClassTemporary;
453e5dd7070Spatrick   }
454e5dd7070Spatrick 
455e5dd7070Spatrick   llvm_unreachable("unhandled expression kind in classification");
456e5dd7070Spatrick }
457e5dd7070Spatrick 
458e5dd7070Spatrick /// ClassifyDecl - Return the classification of an expression referencing the
459e5dd7070Spatrick /// given declaration.
ClassifyDecl(ASTContext & Ctx,const Decl * D)460e5dd7070Spatrick static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
461e5dd7070Spatrick   // C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
462e5dd7070Spatrick   //   function, variable, or data member and a prvalue otherwise.
463e5dd7070Spatrick   // In C, functions are not lvalues.
464e5dd7070Spatrick   // In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
465e5dd7070Spatrick   // lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
466e5dd7070Spatrick   // special-case this.
467e5dd7070Spatrick 
468e5dd7070Spatrick   if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
469e5dd7070Spatrick     return Cl::CL_MemberFunction;
470e5dd7070Spatrick 
471e5dd7070Spatrick   bool islvalue;
472e5dd7070Spatrick   if (const auto *NTTParm = dyn_cast<NonTypeTemplateParmDecl>(D))
473a9ac8606Spatrick     islvalue = NTTParm->getType()->isReferenceType() ||
474a9ac8606Spatrick                NTTParm->getType()->isRecordType();
475e5dd7070Spatrick   else
476*12c85518Srobert     islvalue =
477*12c85518Srobert         isa<VarDecl, FieldDecl, IndirectFieldDecl, BindingDecl, MSGuidDecl,
478*12c85518Srobert             UnnamedGlobalConstantDecl, TemplateParamObjectDecl>(D) ||
479e5dd7070Spatrick         (Ctx.getLangOpts().CPlusPlus &&
480*12c85518Srobert          (isa<FunctionDecl, MSPropertyDecl, FunctionTemplateDecl>(D)));
481e5dd7070Spatrick 
482e5dd7070Spatrick   return islvalue ? Cl::CL_LValue : Cl::CL_PRValue;
483e5dd7070Spatrick }
484e5dd7070Spatrick 
485e5dd7070Spatrick /// ClassifyUnnamed - Return the classification of an expression yielding an
486e5dd7070Spatrick /// unnamed value of the given type. This applies in particular to function
487e5dd7070Spatrick /// calls and casts.
ClassifyUnnamed(ASTContext & Ctx,QualType T)488e5dd7070Spatrick static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) {
489e5dd7070Spatrick   // In C, function calls are always rvalues.
490e5dd7070Spatrick   if (!Ctx.getLangOpts().CPlusPlus) return Cl::CL_PRValue;
491e5dd7070Spatrick 
492e5dd7070Spatrick   // C++ [expr.call]p10: A function call is an lvalue if the result type is an
493e5dd7070Spatrick   //   lvalue reference type or an rvalue reference to function type, an xvalue
494e5dd7070Spatrick   //   if the result type is an rvalue reference to object type, and a prvalue
495e5dd7070Spatrick   //   otherwise.
496e5dd7070Spatrick   if (T->isLValueReferenceType())
497e5dd7070Spatrick     return Cl::CL_LValue;
498e5dd7070Spatrick   const auto *RV = T->getAs<RValueReferenceType>();
499e5dd7070Spatrick   if (!RV) // Could still be a class temporary, though.
500e5dd7070Spatrick     return ClassifyTemporary(T);
501e5dd7070Spatrick 
502e5dd7070Spatrick   return RV->getPointeeType()->isFunctionType() ? Cl::CL_LValue : Cl::CL_XValue;
503e5dd7070Spatrick }
504e5dd7070Spatrick 
ClassifyMemberExpr(ASTContext & Ctx,const MemberExpr * E)505e5dd7070Spatrick static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) {
506e5dd7070Spatrick   if (E->getType() == Ctx.UnknownAnyTy)
507e5dd7070Spatrick     return (isa<FunctionDecl>(E->getMemberDecl())
508e5dd7070Spatrick               ? Cl::CL_PRValue : Cl::CL_LValue);
509e5dd7070Spatrick 
510e5dd7070Spatrick   // Handle C first, it's easier.
511e5dd7070Spatrick   if (!Ctx.getLangOpts().CPlusPlus) {
512e5dd7070Spatrick     // C99 6.5.2.3p3
513e5dd7070Spatrick     // For dot access, the expression is an lvalue if the first part is. For
514e5dd7070Spatrick     // arrow access, it always is an lvalue.
515e5dd7070Spatrick     if (E->isArrow())
516e5dd7070Spatrick       return Cl::CL_LValue;
517e5dd7070Spatrick     // ObjC property accesses are not lvalues, but get special treatment.
518e5dd7070Spatrick     Expr *Base = E->getBase()->IgnoreParens();
519e5dd7070Spatrick     if (isa<ObjCPropertyRefExpr>(Base))
520e5dd7070Spatrick       return Cl::CL_SubObjCPropertySetting;
521e5dd7070Spatrick     return ClassifyInternal(Ctx, Base);
522e5dd7070Spatrick   }
523e5dd7070Spatrick 
524e5dd7070Spatrick   NamedDecl *Member = E->getMemberDecl();
525e5dd7070Spatrick   // C++ [expr.ref]p3: E1->E2 is converted to the equivalent form (*(E1)).E2.
526e5dd7070Spatrick   // C++ [expr.ref]p4: If E2 is declared to have type "reference to T", then
527e5dd7070Spatrick   //   E1.E2 is an lvalue.
528e5dd7070Spatrick   if (const auto *Value = dyn_cast<ValueDecl>(Member))
529e5dd7070Spatrick     if (Value->getType()->isReferenceType())
530e5dd7070Spatrick       return Cl::CL_LValue;
531e5dd7070Spatrick 
532e5dd7070Spatrick   //   Otherwise, one of the following rules applies.
533e5dd7070Spatrick   //   -- If E2 is a static member [...] then E1.E2 is an lvalue.
534e5dd7070Spatrick   if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord())
535e5dd7070Spatrick     return Cl::CL_LValue;
536e5dd7070Spatrick 
537e5dd7070Spatrick   //   -- If E2 is a non-static data member [...]. If E1 is an lvalue, then
538e5dd7070Spatrick   //      E1.E2 is an lvalue; if E1 is an xvalue, then E1.E2 is an xvalue;
539e5dd7070Spatrick   //      otherwise, it is a prvalue.
540e5dd7070Spatrick   if (isa<FieldDecl>(Member)) {
541e5dd7070Spatrick     // *E1 is an lvalue
542e5dd7070Spatrick     if (E->isArrow())
543e5dd7070Spatrick       return Cl::CL_LValue;
544e5dd7070Spatrick     Expr *Base = E->getBase()->IgnoreParenImpCasts();
545e5dd7070Spatrick     if (isa<ObjCPropertyRefExpr>(Base))
546e5dd7070Spatrick       return Cl::CL_SubObjCPropertySetting;
547e5dd7070Spatrick     return ClassifyInternal(Ctx, E->getBase());
548e5dd7070Spatrick   }
549e5dd7070Spatrick 
550e5dd7070Spatrick   //   -- If E2 is a [...] member function, [...]
551e5dd7070Spatrick   //      -- If it refers to a static member function [...], then E1.E2 is an
552e5dd7070Spatrick   //         lvalue; [...]
553e5dd7070Spatrick   //      -- Otherwise [...] E1.E2 is a prvalue.
554e5dd7070Spatrick   if (const auto *Method = dyn_cast<CXXMethodDecl>(Member))
555e5dd7070Spatrick     return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction;
556e5dd7070Spatrick 
557e5dd7070Spatrick   //   -- If E2 is a member enumerator [...], the expression E1.E2 is a prvalue.
558e5dd7070Spatrick   // So is everything else we haven't handled yet.
559e5dd7070Spatrick   return Cl::CL_PRValue;
560e5dd7070Spatrick }
561e5dd7070Spatrick 
ClassifyBinaryOp(ASTContext & Ctx,const BinaryOperator * E)562e5dd7070Spatrick static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) {
563e5dd7070Spatrick   assert(Ctx.getLangOpts().CPlusPlus &&
564e5dd7070Spatrick          "This is only relevant for C++.");
565e5dd7070Spatrick   // C++ [expr.ass]p1: All [...] return an lvalue referring to the left operand.
566e5dd7070Spatrick   // Except we override this for writes to ObjC properties.
567e5dd7070Spatrick   if (E->isAssignmentOp())
568e5dd7070Spatrick     return (E->getLHS()->getObjectKind() == OK_ObjCProperty
569e5dd7070Spatrick               ? Cl::CL_PRValue : Cl::CL_LValue);
570e5dd7070Spatrick 
571e5dd7070Spatrick   // C++ [expr.comma]p1: the result is of the same value category as its right
572e5dd7070Spatrick   //   operand, [...].
573e5dd7070Spatrick   if (E->getOpcode() == BO_Comma)
574e5dd7070Spatrick     return ClassifyInternal(Ctx, E->getRHS());
575e5dd7070Spatrick 
576e5dd7070Spatrick   // C++ [expr.mptr.oper]p6: The result of a .* expression whose second operand
577e5dd7070Spatrick   //   is a pointer to a data member is of the same value category as its first
578e5dd7070Spatrick   //   operand.
579e5dd7070Spatrick   if (E->getOpcode() == BO_PtrMemD)
580e5dd7070Spatrick     return (E->getType()->isFunctionType() ||
581e5dd7070Spatrick             E->hasPlaceholderType(BuiltinType::BoundMember))
582e5dd7070Spatrick              ? Cl::CL_MemberFunction
583e5dd7070Spatrick              : ClassifyInternal(Ctx, E->getLHS());
584e5dd7070Spatrick 
585e5dd7070Spatrick   // C++ [expr.mptr.oper]p6: The result of an ->* expression is an lvalue if its
586e5dd7070Spatrick   //   second operand is a pointer to data member and a prvalue otherwise.
587e5dd7070Spatrick   if (E->getOpcode() == BO_PtrMemI)
588e5dd7070Spatrick     return (E->getType()->isFunctionType() ||
589e5dd7070Spatrick             E->hasPlaceholderType(BuiltinType::BoundMember))
590e5dd7070Spatrick              ? Cl::CL_MemberFunction
591e5dd7070Spatrick              : Cl::CL_LValue;
592e5dd7070Spatrick 
593e5dd7070Spatrick   // All other binary operations are prvalues.
594e5dd7070Spatrick   return Cl::CL_PRValue;
595e5dd7070Spatrick }
596e5dd7070Spatrick 
ClassifyConditional(ASTContext & Ctx,const Expr * True,const Expr * False)597e5dd7070Spatrick static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True,
598e5dd7070Spatrick                                      const Expr *False) {
599e5dd7070Spatrick   assert(Ctx.getLangOpts().CPlusPlus &&
600e5dd7070Spatrick          "This is only relevant for C++.");
601e5dd7070Spatrick 
602e5dd7070Spatrick   // C++ [expr.cond]p2
603e5dd7070Spatrick   //   If either the second or the third operand has type (cv) void,
604e5dd7070Spatrick   //   one of the following shall hold:
605e5dd7070Spatrick   if (True->getType()->isVoidType() || False->getType()->isVoidType()) {
606e5dd7070Spatrick     // The second or the third operand (but not both) is a (possibly
607e5dd7070Spatrick     // parenthesized) throw-expression; the result is of the [...] value
608e5dd7070Spatrick     // category of the other.
609e5dd7070Spatrick     bool TrueIsThrow = isa<CXXThrowExpr>(True->IgnoreParenImpCasts());
610e5dd7070Spatrick     bool FalseIsThrow = isa<CXXThrowExpr>(False->IgnoreParenImpCasts());
611e5dd7070Spatrick     if (const Expr *NonThrow = TrueIsThrow ? (FalseIsThrow ? nullptr : False)
612e5dd7070Spatrick                                            : (FalseIsThrow ? True : nullptr))
613e5dd7070Spatrick       return ClassifyInternal(Ctx, NonThrow);
614e5dd7070Spatrick 
615e5dd7070Spatrick     //   [Otherwise] the result [...] is a prvalue.
616e5dd7070Spatrick     return Cl::CL_PRValue;
617e5dd7070Spatrick   }
618e5dd7070Spatrick 
619e5dd7070Spatrick   // Note that at this point, we have already performed all conversions
620e5dd7070Spatrick   // according to [expr.cond]p3.
621e5dd7070Spatrick   // C++ [expr.cond]p4: If the second and third operands are glvalues of the
622e5dd7070Spatrick   //   same value category [...], the result is of that [...] value category.
623e5dd7070Spatrick   // C++ [expr.cond]p5: Otherwise, the result is a prvalue.
624e5dd7070Spatrick   Cl::Kinds LCl = ClassifyInternal(Ctx, True),
625e5dd7070Spatrick             RCl = ClassifyInternal(Ctx, False);
626e5dd7070Spatrick   return LCl == RCl ? LCl : Cl::CL_PRValue;
627e5dd7070Spatrick }
628e5dd7070Spatrick 
IsModifiable(ASTContext & Ctx,const Expr * E,Cl::Kinds Kind,SourceLocation & Loc)629e5dd7070Spatrick static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E,
630e5dd7070Spatrick                                        Cl::Kinds Kind, SourceLocation &Loc) {
631e5dd7070Spatrick   // As a general rule, we only care about lvalues. But there are some rvalues
632e5dd7070Spatrick   // for which we want to generate special results.
633e5dd7070Spatrick   if (Kind == Cl::CL_PRValue) {
634e5dd7070Spatrick     // For the sake of better diagnostics, we want to specifically recognize
635e5dd7070Spatrick     // use of the GCC cast-as-lvalue extension.
636e5dd7070Spatrick     if (const auto *CE = dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) {
637e5dd7070Spatrick       if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) {
638e5dd7070Spatrick         Loc = CE->getExprLoc();
639e5dd7070Spatrick         return Cl::CM_LValueCast;
640e5dd7070Spatrick       }
641e5dd7070Spatrick     }
642e5dd7070Spatrick   }
643e5dd7070Spatrick   if (Kind != Cl::CL_LValue)
644e5dd7070Spatrick     return Cl::CM_RValue;
645e5dd7070Spatrick 
646e5dd7070Spatrick   // This is the lvalue case.
647e5dd7070Spatrick   // Functions are lvalues in C++, but not modifiable. (C++ [basic.lval]p6)
648e5dd7070Spatrick   if (Ctx.getLangOpts().CPlusPlus && E->getType()->isFunctionType())
649e5dd7070Spatrick     return Cl::CM_Function;
650e5dd7070Spatrick 
651e5dd7070Spatrick   // Assignment to a property in ObjC is an implicit setter access. But a
652e5dd7070Spatrick   // setter might not exist.
653e5dd7070Spatrick   if (const auto *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) {
654e5dd7070Spatrick     if (Expr->isImplicitProperty() &&
655e5dd7070Spatrick         Expr->getImplicitPropertySetter() == nullptr)
656e5dd7070Spatrick       return Cl::CM_NoSetterProperty;
657e5dd7070Spatrick   }
658e5dd7070Spatrick 
659e5dd7070Spatrick   CanQualType CT = Ctx.getCanonicalType(E->getType());
660e5dd7070Spatrick   // Const stuff is obviously not modifiable.
661e5dd7070Spatrick   if (CT.isConstQualified())
662e5dd7070Spatrick     return Cl::CM_ConstQualified;
663e5dd7070Spatrick   if (Ctx.getLangOpts().OpenCL &&
664e5dd7070Spatrick       CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant)
665e5dd7070Spatrick     return Cl::CM_ConstAddrSpace;
666e5dd7070Spatrick 
667e5dd7070Spatrick   // Arrays are not modifiable, only their elements are.
668e5dd7070Spatrick   if (CT->isArrayType())
669e5dd7070Spatrick     return Cl::CM_ArrayType;
670e5dd7070Spatrick   // Incomplete types are not modifiable.
671e5dd7070Spatrick   if (CT->isIncompleteType())
672e5dd7070Spatrick     return Cl::CM_IncompleteType;
673e5dd7070Spatrick 
674e5dd7070Spatrick   // Records with any const fields (recursively) are not modifiable.
675e5dd7070Spatrick   if (const RecordType *R = CT->getAs<RecordType>())
676e5dd7070Spatrick     if (R->hasConstFields())
677e5dd7070Spatrick       return Cl::CM_ConstQualifiedField;
678e5dd7070Spatrick 
679e5dd7070Spatrick   return Cl::CM_Modifiable;
680e5dd7070Spatrick }
681e5dd7070Spatrick 
ClassifyLValue(ASTContext & Ctx) const682e5dd7070Spatrick Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const {
683e5dd7070Spatrick   Classification VC = Classify(Ctx);
684e5dd7070Spatrick   switch (VC.getKind()) {
685e5dd7070Spatrick   case Cl::CL_LValue: return LV_Valid;
686e5dd7070Spatrick   case Cl::CL_XValue: return LV_InvalidExpression;
687e5dd7070Spatrick   case Cl::CL_Function: return LV_NotObjectType;
688e5dd7070Spatrick   case Cl::CL_Void: return LV_InvalidExpression;
689e5dd7070Spatrick   case Cl::CL_AddressableVoid: return LV_IncompleteVoidType;
690e5dd7070Spatrick   case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents;
691e5dd7070Spatrick   case Cl::CL_MemberFunction: return LV_MemberFunction;
692e5dd7070Spatrick   case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting;
693e5dd7070Spatrick   case Cl::CL_ClassTemporary: return LV_ClassTemporary;
694e5dd7070Spatrick   case Cl::CL_ArrayTemporary: return LV_ArrayTemporary;
695e5dd7070Spatrick   case Cl::CL_ObjCMessageRValue: return LV_InvalidMessageExpression;
696e5dd7070Spatrick   case Cl::CL_PRValue: return LV_InvalidExpression;
697e5dd7070Spatrick   }
698e5dd7070Spatrick   llvm_unreachable("Unhandled kind");
699e5dd7070Spatrick }
700e5dd7070Spatrick 
701e5dd7070Spatrick Expr::isModifiableLvalueResult
isModifiableLvalue(ASTContext & Ctx,SourceLocation * Loc) const702e5dd7070Spatrick Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
703e5dd7070Spatrick   SourceLocation dummy;
704e5dd7070Spatrick   Classification VC = ClassifyModifiable(Ctx, Loc ? *Loc : dummy);
705e5dd7070Spatrick   switch (VC.getKind()) {
706e5dd7070Spatrick   case Cl::CL_LValue: break;
707e5dd7070Spatrick   case Cl::CL_XValue: return MLV_InvalidExpression;
708e5dd7070Spatrick   case Cl::CL_Function: return MLV_NotObjectType;
709e5dd7070Spatrick   case Cl::CL_Void: return MLV_InvalidExpression;
710e5dd7070Spatrick   case Cl::CL_AddressableVoid: return MLV_IncompleteVoidType;
711e5dd7070Spatrick   case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
712e5dd7070Spatrick   case Cl::CL_MemberFunction: return MLV_MemberFunction;
713e5dd7070Spatrick   case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
714e5dd7070Spatrick   case Cl::CL_ClassTemporary: return MLV_ClassTemporary;
715e5dd7070Spatrick   case Cl::CL_ArrayTemporary: return MLV_ArrayTemporary;
716e5dd7070Spatrick   case Cl::CL_ObjCMessageRValue: return MLV_InvalidMessageExpression;
717e5dd7070Spatrick   case Cl::CL_PRValue:
718e5dd7070Spatrick     return VC.getModifiable() == Cl::CM_LValueCast ?
719e5dd7070Spatrick       MLV_LValueCast : MLV_InvalidExpression;
720e5dd7070Spatrick   }
721e5dd7070Spatrick   assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind");
722e5dd7070Spatrick   switch (VC.getModifiable()) {
723e5dd7070Spatrick   case Cl::CM_Untested: llvm_unreachable("Did not test modifiability");
724e5dd7070Spatrick   case Cl::CM_Modifiable: return MLV_Valid;
725e5dd7070Spatrick   case Cl::CM_RValue: llvm_unreachable("CM_RValue and CL_LValue don't match");
726e5dd7070Spatrick   case Cl::CM_Function: return MLV_NotObjectType;
727e5dd7070Spatrick   case Cl::CM_LValueCast:
728e5dd7070Spatrick     llvm_unreachable("CM_LValueCast and CL_LValue don't match");
729e5dd7070Spatrick   case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
730e5dd7070Spatrick   case Cl::CM_ConstQualified: return MLV_ConstQualified;
731e5dd7070Spatrick   case Cl::CM_ConstQualifiedField: return MLV_ConstQualifiedField;
732e5dd7070Spatrick   case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace;
733e5dd7070Spatrick   case Cl::CM_ArrayType: return MLV_ArrayType;
734e5dd7070Spatrick   case Cl::CM_IncompleteType: return MLV_IncompleteType;
735e5dd7070Spatrick   }
736e5dd7070Spatrick   llvm_unreachable("Unhandled modifiable type");
737e5dd7070Spatrick }
738