1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/AST/Expr.h" |
14 | #include "clang/AST/ASTContext.h" |
15 | #include "clang/AST/DeclCXX.h" |
16 | #include "clang/AST/DeclObjC.h" |
17 | #include "clang/AST/DeclTemplate.h" |
18 | #include "clang/AST/ExprCXX.h" |
19 | #include "clang/AST/ExprObjC.h" |
20 | #include "llvm/Support/ErrorHandling.h" |
21 | |
22 | using namespace clang; |
23 | |
24 | using Cl = Expr::Classification; |
25 | |
26 | static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E); |
27 | static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D); |
28 | static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T); |
29 | static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E); |
30 | static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E); |
31 | static Cl::Kinds ClassifyConditional(ASTContext &Ctx, |
32 | const Expr *trueExpr, |
33 | const Expr *falseExpr); |
34 | static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, |
35 | Cl::Kinds Kind, SourceLocation &Loc); |
36 | |
37 | Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { |
38 | (0) . __assert_fail ("!TR->isReferenceType() && \"Expressions can't have reference type.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 38, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!TR->isReferenceType() && "Expressions can't have reference type."); |
39 | |
40 | Cl::Kinds kind = ClassifyInternal(Ctx, this); |
41 | |
42 | |
43 | if (!Ctx.getLangOpts().CPlusPlus) { |
44 | |
45 | if (TR->isFunctionType() || TR == Ctx.OverloadTy) |
46 | kind = Cl::CL_Function; |
47 | |
48 | |
49 | |
50 | else if (TR->isVoidType() && !TR.hasQualifiers()) |
51 | kind = (kind == Cl::CL_LValue ? Cl::CL_AddressableVoid : Cl::CL_Void); |
52 | } |
53 | |
54 | |
55 | switch (kind) { |
56 | case Cl::CL_LValue: assert(getValueKind() == VK_LValue); break; |
57 | case Cl::CL_XValue: assert(getValueKind() == VK_XValue); break; |
58 | case Cl::CL_Function: |
59 | case Cl::CL_Void: |
60 | case Cl::CL_AddressableVoid: |
61 | case Cl::CL_DuplicateVectorComponents: |
62 | case Cl::CL_MemberFunction: |
63 | case Cl::CL_SubObjCPropertySetting: |
64 | case Cl::CL_ClassTemporary: |
65 | case Cl::CL_ArrayTemporary: |
66 | case Cl::CL_ObjCMessageRValue: |
67 | case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break; |
68 | } |
69 | |
70 | Cl::ModifiableType modifiable = Cl::CM_Untested; |
71 | if (Loc) |
72 | modifiable = IsModifiable(Ctx, this, kind, *Loc); |
73 | return Classification(kind, modifiable); |
74 | } |
75 | |
76 | |
77 | static Cl::Kinds ClassifyTemporary(QualType T) { |
78 | if (T->isRecordType()) |
79 | return Cl::CL_ClassTemporary; |
80 | if (T->isArrayType()) |
81 | return Cl::CL_ArrayTemporary; |
82 | |
83 | |
84 | |
85 | return Cl::CL_PRValue; |
86 | } |
87 | |
88 | static Cl::Kinds ClassifyExprValueKind(const LangOptions &Lang, |
89 | const Expr *E, |
90 | ExprValueKind Kind) { |
91 | switch (Kind) { |
92 | case VK_RValue: |
93 | return Lang.CPlusPlus ? ClassifyTemporary(E->getType()) : Cl::CL_PRValue; |
94 | case VK_LValue: |
95 | return Cl::CL_LValue; |
96 | case VK_XValue: |
97 | return Cl::CL_XValue; |
98 | } |
99 | llvm_unreachable("Invalid value category of implicit cast."); |
100 | } |
101 | |
102 | static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { |
103 | |
104 | const LangOptions &Lang = Ctx.getLangOpts(); |
105 | |
106 | switch (E->getStmtClass()) { |
107 | case Stmt::NoStmtClass: |
108 | #define ABSTRACT_STMT(Kind) |
109 | #define STMT(Kind, Base) case Expr::Kind##Class: |
110 | #define EXPR(Kind, Base) |
111 | #include "clang/AST/StmtNodes.inc" |
112 | llvm_unreachable("cannot classify a statement"); |
113 | |
114 | |
115 | case Expr::ObjCIsaExprClass: |
116 | |
117 | case Expr::StringLiteralClass: |
118 | |
119 | case Expr::ObjCEncodeExprClass: |
120 | |
121 | case Expr::PredefinedExprClass: |
122 | |
123 | case Expr::ObjCSubscriptRefExprClass: |
124 | case Expr::ObjCPropertyRefExprClass: |
125 | |
126 | case Expr::CXXTypeidExprClass: |
127 | |
128 | |
129 | case Expr::UnresolvedLookupExprClass: |
130 | case Expr::UnresolvedMemberExprClass: |
131 | case Expr::TypoExprClass: |
132 | case Expr::DependentCoawaitExprClass: |
133 | case Expr::CXXDependentScopeMemberExprClass: |
134 | case Expr::DependentScopeDeclRefExprClass: |
135 | |
136 | |
137 | case Expr::ObjCIvarRefExprClass: |
138 | case Expr::FunctionParmPackExprClass: |
139 | case Expr::MSPropertyRefExprClass: |
140 | case Expr::MSPropertySubscriptExprClass: |
141 | case Expr::OMPArraySectionExprClass: |
142 | return Cl::CL_LValue; |
143 | |
144 | |
145 | |
146 | case Expr::CompoundLiteralExprClass: |
147 | return !E->isLValue() ? ClassifyTemporary(E->getType()) : Cl::CL_LValue; |
148 | |
149 | |
150 | case Expr::CXXBoolLiteralExprClass: |
151 | case Expr::CXXPseudoDestructorExprClass: |
152 | case Expr::UnaryExprOrTypeTraitExprClass: |
153 | case Expr::CXXNewExprClass: |
154 | case Expr::CXXThisExprClass: |
155 | case Expr::CXXNullPtrLiteralExprClass: |
156 | case Expr::ImaginaryLiteralClass: |
157 | case Expr::GNUNullExprClass: |
158 | case Expr::OffsetOfExprClass: |
159 | case Expr::CXXThrowExprClass: |
160 | case Expr::ShuffleVectorExprClass: |
161 | case Expr::ConvertVectorExprClass: |
162 | case Expr::IntegerLiteralClass: |
163 | case Expr::FixedPointLiteralClass: |
164 | case Expr::CharacterLiteralClass: |
165 | case Expr::AddrLabelExprClass: |
166 | case Expr::CXXDeleteExprClass: |
167 | case Expr::ImplicitValueInitExprClass: |
168 | case Expr::BlockExprClass: |
169 | case Expr::FloatingLiteralClass: |
170 | case Expr::CXXNoexceptExprClass: |
171 | case Expr::CXXScalarValueInitExprClass: |
172 | case Expr::TypeTraitExprClass: |
173 | case Expr::ArrayTypeTraitExprClass: |
174 | case Expr::ExpressionTraitExprClass: |
175 | case Expr::ObjCSelectorExprClass: |
176 | case Expr::ObjCProtocolExprClass: |
177 | case Expr::ObjCStringLiteralClass: |
178 | case Expr::ObjCBoxedExprClass: |
179 | case Expr::ObjCArrayLiteralClass: |
180 | case Expr::ObjCDictionaryLiteralClass: |
181 | case Expr::ObjCBoolLiteralExprClass: |
182 | case Expr::ObjCAvailabilityCheckExprClass: |
183 | case Expr::ParenListExprClass: |
184 | case Expr::SizeOfPackExprClass: |
185 | case Expr::SubstNonTypeTemplateParmPackExprClass: |
186 | case Expr::AsTypeExprClass: |
187 | case Expr::ObjCIndirectCopyRestoreExprClass: |
188 | case Expr::AtomicExprClass: |
189 | case Expr::CXXFoldExprClass: |
190 | case Expr::ArrayInitLoopExprClass: |
191 | case Expr::ArrayInitIndexExprClass: |
192 | case Expr::NoInitExprClass: |
193 | case Expr::DesignatedInitUpdateExprClass: |
194 | return Cl::CL_PRValue; |
195 | |
196 | case Expr::ConstantExprClass: |
197 | return ClassifyInternal(Ctx, cast<ConstantExpr>(E)->getSubExpr()); |
198 | |
199 | |
200 | case Expr::SubstNonTypeTemplateParmExprClass: |
201 | return ClassifyInternal(Ctx, |
202 | cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement()); |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | case Expr::ArraySubscriptExprClass: |
209 | if (cast<ArraySubscriptExpr>(E)->getBase()->getType()->isVectorType()) |
210 | return ClassifyInternal(Ctx, cast<ArraySubscriptExpr>(E)->getBase()); |
211 | if (Lang.CPlusPlus11) { |
212 | |
213 | |
214 | auto *Base = cast<ArraySubscriptExpr>(E)->getBase()->IgnoreImpCasts(); |
215 | if (Base->getType()->isArrayType()) |
216 | return ClassifyInternal(Ctx, Base); |
217 | } |
218 | return Cl::CL_LValue; |
219 | |
220 | |
221 | |
222 | case Expr::DeclRefExprClass: |
223 | if (E->getType() == Ctx.UnknownAnyTy) |
224 | return isa<FunctionDecl>(cast<DeclRefExpr>(E)->getDecl()) |
225 | ? Cl::CL_PRValue : Cl::CL_LValue; |
226 | return ClassifyDecl(Ctx, cast<DeclRefExpr>(E)->getDecl()); |
227 | |
228 | |
229 | case Expr::MemberExprClass: |
230 | return ClassifyMemberExpr(Ctx, cast<MemberExpr>(E)); |
231 | |
232 | case Expr::UnaryOperatorClass: |
233 | switch (cast<UnaryOperator>(E)->getOpcode()) { |
234 | |
235 | |
236 | |
237 | case UO_Deref: |
238 | return Cl::CL_LValue; |
239 | |
240 | |
241 | case UO_Extension: |
242 | return ClassifyInternal(Ctx, cast<UnaryOperator>(E)->getSubExpr()); |
243 | |
244 | |
245 | |
246 | case UO_Real: |
247 | case UO_Imag: { |
248 | const Expr *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); |
249 | Cl::Kinds K = ClassifyInternal(Ctx, Op); |
250 | if (K != Cl::CL_LValue) return K; |
251 | |
252 | if (isa<ObjCPropertyRefExpr>(Op)) |
253 | return Cl::CL_SubObjCPropertySetting; |
254 | return Cl::CL_LValue; |
255 | } |
256 | |
257 | |
258 | |
259 | |
260 | case UO_PreInc: |
261 | case UO_PreDec: |
262 | return Lang.CPlusPlus ? Cl::CL_LValue : Cl::CL_PRValue; |
263 | |
264 | default: |
265 | return Cl::CL_PRValue; |
266 | } |
267 | |
268 | case Expr::OpaqueValueExprClass: |
269 | return ClassifyExprValueKind(Lang, E, E->getValueKind()); |
270 | |
271 | |
272 | case Expr::PseudoObjectExprClass: |
273 | return ClassifyExprValueKind(Lang, E, |
274 | cast<PseudoObjectExpr>(E)->getValueKind()); |
275 | |
276 | |
277 | |
278 | case Expr::ImplicitCastExprClass: |
279 | return ClassifyExprValueKind(Lang, E, E->getValueKind()); |
280 | |
281 | |
282 | |
283 | case Expr::ParenExprClass: |
284 | return ClassifyInternal(Ctx, cast<ParenExpr>(E)->getSubExpr()); |
285 | |
286 | |
287 | |
288 | |
289 | case Expr::GenericSelectionExprClass: |
290 | if (cast<GenericSelectionExpr>(E)->isResultDependent()) |
291 | return Cl::CL_PRValue; |
292 | return ClassifyInternal(Ctx,cast<GenericSelectionExpr>(E)->getResultExpr()); |
293 | |
294 | case Expr::BinaryOperatorClass: |
295 | case Expr::CompoundAssignOperatorClass: |
296 | |
297 | if (Lang.CPlusPlus) |
298 | return ClassifyBinaryOp(Ctx, cast<BinaryOperator>(E)); |
299 | return Cl::CL_PRValue; |
300 | |
301 | case Expr::CallExprClass: |
302 | case Expr::CXXOperatorCallExprClass: |
303 | case Expr::CXXMemberCallExprClass: |
304 | case Expr::UserDefinedLiteralClass: |
305 | case Expr::CUDAKernelCallExprClass: |
306 | return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType(Ctx)); |
307 | |
308 | |
309 | case Expr::ChooseExprClass: |
310 | return ClassifyInternal(Ctx, cast<ChooseExpr>(E)->getChosenSubExpr()); |
311 | |
312 | |
313 | |
314 | case Expr::ExtVectorElementExprClass: |
315 | if (cast<ExtVectorElementExpr>(E)->containsDuplicateElements()) |
316 | return Cl::CL_DuplicateVectorComponents; |
317 | if (cast<ExtVectorElementExpr>(E)->isArrow()) |
318 | return Cl::CL_LValue; |
319 | return ClassifyInternal(Ctx, cast<ExtVectorElementExpr>(E)->getBase()); |
320 | |
321 | |
322 | case Expr::CXXDefaultArgExprClass: |
323 | return ClassifyInternal(Ctx, cast<CXXDefaultArgExpr>(E)->getExpr()); |
324 | |
325 | |
326 | case Expr::CXXDefaultInitExprClass: |
327 | return ClassifyInternal(Ctx, cast<CXXDefaultInitExpr>(E)->getExpr()); |
328 | |
329 | |
330 | case Expr::CXXBindTemporaryExprClass: |
331 | return ClassifyInternal(Ctx, cast<CXXBindTemporaryExpr>(E)->getSubExpr()); |
332 | |
333 | |
334 | case Expr::ExprWithCleanupsClass: |
335 | return ClassifyInternal(Ctx, cast<ExprWithCleanups>(E)->getSubExpr()); |
336 | |
337 | |
338 | case Expr::CStyleCastExprClass: |
339 | case Expr::CXXFunctionalCastExprClass: |
340 | case Expr::CXXStaticCastExprClass: |
341 | case Expr::CXXDynamicCastExprClass: |
342 | case Expr::CXXReinterpretCastExprClass: |
343 | case Expr::CXXConstCastExprClass: |
344 | case Expr::ObjCBridgedCastExprClass: |
345 | |
346 | if (!Lang.CPlusPlus) return Cl::CL_PRValue; |
347 | return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten()); |
348 | |
349 | case Expr::CXXUnresolvedConstructExprClass: |
350 | return ClassifyUnnamed(Ctx, |
351 | cast<CXXUnresolvedConstructExpr>(E)->getTypeAsWritten()); |
352 | |
353 | case Expr::BinaryConditionalOperatorClass: { |
354 | if (!Lang.CPlusPlus) return Cl::CL_PRValue; |
355 | const auto *co = cast<BinaryConditionalOperator>(E); |
356 | return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); |
357 | } |
358 | |
359 | case Expr::ConditionalOperatorClass: { |
360 | |
361 | if (!Lang.CPlusPlus) return Cl::CL_PRValue; |
362 | const auto *co = cast<ConditionalOperator>(E); |
363 | return ClassifyConditional(Ctx, co->getTrueExpr(), co->getFalseExpr()); |
364 | } |
365 | |
366 | |
367 | |
368 | case Expr::ObjCMessageExprClass: |
369 | if (const ObjCMethodDecl *Method = |
370 | cast<ObjCMessageExpr>(E)->getMethodDecl()) { |
371 | Cl::Kinds kind = ClassifyUnnamed(Ctx, Method->getReturnType()); |
372 | return (kind == Cl::CL_PRValue) ? Cl::CL_ObjCMessageRValue : kind; |
373 | } |
374 | return Cl::CL_PRValue; |
375 | |
376 | |
377 | case Expr::CXXConstructExprClass: |
378 | case Expr::CXXInheritedCtorInitExprClass: |
379 | case Expr::CXXTemporaryObjectExprClass: |
380 | case Expr::LambdaExprClass: |
381 | case Expr::CXXStdInitializerListExprClass: |
382 | return Cl::CL_ClassTemporary; |
383 | |
384 | case Expr::VAArgExprClass: |
385 | return ClassifyUnnamed(Ctx, E->getType()); |
386 | |
387 | case Expr::DesignatedInitExprClass: |
388 | return ClassifyInternal(Ctx, cast<DesignatedInitExpr>(E)->getInit()); |
389 | |
390 | case Expr::StmtExprClass: { |
391 | const CompoundStmt *S = cast<StmtExpr>(E)->getSubStmt(); |
392 | if (const auto *LastExpr = dyn_cast_or_null<Expr>(S->body_back())) |
393 | return ClassifyUnnamed(Ctx, LastExpr->getType()); |
394 | return Cl::CL_PRValue; |
395 | } |
396 | |
397 | case Expr::CXXUuidofExprClass: |
398 | return Cl::CL_LValue; |
399 | |
400 | case Expr::PackExpansionExprClass: |
401 | return ClassifyInternal(Ctx, cast<PackExpansionExpr>(E)->getPattern()); |
402 | |
403 | case Expr::MaterializeTemporaryExprClass: |
404 | return cast<MaterializeTemporaryExpr>(E)->isBoundToLvalueReference() |
405 | ? Cl::CL_LValue |
406 | : Cl::CL_XValue; |
407 | |
408 | case Expr::InitListExprClass: |
409 | |
410 | |
411 | |
412 | |
413 | if (E->isRValue()) |
414 | return ClassifyExprValueKind(Lang, E, E->getValueKind()); |
415 | (0) . __assert_fail ("cast(E)->getNumInits() == 1 && \"Only 1-element init lists can be glvalues.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 416, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(cast<InitListExpr>(E)->getNumInits() == 1 && |
416 | (0) . __assert_fail ("cast(E)->getNumInits() == 1 && \"Only 1-element init lists can be glvalues.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 416, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "Only 1-element init lists can be glvalues."); |
417 | return ClassifyInternal(Ctx, cast<InitListExpr>(E)->getInit(0)); |
418 | |
419 | case Expr::CoawaitExprClass: |
420 | case Expr::CoyieldExprClass: |
421 | return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr()); |
422 | } |
423 | |
424 | llvm_unreachable("unhandled expression kind in classification"); |
425 | } |
426 | |
427 | |
428 | |
429 | static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) { |
430 | |
431 | |
432 | |
433 | |
434 | |
435 | |
436 | |
437 | if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) |
438 | return Cl::CL_MemberFunction; |
439 | |
440 | bool islvalue; |
441 | if (const auto *NTTParm = dyn_cast<NonTypeTemplateParmDecl>(D)) |
442 | islvalue = NTTParm->getType()->isReferenceType(); |
443 | else |
444 | islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || |
445 | isa<IndirectFieldDecl>(D) || |
446 | isa<BindingDecl>(D) || |
447 | (Ctx.getLangOpts().CPlusPlus && |
448 | (isa<FunctionDecl>(D) || isa<MSPropertyDecl>(D) || |
449 | isa<FunctionTemplateDecl>(D))); |
450 | |
451 | return islvalue ? Cl::CL_LValue : Cl::CL_PRValue; |
452 | } |
453 | |
454 | |
455 | |
456 | |
457 | static Cl::Kinds ClassifyUnnamed(ASTContext &Ctx, QualType T) { |
458 | |
459 | if (!Ctx.getLangOpts().CPlusPlus) return Cl::CL_PRValue; |
460 | |
461 | |
462 | |
463 | |
464 | |
465 | if (T->isLValueReferenceType()) |
466 | return Cl::CL_LValue; |
467 | const auto *RV = T->getAs<RValueReferenceType>(); |
468 | if (!RV) |
469 | return ClassifyTemporary(T); |
470 | |
471 | return RV->getPointeeType()->isFunctionType() ? Cl::CL_LValue : Cl::CL_XValue; |
472 | } |
473 | |
474 | static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { |
475 | if (E->getType() == Ctx.UnknownAnyTy) |
476 | return (isa<FunctionDecl>(E->getMemberDecl()) |
477 | ? Cl::CL_PRValue : Cl::CL_LValue); |
478 | |
479 | |
480 | if (!Ctx.getLangOpts().CPlusPlus) { |
481 | |
482 | |
483 | |
484 | if (E->isArrow()) |
485 | return Cl::CL_LValue; |
486 | |
487 | Expr *Base = E->getBase()->IgnoreParens(); |
488 | if (isa<ObjCPropertyRefExpr>(Base)) |
489 | return Cl::CL_SubObjCPropertySetting; |
490 | return ClassifyInternal(Ctx, Base); |
491 | } |
492 | |
493 | NamedDecl *Member = E->getMemberDecl(); |
494 | |
495 | |
496 | |
497 | if (const auto *Value = dyn_cast<ValueDecl>(Member)) |
498 | if (Value->getType()->isReferenceType()) |
499 | return Cl::CL_LValue; |
500 | |
501 | |
502 | |
503 | if (isa<VarDecl>(Member) && Member->getDeclContext()->isRecord()) |
504 | return Cl::CL_LValue; |
505 | |
506 | |
507 | |
508 | |
509 | if (isa<FieldDecl>(Member)) { |
510 | |
511 | if (E->isArrow()) |
512 | return Cl::CL_LValue; |
513 | Expr *Base = E->getBase()->IgnoreParenImpCasts(); |
514 | if (isa<ObjCPropertyRefExpr>(Base)) |
515 | return Cl::CL_SubObjCPropertySetting; |
516 | return ClassifyInternal(Ctx, E->getBase()); |
517 | } |
518 | |
519 | |
520 | |
521 | |
522 | |
523 | if (const auto *Method = dyn_cast<CXXMethodDecl>(Member)) |
524 | return Method->isStatic() ? Cl::CL_LValue : Cl::CL_MemberFunction; |
525 | |
526 | |
527 | |
528 | return Cl::CL_PRValue; |
529 | } |
530 | |
531 | static Cl::Kinds ClassifyBinaryOp(ASTContext &Ctx, const BinaryOperator *E) { |
532 | (0) . __assert_fail ("Ctx.getLangOpts().CPlusPlus && \"This is only relevant for C++.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 533, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Ctx.getLangOpts().CPlusPlus && |
533 | (0) . __assert_fail ("Ctx.getLangOpts().CPlusPlus && \"This is only relevant for C++.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 533, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "This is only relevant for C++."); |
534 | |
535 | |
536 | if (E->isAssignmentOp()) |
537 | return (E->getLHS()->getObjectKind() == OK_ObjCProperty |
538 | ? Cl::CL_PRValue : Cl::CL_LValue); |
539 | |
540 | |
541 | |
542 | if (E->getOpcode() == BO_Comma) |
543 | return ClassifyInternal(Ctx, E->getRHS()); |
544 | |
545 | |
546 | |
547 | |
548 | if (E->getOpcode() == BO_PtrMemD) |
549 | return (E->getType()->isFunctionType() || |
550 | E->hasPlaceholderType(BuiltinType::BoundMember)) |
551 | ? Cl::CL_MemberFunction |
552 | : ClassifyInternal(Ctx, E->getLHS()); |
553 | |
554 | |
555 | |
556 | if (E->getOpcode() == BO_PtrMemI) |
557 | return (E->getType()->isFunctionType() || |
558 | E->hasPlaceholderType(BuiltinType::BoundMember)) |
559 | ? Cl::CL_MemberFunction |
560 | : Cl::CL_LValue; |
561 | |
562 | |
563 | return Cl::CL_PRValue; |
564 | } |
565 | |
566 | static Cl::Kinds ClassifyConditional(ASTContext &Ctx, const Expr *True, |
567 | const Expr *False) { |
568 | (0) . __assert_fail ("Ctx.getLangOpts().CPlusPlus && \"This is only relevant for C++.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 569, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Ctx.getLangOpts().CPlusPlus && |
569 | (0) . __assert_fail ("Ctx.getLangOpts().CPlusPlus && \"This is only relevant for C++.\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 569, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "This is only relevant for C++."); |
570 | |
571 | |
572 | |
573 | |
574 | if (True->getType()->isVoidType() || False->getType()->isVoidType()) { |
575 | |
576 | |
577 | |
578 | bool TrueIsThrow = isa<CXXThrowExpr>(True->IgnoreParenImpCasts()); |
579 | bool FalseIsThrow = isa<CXXThrowExpr>(False->IgnoreParenImpCasts()); |
580 | if (const Expr *NonThrow = TrueIsThrow ? (FalseIsThrow ? nullptr : False) |
581 | : (FalseIsThrow ? True : nullptr)) |
582 | return ClassifyInternal(Ctx, NonThrow); |
583 | |
584 | |
585 | return Cl::CL_PRValue; |
586 | } |
587 | |
588 | |
589 | |
590 | |
591 | |
592 | |
593 | Cl::Kinds LCl = ClassifyInternal(Ctx, True), |
594 | RCl = ClassifyInternal(Ctx, False); |
595 | return LCl == RCl ? LCl : Cl::CL_PRValue; |
596 | } |
597 | |
598 | static Cl::ModifiableType IsModifiable(ASTContext &Ctx, const Expr *E, |
599 | Cl::Kinds Kind, SourceLocation &Loc) { |
600 | |
601 | |
602 | if (Kind == Cl::CL_PRValue) { |
603 | |
604 | |
605 | if (const auto *CE = dyn_cast<ExplicitCastExpr>(E->IgnoreParens())) { |
606 | if (CE->getSubExpr()->IgnoreParenImpCasts()->isLValue()) { |
607 | Loc = CE->getExprLoc(); |
608 | return Cl::CM_LValueCast; |
609 | } |
610 | } |
611 | } |
612 | if (Kind != Cl::CL_LValue) |
613 | return Cl::CM_RValue; |
614 | |
615 | |
616 | |
617 | if (Ctx.getLangOpts().CPlusPlus && E->getType()->isFunctionType()) |
618 | return Cl::CM_Function; |
619 | |
620 | |
621 | |
622 | if (const auto *Expr = dyn_cast<ObjCPropertyRefExpr>(E)) { |
623 | if (Expr->isImplicitProperty() && |
624 | Expr->getImplicitPropertySetter() == nullptr) |
625 | return Cl::CM_NoSetterProperty; |
626 | } |
627 | |
628 | CanQualType CT = Ctx.getCanonicalType(E->getType()); |
629 | |
630 | if (CT.isConstQualified()) |
631 | return Cl::CM_ConstQualified; |
632 | if (Ctx.getLangOpts().OpenCL && |
633 | CT.getQualifiers().getAddressSpace() == LangAS::opencl_constant) |
634 | return Cl::CM_ConstAddrSpace; |
635 | |
636 | |
637 | if (CT->isArrayType()) |
638 | return Cl::CM_ArrayType; |
639 | |
640 | if (CT->isIncompleteType()) |
641 | return Cl::CM_IncompleteType; |
642 | |
643 | |
644 | if (const RecordType *R = CT->getAs<RecordType>()) |
645 | if (R->hasConstFields()) |
646 | return Cl::CM_ConstQualifiedField; |
647 | |
648 | return Cl::CM_Modifiable; |
649 | } |
650 | |
651 | Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const { |
652 | Classification VC = Classify(Ctx); |
653 | switch (VC.getKind()) { |
654 | case Cl::CL_LValue: return LV_Valid; |
655 | case Cl::CL_XValue: return LV_InvalidExpression; |
656 | case Cl::CL_Function: return LV_NotObjectType; |
657 | case Cl::CL_Void: return LV_InvalidExpression; |
658 | case Cl::CL_AddressableVoid: return LV_IncompleteVoidType; |
659 | case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents; |
660 | case Cl::CL_MemberFunction: return LV_MemberFunction; |
661 | case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting; |
662 | case Cl::CL_ClassTemporary: return LV_ClassTemporary; |
663 | case Cl::CL_ArrayTemporary: return LV_ArrayTemporary; |
664 | case Cl::CL_ObjCMessageRValue: return LV_InvalidMessageExpression; |
665 | case Cl::CL_PRValue: return LV_InvalidExpression; |
666 | } |
667 | llvm_unreachable("Unhandled kind"); |
668 | } |
669 | |
670 | Expr::isModifiableLvalueResult |
671 | Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { |
672 | SourceLocation dummy; |
673 | Classification VC = ClassifyModifiable(Ctx, Loc ? *Loc : dummy); |
674 | switch (VC.getKind()) { |
675 | case Cl::CL_LValue: break; |
676 | case Cl::CL_XValue: return MLV_InvalidExpression; |
677 | case Cl::CL_Function: return MLV_NotObjectType; |
678 | case Cl::CL_Void: return MLV_InvalidExpression; |
679 | case Cl::CL_AddressableVoid: return MLV_IncompleteVoidType; |
680 | case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents; |
681 | case Cl::CL_MemberFunction: return MLV_MemberFunction; |
682 | case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting; |
683 | case Cl::CL_ClassTemporary: return MLV_ClassTemporary; |
684 | case Cl::CL_ArrayTemporary: return MLV_ArrayTemporary; |
685 | case Cl::CL_ObjCMessageRValue: return MLV_InvalidMessageExpression; |
686 | case Cl::CL_PRValue: |
687 | return VC.getModifiable() == Cl::CM_LValueCast ? |
688 | MLV_LValueCast : MLV_InvalidExpression; |
689 | } |
690 | (0) . __assert_fail ("VC.getKind() == Cl..CL_LValue && \"Unhandled kind\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/ExprClassification.cpp", 690, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(VC.getKind() == Cl::CL_LValue && "Unhandled kind"); |
691 | switch (VC.getModifiable()) { |
692 | case Cl::CM_Untested: llvm_unreachable("Did not test modifiability"); |
693 | case Cl::CM_Modifiable: return MLV_Valid; |
694 | case Cl::CM_RValue: llvm_unreachable("CM_RValue and CL_LValue don't match"); |
695 | case Cl::CM_Function: return MLV_NotObjectType; |
696 | case Cl::CM_LValueCast: |
697 | llvm_unreachable("CM_LValueCast and CL_LValue don't match"); |
698 | case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty; |
699 | case Cl::CM_ConstQualified: return MLV_ConstQualified; |
700 | case Cl::CM_ConstQualifiedField: return MLV_ConstQualifiedField; |
701 | case Cl::CM_ConstAddrSpace: return MLV_ConstAddrSpace; |
702 | case Cl::CM_ArrayType: return MLV_ArrayType; |
703 | case Cl::CM_IncompleteType: return MLV_IncompleteType; |
704 | } |
705 | llvm_unreachable("Unhandled modifiable type"); |
706 | } |
707 | |