clang 24.0.0git
CIRGenExprAggregate.cpp
Go to the documentation of this file.
1//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions ===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit Aggregate Expr nodes as CIR code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenBuilder.h"
15#include "CIRGenFunction.h"
16#include "CIRGenValue.h"
17#include "mlir/IR/Builders.h"
19
20#include "clang/AST/Expr.h"
23#include "llvm/IR/Value.h"
24#include <cstdint>
25
26using namespace clang;
27using namespace clang::CIRGen;
28
29namespace {
30// FIXME(cir): This should be a common helper between CIRGen
31// and traditional CodeGen
32/// Is the value of the given expression possibly a reference to or
33/// into a __block variable?
34static bool isBlockVarRef(const Expr *e) {
35 // Make sure we look through parens.
36 e = e->IgnoreParens();
37
38 // Check for a direct reference to a __block variable.
39 if (const DeclRefExpr *dre = dyn_cast<DeclRefExpr>(e)) {
40 const VarDecl *var = dyn_cast<VarDecl>(dre->getDecl());
41 return (var && var->hasAttr<BlocksAttr>());
42 }
43
44 // More complicated stuff.
45
46 // Binary operators.
47 if (const BinaryOperator *op = dyn_cast<BinaryOperator>(e)) {
48 // For an assignment or pointer-to-member operation, just care
49 // about the LHS.
50 if (op->isAssignmentOp() || op->isPtrMemOp())
51 return isBlockVarRef(op->getLHS());
52
53 // For a comma, just care about the RHS.
54 if (op->getOpcode() == BO_Comma)
55 return isBlockVarRef(op->getRHS());
56
57 // FIXME: pointer arithmetic?
58 return false;
59
60 // Check both sides of a conditional operator.
61 } else if (const AbstractConditionalOperator *op =
62 dyn_cast<AbstractConditionalOperator>(e)) {
63 return isBlockVarRef(op->getTrueExpr()) ||
64 isBlockVarRef(op->getFalseExpr());
65
66 // OVEs are required to support BinaryConditionalOperators.
67 } else if (const OpaqueValueExpr *op = dyn_cast<OpaqueValueExpr>(e)) {
68 if (const Expr *src = op->getSourceExpr())
69 return isBlockVarRef(src);
70
71 // Casts are necessary to get things like (*(int*)&var) = foo().
72 // We don't really care about the kind of cast here, except
73 // we don't want to look through l2r casts, because it's okay
74 // to get the *value* in a __block variable.
75 } else if (const CastExpr *cast = dyn_cast<CastExpr>(e)) {
76 if (cast->getCastKind() == CK_LValueToRValue)
77 return false;
78 return isBlockVarRef(cast->getSubExpr());
79
80 // Handle unary operators. Again, just aggressively look through
81 // it, ignoring the operation.
82 } else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
83 return isBlockVarRef(uop->getSubExpr());
84
85 // Look into the base of a field access.
86 } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
87 return isBlockVarRef(mem->getBase());
88
89 // Look into the base of a subscript.
90 } else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(e)) {
91 return isBlockVarRef(sub->getBase());
92 }
93
94 return false;
95}
96
97class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
98
99 CIRGenFunction &cgf;
100 AggValueSlot dest;
101
102 // Calls `fn` with a valid return value slot, potentially creating a temporary
103 // to do so. If a temporary is created, an appropriate copy into `Dest` will
104 // be emitted, as will lifetime markers.
105 //
106 // The given function should take a ReturnValueSlot, and return an RValue that
107 // points to said slot.
108 void withReturnValueSlot(const Expr *e,
109 llvm::function_ref<RValue(ReturnValueSlot)> fn);
110
111 AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
112 if (!dest.isIgnored())
113 return dest;
114 return cgf.createAggTemp(t, loc, "agg.tmp.ensured");
115 }
116
117 void ensureDest(mlir::Location loc, QualType ty) {
118 if (!dest.isIgnored())
119 return;
120 dest = cgf.createAggTemp(ty, loc, "agg.tmp.ensured");
121 }
122
123public:
124 AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
125 : cgf(cgf), dest(dest) {}
126
127 /// Given an expression with aggregate type that represents a value lvalue,
128 /// this method emits the address of the lvalue, then loads the result into
129 /// DestPtr.
130 void emitAggLoadOfLValue(const Expr *e);
131
132 void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
133 Expr *exprToVisit, ArrayRef<Expr *> args,
134 Expr *arrayFiller);
135
136 void emitFinalDestCopy(QualType type, RValue src);
137
138 /// Perform the final copy to DestPtr, if desired.
139 void emitFinalDestCopy(QualType type, const LValue &src,
140 CIRGenFunction::ExprValueKind srcValueKind =
142
143 void emitCopy(QualType type, const AggValueSlot &dest,
144 const AggValueSlot &src);
145
146 void emitInitializationToLValue(Expr *e, LValue lv);
147
148 void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
149
150 void emitComparisonResult(const Expr *e, mlir::Location loc,
151 const ComparisonCategoryInfo &cmpInfo,
152 mlir::Value resultValue);
153
154 void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
155
156 void VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
157 emitAggLoadOfLValue(e);
158 }
159
160 void VisitCallExpr(const CallExpr *e);
161 void VisitStmtExpr(const StmtExpr *e) {
162 CIRGenFunction::StmtExprEvaluation eval(cgf);
163 Address retAlloca =
164 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
165 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca, dest);
166 }
167
168 void VisitBinAssign(const BinaryOperator *e) {
169 // For an assignment to work, the value on the right has
170 // to be compatible with the value on the left.
171 assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
172 e->getRHS()->getType()) &&
173 "Invalid assignment");
174
175 if (isBlockVarRef(e->getLHS()) &&
176 e->getRHS()->HasSideEffects(cgf.getContext())) {
177 cgf.cgm.errorNYI(e->getSourceRange(),
178 "block var reference with side effects");
179 return;
180 }
181
182 LValue lhs = cgf.emitLValue(e->getLHS());
183
184 // If we have an atomic type, evaluate into the destination and then
185 // do an atomic copy.
186 if (lhs.getType()->isAtomicType() ||
187 cgf.isLValueSuitableForInlineAtomic(lhs)) {
188 ensureDest(cgf.getLoc(e->getExprLoc()), e->getRHS()->getType());
189 Visit(e->getRHS());
190 cgf.emitAtomicStore(dest.asRValue(), lhs, /*isInit=*/false);
191 return;
192 }
193
194 // Codegen the RHS so that it stores directly into the LHS.
196 AggValueSlot lhsSlot = AggValueSlot::forLValue(
199
200 // A non-volatile aggregate destination might have volatile member.
201 if (!lhsSlot.isVolatile() && cgf.hasVolatileMember(e->getLHS()->getType()))
202 lhsSlot.setVolatile(true);
203
204 cgf.emitAggExpr(e->getRHS(), lhsSlot);
205
206 // Copy into the destination if the assignment isn't ignored.
207 emitFinalDestCopy(e->getType(), lhs);
208
209 if (!dest.isIgnored() && !dest.isExternallyDestructed() &&
211 cgf.pushDestroy(QualType::DK_nontrivial_c_struct, dest.getAddress(),
212 e->getType());
213 }
214
215 void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
216
217 void VisitInitListExpr(InitListExpr *e);
218 void VisitCXXConstructExpr(const CXXConstructExpr *e);
219
220 void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
221 FieldDecl *initializedFieldInUnion,
222 Expr *arrayFiller);
223 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
224 CIRGenFunction::CXXDefaultInitExprScope Scope(cgf, die);
225 Visit(die->getExpr());
226 }
227 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *e) {
228 // Ensure that we have a slot, but if we already do, remember
229 // whether it was externally destructed.
230 bool wasExternallyDestructed = dest.isExternallyDestructed();
231 ensureDest(cgf.getLoc(e->getSourceRange()), e->getType());
232
233 // We're going to push a destructor if there isn't already one.
234 dest.setExternallyDestructed();
235
236 Visit(e->getSubExpr());
237
238 // Push that destructor we promised.
239 if (!wasExternallyDestructed)
240 cgf.emitCXXTemporary(e->getTemporary(), e->getType(), dest.getAddress());
241 }
242 void VisitLambdaExpr(LambdaExpr *e);
243 void VisitExprWithCleanups(ExprWithCleanups *e);
244
245 /// Attempt to look through various unimportant expressions to find a
246 /// cast of the given kind.
247 static Expr *findPeephole(Expr *op, CastKind kind, const ASTContext &ctx) {
248 op = op->IgnoreParenNoopCasts(ctx);
249 if (auto *castE = dyn_cast<CastExpr>(op)) {
250 if (castE->getCastKind() == kind)
251 return castE->getSubExpr();
252 }
253 return nullptr;
254 }
255
256 // Stubs -- These should be moved up when they are implemented.
257 void VisitCastExpr(CastExpr *e) {
258 switch (e->getCastKind()) {
259 case CK_LValueToRValueBitCast: {
260 if (dest.isIgnored()) {
261 cgf.emitAnyExpr(e->getSubExpr(), AggValueSlot::ignored(),
262 /*ignoreResult=*/true);
263 break;
264 }
265
266 LValue sourceLV = cgf.emitLValue(e->getSubExpr());
267 Address sourceAddress =
268 sourceLV.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
269 Address destAddress =
270 dest.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
271
272 mlir::Location loc = cgf.getLoc(e->getExprLoc());
273
274 mlir::Value sizeVal = cgf.getBuilder().getConstInt(
275 loc, cgf.sizeTy,
276 cgf.getContext().getTypeSizeInChars(e->getType()).getQuantity());
277 cgf.getBuilder().createMemCpy(loc, destAddress.getPointer(),
278 sourceAddress.getPointer(), sizeVal);
279
280 break;
281 }
282
283 case CK_NonAtomicToAtomic:
284 case CK_AtomicToNonAtomic: {
285 bool isToAtomic = (e->getCastKind() == CK_NonAtomicToAtomic);
286
287 // Determine the atomic and value types.
288 QualType atomicType = e->getSubExpr()->getType();
289 QualType valueType = e->getType();
290 if (isToAtomic)
291 std::swap(atomicType, valueType);
292
293 assert(atomicType->isAtomicType());
294 assert(cgf.getContext().hasSameUnqualifiedType(
295 valueType, atomicType->castAs<AtomicType>()->getValueType()));
296
297 // Just recurse normally if we're ignoring the result or the
298 // atomic type doesn't change representation.
299 if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(atomicType))
300 return Visit(e->getSubExpr());
301
302 // These two cases are reverses of each other; try to peephole them.
303 CastKind peepholeTarget =
304 (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
305
306 // These two cases are reverses of each other; try to peephole them.
307 if (Expr *op =
308 findPeephole(e->getSubExpr(), peepholeTarget, cgf.getContext())) {
309 assert(cgf.getContext().hasSameUnqualifiedType(op->getType(),
310 e->getType()) &&
311 "peephole significantly changed types?");
312 return Visit(op);
313 }
314
315 // If we're converting an r-value of non-atomic type to an r-value
316 // of atomic type, just emit directly into the relevant sub-object.
317 if (isToAtomic) {
318 AggValueSlot valueDest = dest;
319 if (!valueDest.isIgnored() && cgf.cgm.isPaddedAtomicType(atomicType)) {
320 // Zero-initialize. (Strictly speaking, we only need to initialize
321 // the padding at the end, but this is simpler.)
322 mlir::Location loc = cgf.getLoc(e->getExprLoc());
323 if (!dest.isZeroed())
324 cgf.emitNullInitialization(loc, dest.getAddress(), atomicType);
325
326 Address valueAddr = cgf.getBuilder().createGetMember(
327 loc, valueDest.getAddress(), "value_addr", 0);
328
330 valueDest = AggValueSlot::forAddr(
331 valueAddr, valueDest.getQualifiers(),
332 valueDest.isExternallyDestructed(),
335 }
336
337 cgf.emitAggExpr(e->getSubExpr(), valueDest);
338 return;
339 }
340
341 mlir::Location loc = cgf.getLoc(e->getExprLoc());
342 AggValueSlot atomicSlot = cgf.createAggTemp(atomicType, loc);
343 cgf.emitAggExpr(e->getSubExpr(), atomicSlot);
344
345 Address valueAddr = cgf.getBuilder().createGetMember(
346 loc, atomicSlot.getAddress(), "value_addr", 0);
347 RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile());
348 return emitFinalDestCopy(valueType, rvalue);
349 }
350 case CK_LValueToRValue:
351 // If we're loading from a volatile type, force the destination
352 // into existence.
354 cgf.cgm.errorNYI(e->getSourceRange(),
355 "AggExprEmitter: volatile lvalue-to-rvalue cast");
356 [[fallthrough]];
357 case CK_NoOp:
358 case CK_UserDefinedConversion:
359 case CK_ConstructorConversion:
360 assert(cgf.getContext().hasSameUnqualifiedType(e->getSubExpr()->getType(),
361 e->getType()) &&
362 "Implicit cast types must be compatible");
363 Visit(e->getSubExpr());
364 break;
365 case CK_ToUnion: {
366 if (dest.isIgnored()) {
367 cgf.emitAnyExpr(e->getSubExpr(), AggValueSlot::ignored(),
368 /*ignoreResult=*/true);
369 break;
370 }
371 QualType ty = e->getSubExpr()->getType();
372 Address castPtr = dest.getAddress().withElementType(cgf.getBuilder(),
373 cgf.convertType(ty));
374 emitInitializationToLValue(e->getSubExpr(),
375 cgf.makeAddrLValue(castPtr, ty));
376 break;
377 }
378 default:
379 cgf.cgm.errorNYI(e->getSourceRange(),
380 std::string("AggExprEmitter: VisitCastExpr: ") +
381 e->getCastKindName());
382 break;
383 }
384 }
385 void VisitStmt(Stmt *s) {
386 cgf.cgm.errorNYI(s->getSourceRange(),
387 std::string("AggExprEmitter::VisitStmt: ") +
388 s->getStmtClassName());
389 }
390 void VisitParenExpr(ParenExpr *pe) { Visit(pe->getSubExpr()); }
391 void VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
392 Visit(ge->getResultExpr());
393 }
394 void VisitCoawaitExpr(CoawaitExpr *e) {
395 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCoawaitExpr");
396 }
397 void VisitCoyieldExpr(CoyieldExpr *e) {
398 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCoyieldExpr");
399 }
400 void VisitUnaryCoawait(UnaryOperator *e) {
401 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitUnaryCoawait");
402 }
403 void VisitUnaryExtension(UnaryOperator *e) { Visit(e->getSubExpr()); }
404 void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
405 cgf.cgm.errorNYI(e->getSourceRange(),
406 "AggExprEmitter: VisitSubstNonTypeTemplateParmExpr");
407 }
408 void VisitConstantExpr(ConstantExpr *e) {
409 ensureDest(cgf.getLoc(e->getSourceRange()), e->getType());
410
411 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
412 mlir::Value resultVal = cgf.getBuilder().getConstant(
413 cgf.getLoc(e->getSourceRange()), mlir::cast<mlir::TypedAttr>(result));
414 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->getType());
415 cgf.emitStoreThroughLValue(RValue::get(resultVal), destLVal);
416 return;
417 }
418
419 // It isn't clear that it is possible to get to here, but this branch is
420 // present in classic codegen, so we leave it here too.
421 return Visit(e->getSubExpr());
422 }
423 void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
424 void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
425 void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
426 void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
427
428 void VisitPredefinedExpr(const PredefinedExpr *e) { emitAggLoadOfLValue(e); }
429 void VisitBinaryOperator(const BinaryOperator *e) {
430 cgf.cgm.errorNYI(e->getSourceRange(),
431 "AggExprEmitter: VisitBinaryOperator");
432 }
433 void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *e) {
434 cgf.cgm.errorNYI(e->getSourceRange(),
435 "AggExprEmitter: VisitPointerToDataMemberBinaryOperator");
436 }
437 void VisitBinComma(const BinaryOperator *e) {
438 cgf.emitIgnoredExpr(e->getLHS());
439 Visit(e->getRHS());
440 }
441 void VisitBinCmp(const BinaryOperator *e) {
442 assert(cgf.getContext().hasSameType(e->getLHS()->getType(),
443 e->getRHS()->getType()));
444 const ComparisonCategoryInfo &cmpInfo =
445 cgf.getContext().CompCategories.getInfoForType(e->getType());
446 assert(cmpInfo.Record->isTriviallyCopyable() &&
447 "cannot copy non-trivially copyable aggregate");
448
449 QualType argTy = e->getLHS()->getType();
450
451 if (!argTy->isIntegralOrEnumerationType() && !argTy->isRealFloatingType() &&
452 !argTy->isNullPtrType() && !argTy->isPointerType() &&
453 !argTy->isMemberPointerType() && !argTy->isAnyComplexType())
454 cgf.cgm.errorNYI(e->getBeginLoc(), "aggregate three-way comparison");
455
456 mlir::Location loc = cgf.getLoc(e->getSourceRange());
457 CIRGenBuilderTy &builder = cgf.getBuilder();
458
459 if (e->getType()->isAnyComplexType())
460 cgf.cgm.errorNYI(e->getBeginLoc(), "VisitBinCmp: complex type");
461
462 if (e->getType()->isAggregateType())
463 cgf.cgm.errorNYI(e->getBeginLoc(), "VisitBinCmp: aggregate type");
464
465 mlir::Value lhs = cgf.emitAnyExpr(e->getLHS()).getValue();
466 mlir::Value rhs = cgf.emitAnyExpr(e->getRHS()).getValue();
467
468 mlir::Value resultScalar;
469 if (argTy->isNullPtrType()) {
470 resultScalar =
471 builder.getConstInt(loc, cmpInfo.getEqualOrEquiv()->getIntValue());
472 } else {
473 llvm::APSInt ltRes = cmpInfo.getLess()->getIntValue();
474 llvm::APSInt eqRes = cmpInfo.getEqualOrEquiv()->getIntValue();
475 llvm::APSInt gtRes = cmpInfo.getGreater()->getIntValue();
476 if (!cmpInfo.isPartial()) {
477 cir::CmpOrdering ordering = cmpInfo.isStrong()
478 ? cir::CmpOrdering::Strong
479 : cir::CmpOrdering::Weak;
480 resultScalar = builder.createThreeWayCmpTotalOrdering(
481 loc, lhs, rhs, ltRes, eqRes, gtRes, ordering);
482 } else {
483 // Partial ordering.
484 llvm::APSInt unorderedRes = cmpInfo.getUnordered()->getIntValue();
485 resultScalar = builder.createThreeWayCmpPartialOrdering(
486 loc, lhs, rhs, ltRes, eqRes, gtRes, unorderedRes);
487 }
488 }
489
490 emitComparisonResult(e, loc, cmpInfo, resultScalar);
491 }
492
493 void VisitTypeTraitExpr(const TypeTraitExpr *e) {
494 assert(e->isStoredAsComparisonResult() &&
495 "expected a strong_ordering type trait with a stored value");
496
497 const ComparisonCategoryInfo &cmpInfo =
498 cgf.getContext().CompCategories.getInfoForType(e->getType());
499 const auto result =
500 ComparisonCategoryResult(e->getAPValue().getInt().getZExtValue());
501 mlir::Location loc = cgf.getLoc(e->getSourceRange());
502 mlir::Value resultValue = cgf.getBuilder().getConstInt(
503 loc, cmpInfo.getValueInfo(result)->getIntValue());
504
505 emitComparisonResult(e, loc, cmpInfo, resultValue);
506 }
507
508 void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
509 Visit(e->getSemanticForm());
510 }
511 void VisitObjCMessageExpr(ObjCMessageExpr *e) {
512 cgf.cgm.errorNYI(e->getSourceRange(),
513 "AggExprEmitter: VisitObjCMessageExpr");
514 }
515 void VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
516 cgf.cgm.errorNYI(e->getSourceRange(),
517 "AggExprEmitter: VisitObjCIVarRefExpr");
518 }
519
520 void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e) {
521 AggValueSlot dest = ensureSlot(cgf.getLoc(e->getExprLoc()), e->getType());
522 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
523 emitInitializationToLValue(e->getBase(), destLV);
524 VisitInitListExpr(e->getUpdater());
525 }
526 void VisitAbstractConditionalOperator(const AbstractConditionalOperator *e) {
527 mlir::Location loc = cgf.getLoc(e->getSourceRange());
528
529 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
530 CIRGenFunction::ConditionalEvaluation eval(cgf);
531
532 // Save whether the destination's lifetime is externally managed.
533 bool isExternallyDestructed = dest.isExternallyDestructed();
534 bool destructNonTrivialCStruct =
535 !isExternallyDestructed &&
537 isExternallyDestructed |= destructNonTrivialCStruct;
538
539 // emitIfOnBoolExpr terminates each region; an unconditional yield here
540 // would keep alive the dead block a noreturn arm leaves behind.
541 cgf.emitIfOnBoolExpr(
542 e->getCond(),
543 /*thenBuilder=*/
544 [&](mlir::OpBuilder &b, mlir::Location loc) {
545 eval.beginEvaluation();
546 {
547 CIRGenFunction::LexicalScope lexScope{cgf, loc,
548 b.getInsertionBlock()};
549 cgf.curLexScope->setAsTernary();
550 dest.setExternallyDestructed(isExternallyDestructed);
551 assert(!cir::MissingFeatures::incrementProfileCounter());
552 Visit(e->getTrueExpr());
553 }
554 eval.endEvaluation();
555 },
556 loc,
557 /*elseBuilder=*/
558 [&](mlir::OpBuilder &b, mlir::Location loc) {
559 eval.beginEvaluation();
560 {
561 CIRGenFunction::LexicalScope lexScope{cgf, loc,
562 b.getInsertionBlock()};
563 cgf.curLexScope->setAsTernary();
564
565 // If the result of an agg expression is unused, then the emission
566 // of the LHS might need to create a destination slot. That's fine
567 // with us, and we can safely emit the RHS into the same slot, but
568 // we shouldn't claim that it's already being destructed.
569 dest.setExternallyDestructed(isExternallyDestructed);
571 Visit(e->getFalseExpr());
572 }
573 eval.endEvaluation();
574 },
575 loc);
576
577 if (destructNonTrivialCStruct)
578 cgf.cgm.errorNYI(
579 e->getSourceRange(),
580 "Abstract conditional aggregate: destructNonTrivialCStruct");
581 }
582 void VisitChooseExpr(const ChooseExpr *e) { Visit(e->getChosenSubExpr()); }
583 void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) {
584 visitCXXParenListOrInitListExpr(e, e->getInitExprs(),
586 e->getArrayFiller());
587 }
588
589 void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *e) {
591 uint64_t numElements = e->getArraySize().getZExtValue();
592
593 if (!numElements)
594 return;
595
596 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
597
598 if (!e->getType()->isConstantArrayType())
599 cgf.cgm.errorNYI(e->getSourceRange(),
600 "VisitArrayInitLoopExpr: Non-constant array");
601
602 Address dest = ensureSlot(loc, e->getType()).getAddress();
603 cir::ArrayType arrayTy = cast<cir::ArrayType>(dest.getElementType());
604
605 emitArrayInit(dest, arrayTy, e->getType(),
606 const_cast<ArrayInitLoopExpr *>(e), {}, e->getSubExpr());
607 }
608
609 void VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
610 QualType ty = e->getType();
611 mlir::Location loc = cgf.getLoc(e->getSourceRange());
612 AggValueSlot slot = ensureSlot(loc, ty);
613 emitNullInitializationToLValue(loc,
614 cgf.makeAddrLValue(slot.getAddress(), ty));
615 }
616 void VisitNoInitExpr(NoInitExpr *e) {
617 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitNoInitExpr");
618 }
619 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
621 Visit(dae->getExpr());
622 }
623 void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *e) {
624 AggValueSlot slot =
625 ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
627 e->constructsVBase(), slot.getAddress(),
628 e->inheritedFromVBase(), e);
629 }
630
631 /// Emit the initializer for a std::initializer_list initialized with a
632 /// real initializer list.
633 void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *e) {
634 ASTContext &ctx = cgf.getContext();
635 CIRGenBuilderTy &builder = cgf.getBuilder();
636 mlir::Location loc = cgf.getLoc(e->getExprLoc());
637
638 LValue array = cgf.emitLValue(e->getSubExpr());
639 assert(array.isSimple() && "initializer_list array not a simple lvalue");
640 Address arrayPtr = array.getAddress();
641
644 assert(arrayType && "std::initializer_list constructed from non-array");
645
646 auto *record = e->getType()->castAsRecordDecl();
647 assert(record->getNumFields() == 2 &&
648 "Expected std::initializer_list to only have two fields");
649
650 RecordDecl::field_iterator field = record->field_begin();
651 assert(field != record->field_end() &&
652 ctx.hasSameType(field->getType()->getPointeeType(),
653 arrayType->getElementType()) &&
654 "Expected std::initializer_list first field to be const E *");
655
656 // Start pointer.
657 AggValueSlot dest = ensureSlot(loc, e->getType());
658 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
659 LValue start =
660 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
661
662 mlir::Value arrayStart = arrayPtr.emitRawPointer();
663 cgf.emitStoreThroughLValue(RValue::get(arrayStart), start);
664 ++field;
665 assert(field != record->field_end() &&
666 "Expected std::initializer_list to have two fields");
667
668 cir::ConstantOp size = builder.getConstInt(loc, arrayType->getSize());
669 LValue endOrLength =
670 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
671 if (ctx.hasSameType(field->getType(), ctx.getSizeType())) {
672 // Length.
673 cgf.emitStoreThroughLValue(RValue::get(size), endOrLength);
674 } else {
675 // End pointer.
676 assert(field->getType()->isPointerType() &&
677 ctx.hasSameType(field->getType()->getPointeeType(),
678 arrayType->getElementType()) &&
679 "Expected std::initializer_list second field to be const E *");
680 mlir::Value arrayEnd = builder.createPtrStride(loc, arrayStart, size);
681 cgf.emitStoreThroughLValue(RValue::get(arrayEnd), endOrLength);
682 }
683 }
684
685 void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
686 cgf.cgm.errorNYI(e->getSourceRange(),
687 "AggExprEmitter: VisitCXXScalarValueInitExpr");
688 }
689 void VisitCXXTypeidExpr(CXXTypeidExpr *e) { emitAggLoadOfLValue(e); }
690 void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {
691 Visit(e->getSubExpr());
692 }
693 void VisitOpaqueValueExpr(OpaqueValueExpr *e) {
694 cgf.cgm.errorNYI(e->getSourceRange(),
695 "AggExprEmitter: VisitOpaqueValueExpr");
696 }
697
698 void VisitPseudoObjectExpr(PseudoObjectExpr *e) {
699 cgf.cgm.errorNYI(e->getSourceRange(),
700 "AggExprEmitter: VisitPseudoObjectExpr");
701 }
702
703 void VisitVAArgExpr(VAArgExpr *e) {
704 // emitVAArg returns an aggregate value (not a pointer) at the CIR level.
705 // ABI-specific pointer handling will be done later in LoweringPrepare.
706 mlir::Value vaArgValue = cgf.emitVAArg(e);
707
708 // Create a temporary alloca to hold the aggregate value.
709 mlir::Location loc = cgf.getLoc(e->getSourceRange());
710 Address tmpAddr = cgf.createMemTemp(e->getType(), loc, "vaarg.tmp");
711
712 // Store the va_arg result into the temporary.
713 cgf.emitAggregateStore(vaArgValue, tmpAddr);
714
715 // Create an LValue from the temporary address.
716 LValue tmpLValue = cgf.makeAddrLValue(tmpAddr, e->getType());
717
718 // Copy the aggregate value from temporary to destination.
719 emitFinalDestCopy(e->getType(), tmpLValue);
720 }
721
722 void VisitCXXThrowExpr(const CXXThrowExpr *e) { cgf.emitCXXThrowExpr(e); }
723 void VisitAtomicExpr(AtomicExpr *e) {
724 RValue result = cgf.emitAtomicExpr(e);
725 emitFinalDestCopy(e->getType(), result);
726 }
727};
728
729} // namespace
730
731static bool isTrivialFiller(Expr *e) {
732 if (!e)
733 return true;
734
736 return true;
737
738 if (auto *ile = dyn_cast<InitListExpr>(e)) {
739 if (ile->getNumInits())
740 return false;
741 return isTrivialFiller(ile->getArrayFiller());
742 }
743
744 if (const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))
745 return cons->getConstructor()->isDefaultConstructor() &&
746 cons->getConstructor()->isTrivial();
747
748 return false;
749}
750
751/// Given an expression with aggregate type that represents a value lvalue, this
752/// method emits the address of the lvalue, then loads the result into DestPtr.
753void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
754 LValue lv = cgf.emitLValue(e);
755
756 // If the type of the l-value is atomic, then do an atomic load.
757 if (lv.getType()->isAtomicType() || cgf.isLValueSuitableForInlineAtomic(lv)) {
758 cgf.emitAtomicLoad(lv, e->getExprLoc(), dest);
759 return;
760 }
761
762 emitFinalDestCopy(e->getType(), lv);
763}
764
765void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
766 if (dest.isPotentiallyAliased() && e->getType().isPODType(cgf.getContext())) {
767 // For a POD type, just emit a load of the lvalue + a copy, because our
768 // compound literal might alias the destination.
769 emitAggLoadOfLValue(e);
770 return;
771 }
772
773 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
774
775 // Block-scope compound literals are destroyed at the end of the enclosing
776 // scope in C.
777 bool destruct =
778 !cgf.getLangOpts().CPlusPlus && !slot.isExternallyDestructed();
779 if (destruct)
781
782 cgf.emitAggExpr(e->getInitializer(), slot);
783
784 if (destruct)
785 if ([[maybe_unused]] QualType::DestructionKind dtorKind =
787 cgf.cgm.errorNYI(e->getSourceRange(), "compound literal with destructor");
788}
789
790void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
791 QualType arrayQTy, Expr *e,
792 ArrayRef<Expr *> args, Expr *arrayFiller) {
793 CIRGenBuilderTy &builder = cgf.getBuilder();
794 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
795
796 const uint64_t numInitElements = args.size();
797
798 bool setArrayInitLoopExprScope = isa<ArrayInitLoopExpr>(e);
799
800 const QualType elementType =
801 cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
802
803 const QualType elementPtrType = cgf.getContext().getPointerType(elementType);
804
805 const mlir::Type cirElementType = cgf.convertType(elementType);
806 const cir::PointerType cirElementPtrType =
807 builder.getPointerTo(cirElementType);
808
809 auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,
810 cir::CastKind::array_to_ptrdecay,
811 destPtr.getPointer());
812
813 const CharUnits elementSize =
814 cgf.getContext().getTypeSizeInChars(elementType);
815 const CharUnits elementAlign =
816 destPtr.getAlignment().alignmentOfArrayElement(elementSize);
817
818 // Exception safety requires us to destroy all the already-constructed
819 // members if an initializer throws. For that, we'll need an EH cleanup.
820 QualType::DestructionKind dtorKind = elementType.isDestructedType();
821 Address endOfInit = Address::invalid();
823
824 if (dtorKind && cgf.getLangOpts().Exceptions) {
825 endOfInit = cgf.createTempAlloca(cirElementPtrType, cgf.getPointerAlign(),
826 loc, "arrayinit.endOfInit");
827 builder.createStore(loc, begin, endOfInit);
828
829 cgf.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType,
830 elementAlign,
831 cgf.getDestroyer(dtorKind));
832 }
833
834 // The 'current element to initialize'. The invariants on this
835 // variable are complicated. Essentially, after each iteration of
836 // the loop, it points to the last initialized element, except
837 // that it points to the beginning of the array before any
838 // elements have been initialized.
839 mlir::Value element = begin;
840
841 // Don't build the 'one' before the cycle to avoid
842 // emmiting the redundant `cir.const 1` instrs.
843 mlir::Value one;
844
845 // Emit the explicit initializers.
846 for (uint64_t i = 0; i != numInitElements; ++i) {
847 // Advance to the next element.
848 if (i > 0) {
849 one = builder.getConstantInt(loc, cgf.ptrDiffTy, i);
850 element = builder.createPtrStride(loc, begin, one);
851
852 // Tell the cleanup that it needs to destroy up to this element.
853 if (endOfInit.isValid())
854 builder.createStore(loc, element, endOfInit);
855 }
856
857 const Address address = Address(element, cirElementType, elementAlign);
858 const LValue elementLV = cgf.makeAddrLValue(address, elementType);
859 emitInitializationToLValue(args[i], elementLV);
860 }
861
862 const uint64_t numArrayElements = arrayTy.getSize();
863
864 // Check whether there's a non-trivial array-fill expression.
865 const bool hasTrivialFiller = isTrivialFiller(arrayFiller);
866
867 // Any remaining elements need to be zero-initialized, possibly
868 // using the filler expression. We can skip this if the we're
869 // emitting to zeroed memory.
870 if (numInitElements != numArrayElements &&
871 !(dest.isZeroed() && hasTrivialFiller &&
872 cgf.getTypes().isZeroInitializable(elementType))) {
873 // Advance to the start of the rest of the array.
874 if (numInitElements) {
875 one = builder.getConstantInt(loc, cgf.ptrDiffTy, 1);
876 element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
877 element, one);
878
879 if (endOfInit.isValid())
880 builder.createStore(loc, element, endOfInit);
881 }
882
883 // Allocate the temporary variable
884 // to store the pointer to first unitialized element
885 const Address tmpAddr = cgf.createTempAlloca(
886 cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");
887 LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType);
888 cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
889
890 // Compute the end of array
891 cir::ConstantOp numArrayElementsConst = builder.getConstInt(
892 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), numArrayElements);
893 mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
894 begin, numArrayElementsConst);
895
896 builder.createDoWhile(
897 loc,
898 /*condBuilder=*/
899 [&](mlir::OpBuilder &b, mlir::Location loc) {
900 cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
901 cir::CmpOp cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
902 currentElement, end);
903 builder.createCondition(cmp);
904 },
905 /*bodyBuilder=*/
906 [&](mlir::OpBuilder &b, mlir::Location loc) {
907 cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
908
909 // Emit the actual filler expression.
910 LValue elementLV = cgf.makeAddrLValue(
911 Address(currentElement, cirElementType, elementAlign),
912 elementType);
913
914 mlir::Value idx;
915 if (setArrayInitLoopExprScope)
916 idx = cir::PtrDiffOp::create(b, loc, cgf.ptrDiffTy, currentElement,
917 begin);
918
919 CIRGenFunction::ArrayInitLoopExprScope loopExprScope(
920 cgf, setArrayInitLoopExprScope, idx);
921
922 if (arrayFiller)
923 emitInitializationToLValue(arrayFiller, elementLV);
924 else
925 emitNullInitializationToLValue(loc, elementLV);
926
927 // Advance pointer and store them to temporary variable
928 cir::ConstantOp one = builder.getConstInt(
929 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), 1);
930 auto nextElement = cir::PtrStrideOp::create(
931 builder, loc, cirElementPtrType, currentElement, one);
932
933 // Tell the EH cleanup that we finished with the last element.
934 if (endOfInit.isValid())
935 builder.createStore(loc, nextElement, endOfInit);
936
937 cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
938
939 builder.createYield(loc);
940 });
941 }
942}
943
944/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
945void AggExprEmitter::emitFinalDestCopy(QualType type, RValue src) {
946 assert(src.isAggregate() && "value must be aggregate value!");
947 LValue srcLV = cgf.makeAddrLValue(src.getAggregateAddress(), type);
948 emitFinalDestCopy(type, srcLV, CIRGenFunction::EVK_RValue);
949}
950
951/// Perform the final copy to destPtr, if desired.
952void AggExprEmitter::emitFinalDestCopy(
953 QualType type, const LValue &src,
954 CIRGenFunction::ExprValueKind srcValueKind) {
955 // If dest is ignored, then we're evaluating an aggregate expression
956 // in a context that doesn't care about the result. Note that loads
957 // from volatile l-values force the existence of a non-ignored
958 // destination.
959 if (dest.isIgnored())
960 return;
961
962 if (srcValueKind == CIRGenFunction::EVK_RValue) {
963 if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) {
964 cgf.cgm.errorNYI("emitFinalDestCopy: EVK_RValue & PCK_Struct");
965 }
966 } else {
967 if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
968 cgf.cgm.errorNYI("emitFinalDestCopy: !EVK_RValue & PCK_Struct");
969 }
970 }
971
975
976 AggValueSlot srcAgg = AggValueSlot::forLValue(src, AggValueSlot::IsDestructed,
979 emitCopy(type, dest, srcAgg);
980}
981
982/// Perform a copy from the source into the destination.
983///
984/// \param type - the type of the aggregate being copied; qualifiers are
985/// ignored
986void AggExprEmitter::emitCopy(QualType type, const AggValueSlot &dest,
987 const AggValueSlot &src) {
989
990 // If the result of the assignment is used, copy the LHS there also.
991 // It's volatile if either side is. Use the minimum alignment of
992 // the two sides.
993 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), type);
994 LValue srcLV = cgf.makeAddrLValue(src.getAddress(), type);
996 cgf.emitAggregateCopy(destLV, srcLV, type, dest.mayOverlap(),
997 dest.isVolatile() || src.isVolatile());
998}
999
1000void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
1001 const QualType type = lv.getType();
1002
1004 const mlir::Location loc = e->getSourceRange().isValid()
1005 ? cgf.getLoc(e->getSourceRange())
1006 : *cgf.currSrcLoc;
1007 return emitNullInitializationToLValue(loc, lv);
1008 }
1009
1010 if (isa<NoInitExpr>(e))
1011 return;
1012
1013 if (type->isReferenceType()) {
1014 RValue rv = cgf.emitReferenceBindingToExpr(e);
1015 return cgf.emitStoreThroughLValue(rv, lv);
1016 }
1017
1018 switch (cgf.getEvaluationKind(type)) {
1019 case cir::TEK_Complex:
1020 cgf.emitComplexExprIntoLValue(e, lv, /*isInit*/ true);
1021 break;
1022 case cir::TEK_Aggregate:
1026 dest.isZeroed()));
1027
1028 return;
1029 case cir::TEK_Scalar:
1030 if (lv.isSimple())
1031 cgf.emitScalarInit(e, cgf.getLoc(e->getSourceRange()), lv);
1032 else
1034 return;
1035 }
1036}
1037
1038void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *e) {
1039 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
1040 cgf.emitCXXConstructExpr(e, slot);
1041}
1042
1043void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
1044 LValue lv) {
1045 const QualType type = lv.getType();
1046
1047 // If the destination slot is already zeroed out before the aggregate is
1048 // copied into it, we don't have to emit any zeros here.
1049 if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
1050 return;
1051
1052 if (cgf.hasScalarEvaluationKind(type)) {
1053 // For non-aggregates, we can store the appropriate null constant.
1054 mlir::Value null = cgf.cgm.emitNullConstant(type, loc);
1055 if (lv.isSimple()) {
1056 cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
1057 return;
1058 }
1059
1061 return;
1062 }
1063
1064 // There's a potential optimization opportunity in combining
1065 // memsets; that would be easy for arrays, but relatively
1066 // difficult for structures with the current code.
1067 cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
1068}
1069
1070void AggExprEmitter::emitComparisonResult(const Expr *e, mlir::Location loc,
1071 const ComparisonCategoryInfo &cmpInfo,
1072 mlir::Value resultValue) {
1073 // Create the return value in the destination slot.
1074 ensureDest(loc, e->getType());
1075 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->getType());
1076
1077 // Emit the address of the first (and only) field in the comparison category
1078 // type, and initialize it from the constant integer value produced above.
1079 const FieldDecl *resultField = *cmpInfo.Record->field_begin();
1080 LValue fieldLVal = cgf.emitLValueForFieldInitialization(
1081 destLVal, resultField, resultField->getName());
1082 cgf.emitStoreThroughLValue(RValue::get(resultValue), fieldLVal);
1083}
1084
1085void AggExprEmitter::VisitLambdaExpr(LambdaExpr *e) {
1086 CIRGenFunction::SourceLocRAIIObject loc{cgf, cgf.getLoc(e->getSourceRange())};
1087 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
1088 LValue slotLV = cgf.makeAddrLValue(slot.getAddress(), e->getType());
1089
1090 // We'll need to enter cleanup scopes in case any of the element
1091 // initializers throws an exception or contains branch out of the expressions.
1092 CIRGenFunction::CleanupDeactivationScope deactivationScope(cgf);
1093
1094 for (auto [curField, capture, captureInit] : llvm::zip(
1095 e->getLambdaClass()->fields(), e->captures(), e->capture_inits())) {
1096 // Pick a name for the field.
1097 llvm::StringRef fieldName = curField->getName();
1098 if (capture.capturesVariable()) {
1099 assert(!curField->isBitField() && "lambdas don't have bitfield members!");
1100 ValueDecl *v = capture.getCapturedVar();
1101 fieldName = v->getName();
1102 cgf.cgm.lambdaFieldToName[curField] = fieldName;
1103 } else if (capture.capturesThis()) {
1104 cgf.cgm.lambdaFieldToName[curField] = "this";
1105 } else {
1106 cgf.cgm.errorNYI(e->getSourceRange(), "Unhandled capture kind");
1107 cgf.cgm.lambdaFieldToName[curField] = "unhandled-capture-kind";
1108 }
1109
1110 // Emit initialization
1111 LValue lv =
1112 cgf.emitLValueForFieldInitialization(slotLV, curField, fieldName);
1113 if (curField->hasCapturedVLAType())
1114 cgf.cgm.errorNYI(e->getSourceRange(), "lambda captured VLA type");
1115
1116 emitInitializationToLValue(captureInit, lv);
1117
1118 // Push a destructor if necessary.
1119 if (QualType::DestructionKind dtorKind =
1120 curField->getType().isDestructedType()) {
1121 assert(lv.isSimple());
1123 curField->getType(),
1124 cgf.getDestroyer(dtorKind), false);
1125 }
1126 }
1127}
1128
1129void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1130 CIRGenFunction::FullExprCleanupScope fullExprScope(cgf, e->getSubExpr());
1131 Visit(e->getSubExpr());
1132}
1133
1134void AggExprEmitter::VisitCallExpr(const CallExpr *e) {
1135 if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
1136 cgf.cgm.errorNYI(e->getSourceRange(), "reference return type");
1137 return;
1138 }
1139
1140 withReturnValueSlot(
1141 e, [&](ReturnValueSlot slot) { return cgf.emitCallExpr(e, slot); });
1142}
1143
1144void AggExprEmitter::withReturnValueSlot(
1145 const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
1146 QualType retTy = e->getType();
1147
1149 bool requiresDestruction =
1151 if (requiresDestruction)
1152 cgf.cgm.errorNYI(
1153 e->getSourceRange(),
1154 "withReturnValueSlot: return value requiring destruction is NYI");
1155
1156 // If it makes no observable difference, save a memcpy + temporary.
1157 //
1158 // We need to always provide our own temporary if destruction is required.
1159 // Otherwise, fn will emit its own, notice that it's "unused", and end its
1160 // lifetime before we have the chance to emit a proper destructor call.
1163
1164 Address retAddr = dest.getAddress();
1166
1169 fn(ReturnValueSlot(retAddr));
1170}
1171
1172void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
1173 if (e->hadArrayRangeDesignator())
1174 llvm_unreachable("GNU array range designator extension");
1175
1176 if (e->isTransparent())
1177 return Visit(e->getInit(0));
1178
1179 visitCXXParenListOrInitListExpr(
1180 e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());
1181}
1182
1183void AggExprEmitter::visitCXXParenListOrInitListExpr(
1184 Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
1185 Expr *arrayFiller) {
1186
1187 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
1188 const AggValueSlot dest = ensureSlot(loc, e->getType());
1189
1190 if (e->getType()->isConstantArrayType()) {
1191 cir::ArrayType arrayTy =
1193 emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,
1194 arrayFiller);
1195 return;
1196 } else if (e->getType()->isVariableArrayType()) {
1197 cgf.cgm.errorNYI(e->getSourceRange(),
1198 "visitCXXParenListOrInitListExpr variable array type");
1199 return;
1200 }
1201
1202 if (e->getType()->isArrayType()) {
1203 cgf.cgm.errorNYI(e->getSourceRange(),
1204 "visitCXXParenListOrInitListExpr array type");
1205 return;
1206 }
1207
1208 assert(e->getType()->isRecordType() && "Only support structs/unions here!");
1209
1210 // Do struct initialization; this code just sets each individual member
1211 // to the approprate value. This makes bitfield support automatic;
1212 // the disadvantage is that the generated code is more difficult for
1213 // the optimizer, especially with bitfields.
1214 unsigned numInitElements = args.size();
1215 auto *record = e->getType()->castAsRecordDecl();
1216
1217 // We'll need to enter cleanup scopes in case any of the element
1218 // initializers throws an exception.
1219 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
1220
1221 unsigned curInitIndex = 0;
1222
1223 // Emit initialization of base classes.
1224 if (auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) {
1225 assert(numInitElements >= cxxrd->getNumBases() &&
1226 "missing initializer for base class");
1227 for (auto &base : cxxrd->bases()) {
1228 assert(!base.isVirtual() && "should not see vbases here");
1229 CXXRecordDecl *baseRD = base.getType()->getAsCXXRecordDecl();
1231 loc, dest.getAddress(), cxxrd, baseRD,
1232 /*baseIsVirtual=*/false);
1234 AggValueSlot aggSlot = AggValueSlot::forAddr(
1235 address, Qualifiers(), AggValueSlot::IsDestructed,
1237 cgf.getOverlapForBaseInit(cxxrd, baseRD, false));
1238 cgf.emitAggExpr(args[curInitIndex++], aggSlot);
1239
1240 if (QualType::DestructionKind dtorKind =
1241 base.getType().isDestructedType())
1242 cgf.pushDestroyAndDeferDeactivation(dtorKind, address, base.getType());
1243 }
1244 }
1245
1246 // Prepare a 'this' for CXXDefaultInitExprs.
1247 CIRGenFunction::FieldConstructionScope fcScope(cgf, dest.getAddress());
1248
1249 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
1250
1251 if (record->isUnion()) {
1252 // Only initialize one field of a union. The field itself is
1253 // specified by the initializer list.
1254 if (!initializedFieldInUnion) {
1255 // Empty union; we have nothing to do.
1256
1257 // Make sure that it's really an empty and not a failure of
1258 // semantic analysis.
1259 assert(llvm::all_of(record->fields(),
1260 [](const FieldDecl *f) {
1261 return f->isUnnamedBitField() ||
1262 f->isAnonymousStructOrUnion();
1263 }) &&
1264 "Only unnamed bitfields or anonymous class allowed");
1265 return;
1266 }
1267
1268 // FIXME: volatility
1269 FieldDecl *initedField = initializedFieldInUnion;
1270
1271 LValue fieldLV = cgf.emitLValueForFieldInitialization(
1272 destLV, initedField, initedField->getName());
1273
1274 if (numInitElements) {
1275 // Store the initializer into the field
1276 emitInitializationToLValue(args[0], fieldLV);
1277 } else {
1278 // Default-initialize to null.
1279 emitNullInitializationToLValue(loc, fieldLV);
1280 }
1281 return;
1282 }
1283
1284 // Here we iterate over the fields; this makes it simpler to both
1285 // default-initialize fields and skip over unnamed fields.
1286 for (const FieldDecl *field : record->fields()) {
1287 // We're done once we hit the flexible array member.
1288 if (field->getType()->isIncompleteArrayType())
1289 break;
1290
1291 // Always skip anonymous bitfields.
1292 if (field->isUnnamedBitField())
1293 continue;
1294
1295 // We're done if we reach the end of the explicit initializers, we
1296 // have a zeroed object, and the rest of the fields are
1297 // zero-initializable.
1298 if (curInitIndex == numInitElements && dest.isZeroed() &&
1300 break;
1301 LValue lv =
1302 cgf.emitLValueForFieldInitialization(destLV, field, field->getName());
1303 // We never generate write-barriers for initialized fields.
1305
1306 if (curInitIndex < numInitElements) {
1307 // Store the initializer into the field.
1308 CIRGenFunction::SourceLocRAIIObject loc{
1309 cgf, cgf.getLoc(record->getSourceRange())};
1310 emitInitializationToLValue(args[curInitIndex++], lv);
1311 } else {
1312 // We're out of initializers; default-initialize to null
1313 emitNullInitializationToLValue(cgf.getLoc(e->getSourceRange()), lv);
1314 }
1315
1316 // Push a destructor if necessary.
1317 // FIXME: if we have an array of structures, all explicitly
1318 // initialized, we can end up pushing a linear number of cleanups.
1319 if (QualType::DestructionKind dtorKind =
1320 field->getType().isDestructedType()) {
1321 assert(lv.isSimple());
1323 field->getType(),
1324 cgf.getDestroyer(dtorKind), false);
1325 }
1326
1327 // From classic codegen, maybe not useful for CIR:
1328 // If the GEP didn't get used because of a dead zero init or something
1329 // else, clean it up for -O0 builds and general tidiness.
1330 }
1331}
1332
1333// TODO(cir): This could be shared with classic codegen.
1335 const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual) {
1336 // If the most-derived object is a field declared with [[no_unique_address]],
1337 // the tail padding of any virtual base could be reused for other subobjects
1338 // of that field's class.
1339 if (isVirtual)
1341
1342 // If the base class is laid out entirely within the nvsize of the derived
1343 // class, its tail padding cannot yet be initialized, so we can issue
1344 // stores at the full width of the base class.
1345 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1346 if (layout.getBaseClassOffset(baseRD) +
1347 getContext().getASTRecordLayout(baseRD).getSize() <=
1348 layout.getNonVirtualSize())
1350
1351 // The tail padding may contain values we need to preserve.
1353}
1354
1356 AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
1357}
1358
1360 AggValueSlot::Overlap_t mayOverlap,
1361 bool isVolatile) {
1362 // TODO(cir): this function needs improvements, commented code for now since
1363 // this will be touched again soon.
1364 assert(!ty->isAnyComplexType() && "Unexpected copy of complex");
1365
1366 Address destPtr = dest.getAddress();
1367 Address srcPtr = src.getAddress();
1368
1369 if (getLangOpts().CPlusPlus) {
1370 if (auto *record = ty->getAsCXXRecordDecl()) {
1371 assert((record->hasTrivialCopyConstructor() ||
1372 record->hasTrivialCopyAssignment() ||
1373 record->hasTrivialMoveConstructor() ||
1374 record->hasTrivialMoveAssignment() ||
1375 record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&
1376 "Trying to aggregate-copy a type without a trivial copy/move "
1377 "constructor or assignment operator");
1378 // Ignore empty classes in C++.
1379 if (record->isEmpty())
1380 return;
1381 }
1382 }
1383
1385
1386 // Aggregate assignment turns into llvm.memcpy. This is almost valid per
1387 // C99 6.5.16.1p3, which states "If the value being stored in an object is
1388 // read from another object that overlaps in anyway the storage of the first
1389 // object, then the overlap shall be exact and the two objects shall have
1390 // qualified or unqualified versions of a compatible type."
1391 //
1392 // memcpy is not defined if the source and destination pointers are exactly
1393 // equal, but other compilers do this optimization, and almost every memcpy
1394 // implementation handles this case safely. If there is a libc that does not
1395 // safely handle this, we can add a target hook.
1396
1397 // Get data size info for this aggregate. Don't copy the tail padding if this
1398 // might be a potentially-overlapping subobject, since the tail padding might
1399 // be occupied by a different object. Otherwise, copying it is fine.
1400 TypeInfoChars typeInfo;
1401 if (mayOverlap)
1402 typeInfo = getContext().getTypeInfoDataSizeInChars(ty);
1403 else
1404 typeInfo = getContext().getTypeInfoInChars(ty);
1405
1407
1408 // Don't do any of the memmove_collectable tests if GC isn't set.
1409 if (cgm.getLangOpts().getGC() != LangOptions::NonGC)
1410 cgm.errorNYI("emitAggregateCopy: GC");
1411
1412 // If the data size (excluding tail padding) differs from the full type size,
1413 // use skip_tail_padding to avoid clobbering tail padding that may be occupied
1414 // by other objects (e.g. fields marked with [[no_unique_address]]).
1415 CharUnits dataSize = typeInfo.Width;
1416 bool skipTailPadding =
1417 mayOverlap && dataSize != getContext().getTypeSizeInChars(ty);
1418 // NOTE(cir): original codegen would normally convert destPtr and srcPtr to
1419 // i8* since memcpy operates on bytes. We don't need that in CIR because
1420 // cir.copy will operate on any CIR pointer that points to a sized type.
1421 builder.createCopy(destPtr, srcPtr, isVolatile, skipTailPadding);
1422
1424}
1425
1426// TODO(cir): This could be shared with classic codegen.
1429 if (!fd->hasAttr<NoUniqueAddressAttr>() || !fd->getType()->isRecordType())
1431
1432 // If the field lies entirely within the enclosing class's nvsize, its tail
1433 // padding cannot overlap any already-initialized object. (The only subobjects
1434 // with greater addresses that might already be initialized are vbases.)
1435 const RecordDecl *classRD = fd->getParent();
1436 const ASTRecordLayout &layout = getContext().getASTRecordLayout(classRD);
1437 if (layout.getFieldOffset(fd->getFieldIndex()) +
1438 getContext().getTypeSize(fd->getType()) <=
1439 (uint64_t)getContext().toBits(layout.getNonVirtualSize()))
1441
1442 // The tail padding may contain values we need to preserve.
1444}
1445
static Expr * findPeephole(Expr *op, CastKind kind, const ASTContext &ctx)
Attempt to look through various unimportant expressions to find a cast of the given kind.
static bool isBlockVarRef(const Expr *E)
Is the value of the given expression possibly a reference to or into a __block variable?
static bool isTrivialFiller(Expr *e)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::ConditionOp createCondition(mlir::Value condition)
Create a loop condition.
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
cir::PointerType getPointerTo(mlir::Type ty)
cir::DoWhileOp createDoWhile(mlir::Location loc, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> condBuilder, llvm::function_ref< void(mlir::OpBuilder &, mlir::Location)> bodyBuilder)
Create a do-while operation.
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
APSInt & getInt()
Definition APValue.h:511
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
const ConstantArrayType * getAsConstantArrayType(QualType T) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition Expr.h:4397
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h:4575
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4587
Represents a loop initializing the elements of an array.
Definition Expr.h:6018
llvm::APInt getArraySize() const
Definition Expr.h:6040
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition Expr.h:6033
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition Expr.h:6038
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2765
QualType getElementType() const
Definition TypeBase.h:3848
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition Expr.h:6978
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4082
Expr * getLHS() const
Definition Expr.h:4132
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4137
SourceLocation getExprLoc() const
Definition Expr.h:4123
Expr * getRHS() const
Definition Expr.h:4134
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
static Address invalid()
Definition Address.h:76
clang::CharUnits getAlignment() const
Definition Address.h:138
bool isValid() const
Definition Address.h:77
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:112
An aggregate value slot.
IsZeroed_t isZeroed() const
Overlap_t mayOverlap() const
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
IsDestructed_t isExternallyDestructed() const
static AggValueSlot forLValue(const LValue &LV, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
void setExternallyDestructed(bool destructed=true)
static AggValueSlot ignored()
Returns an aggregate value slot indicating that the aggregate value is being ignored.
IsAliased_t isPotentiallyAliased() const
clang::Qualifiers getQualifiers() const
void setVolatile(bool flag)
cir::CmpThreeWayOp createThreeWayCmpTotalOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt &ltRes, const llvm::APSInt &eqRes, const llvm::APSInt &gtRes, cir::CmpOrdering ordering)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::CmpThreeWayOp createThreeWayCmpPartialOrdering(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, const llvm::APSInt &ltRes, const llvm::APSInt &eqRes, const llvm::APSInt &gtRes, const llvm::APSInt &unorderedRes)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
CIRGenTypes & getTypes() const
const clang::LangOptions & getLangOpts() const
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
void pushIrregularPartialArrayCleanup(mlir::Value arrayBegin, Address arrayEndPointer, QualType elementType, CharUnits elementAlign, Destroyer *destroyer)
Push an EH cleanup to destroy already-constructed elements of the given array.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitAggregateStore(mlir::Value value, Address dest)
RValue emitAtomicExpr(AtomicExpr *e)
void emitNullInitialization(mlir::Location loc, Address destPtr, QualType ty)
RValue emitReferenceBindingToExpr(const Expr *e)
Emits a reference binding to the passed in expression.
void pushDestroyAndDeferDeactivation(QualType::DestructionKind dtorKind, Address addr, QualType type)
AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *fd)
RValue emitAtomicLoad(LValue lvalue, SourceLocation loc, AggValueSlot slot=AggValueSlot::ignored())
void emitCXXConstructExpr(const clang::CXXConstructExpr *e, AggValueSlot dest)
LValue emitAggExprToLValue(const Expr *e)
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
static bool hasAggregateEvaluationKind(clang::QualType type)
void emitScalarInit(const clang::Expr *init, mlir::Location loc, LValue lvalue, bool capturedByInit=false)
LValue emitLValueForFieldInitialization(LValue base, const clang::FieldDecl *field, llvm::StringRef fieldName)
Like emitLValueForField, excpet that if the Field is a reference, this will return the address of the...
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
Address getAddressOfDirectBaseInCompleteClass(mlir::Location loc, Address value, const CXXRecordDecl *derived, const CXXRecordDecl *base, bool baseIsVirtual)
Convert the given pointer to a complete class to the given direct base.
CIRGenBuilderTy & getBuilder()
AggValueSlot::Overlap_t getOverlapForBaseInit(const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual)
Determine whether a base class initialization may overlap some other object.
Destroyer * getDestroyer(clang::QualType::DestructionKind kind)
void emitComplexExprIntoLValue(const Expr *e, LValue dest, bool isInit)
void emitCXXThrowExpr(const CXXThrowExpr *e)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
clang::ASTContext & getContext() const
void emitInheritedCXXConstructorCall(const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr, bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e)
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
bool isLValueSuitableForInlineAtomic(LValue lv)
An LValue is a candidate for having its loads and stores be made atomic if we are operating under /vo...
Address createMemTemp(QualType t, mlir::Location loc, const Twine &name="tmp", Address *alloca=nullptr, mlir::OpBuilder::InsertPoint ip={})
Create a temporary memory object of the given type, with appropriate alignmen and cast it to the defa...
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
llvm::DenseMap< const clang::FieldDecl *, llvm::StringRef > lambdaFieldToName
Keep a map between lambda fields and names, this needs to be per module since lambdas might get gener...
bool isZeroInitializable(clang::QualType ty)
Return whether a type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
Address getAddress() const
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
Address getAggregateAddress() const
Return the value of the address of the aggregate.
Definition CIRGenValue.h:69
bool isAggregate() const
Definition CIRGenValue.h:51
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
static RValue getAggregate(Address addr, bool isVolatile=false)
Convert an Address to an RValue.
CXXTemporary * getTemporary()
Definition ExprCXX.h:1515
const Expr * getSubExpr() const
Definition ExprCXX.h:1519
A default argument (C++ [dcl.fct.default]).
Definition ExprCXX.h:1274
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1138
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1755
bool constructsVBase() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
Definition ExprCXX.h:1796
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will call.
Definition ExprCXX.h:1792
bool inheritedFromVBase() const
Determine whether the inherited constructor is inherited from a virtual base of the object we constru...
Definition ExprCXX.h:1806
Represents a list-initialization with parenthesis.
Definition ExprCXX.h:5194
MutableArrayRef< Expr * > getInitExprs()
Definition ExprCXX.h:5234
FieldDecl * getInitializedFieldInUnion()
Definition ExprCXX.h:5272
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isTriviallyCopyable() const
Determine whether this class is considered trivially copyable per (C++11 [class]p6).
Definition DeclCXX.cpp:613
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:308
An expression "T()" which creates an rvalue of a non-class type T.
Definition ExprCXX.h:2200
Implicit construction of a std::initializer_list<T> object from an array temporary within list-initia...
Definition ExprCXX.h:804
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1212
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
Definition ExprCXX.h:852
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1631
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3720
CastKind getCastKind() const
Definition Expr.h:3764
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1981
Expr * getSubExpr()
Definition Expr.h:3770
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition CharUnits.h:214
ChooseExpr - GNU builtin-in function __builtin_choose_expr.
Definition Expr.h:4892
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4928
bool isPartial() const
True iff the comparison is not totally ordered.
const ValueInfo * getLess() const
const ValueInfo * getUnordered() const
const CXXRecordDecl * Record
The declaration for the comparison category type from the standard library.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
bool isStrong() const
True iff the comparison is "strong".
const ValueInfo * getGreater() const
const ValueInfo * getEqualOrEquiv() const
const Expr * getInitializer() const
Definition Expr.h:3677
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3874
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1290
bool hasAttr() const
Definition DeclBase.h:585
InitListExpr * getUpdater() const
Definition Expr.h:5986
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
Definition Expr.cpp:3150
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3119
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3722
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3295
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3380
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3531
const Expr * getSubExpr() const
Definition Expr.h:1082
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6518
Represents an implicitly-generated value initialization of an object of a given type.
Definition Expr.h:6107
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
Definition Expr.cpp:2495
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
Definition Expr.h:5479
bool hadArrayRangeDesignator() const
Definition Expr.h:5533
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
Definition Expr.h:5455
const Expr * getInit(unsigned Init) const
Definition Expr.h:5407
ArrayRef< Expr * > inits() const
Definition Expr.h:5405
llvm::iterator_range< capture_init_iterator > capture_inits()
Retrieve the initialization expressions for this lambda's captures.
Definition ExprCXX.h:2087
capture_range captures() const
Retrieve this lambda's captures.
Definition ExprCXX.cpp:1404
CXXRecordDecl * getLambdaClass() const
Retrieve the class that corresponds to the lambda.
Definition ExprCXX.cpp:1433
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4973
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4990
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3408
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
Represents a place-holder for an object not to be initialized by anything.
Definition Expr.h:5927
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1198
const Expr * getSubExpr() const
Definition Expr.h:2243
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition Expr.h:6854
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8585
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Definition TypeBase.h:1561
bool isPODType(const ASTContext &Context) const
Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
Definition Type.cpp:2820
@ PCK_Struct
The type is a struct containing a field whose type is neither PCK_Trivial nor PCK_VolatileTrivial.
Definition TypeBase.h:1533
Represents a struct/union/class.
Definition Decl.h:4460
field_range fields() const
Definition Decl.h:4663
specific_decl_iterator< FieldDecl > field_iterator
Definition Decl.h:4660
field_iterator field_begin() const
Definition Decl.cpp:5339
CompoundStmt * getSubStmt()
Definition Expr.h:4656
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
const char * getStmtClassName() const
Definition Stmt.cpp:86
bool isStoredAsComparisonResult() const
Definition ExprCXX.h:2957
const APValue & getAPValue() const
Definition ExprCXX.h:2966
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantArrayType() const
Definition TypeBase.h:8841
bool isArrayType() const
Definition TypeBase.h:8837
bool isPointerType() const
Definition TypeBase.h:8738
bool isReferenceType() const
Definition TypeBase.h:8762
bool isVariableArrayType() const
Definition TypeBase.h:8849
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9232
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2535
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8873
bool isMemberPointerType() const
Definition TypeBase.h:8819
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2437
bool isNullPtrType() const
Definition TypeBase.h:9147
bool isRecordType() const
Definition TypeBase.h:8865
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2288
Expr * getSubExpr() const
Definition Expr.h:2329
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:5001
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const AstTypeMatcher< AtomicType > atomicType
constexpr Variable var(Literal L)
Returns the variable of L.
Definition CNFFormula.h:64
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
CastKind
CastKind - The kind of operation required for a conversion.
U cast(CodeGen::Address addr)
Definition Address.h:327
unsigned long uint64_t
static bool emitLifetimeMarkers()
static bool aggValueSlotDestructedFlag()
static bool aggValueSlotGC()
static bool aggValueSlotAlias()
static bool aggEmitFinalDestCopyRValue()
static bool cleanupDeactivationScope()
static bool aggValueSlotVolatile()
static bool cudaSupport()
static bool incrementProfileCounter()
clang::CharUnits getPointerAlign() const
llvm::APSInt getIntValue() const
Get the constant integer value used by this variable to represent the comparison category result type...