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"
21#include "clang/AST/ExprCXX.h"
25#include "llvm/IR/Value.h"
26#include <cstdint>
27
28using namespace clang;
29using namespace clang::CIRGen;
30
31namespace {
32class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
33
34 CIRGenFunction &cgf;
35 AggValueSlot dest;
36
37 // Calls `fn` with a valid return value slot, potentially creating a temporary
38 // to do so. If a temporary is created, an appropriate copy into `Dest` will
39 // be emitted, as will lifetime markers.
40 //
41 // The given function should take a ReturnValueSlot, and return an RValue that
42 // points to said slot.
43 void withReturnValueSlot(const Expr *e,
44 llvm::function_ref<RValue(ReturnValueSlot)> fn);
45
46 AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
47 if (!dest.isIgnored())
48 return dest;
49 return cgf.createAggTemp(t, loc, "agg.tmp.ensured");
50 }
51
52 void ensureDest(mlir::Location loc, QualType ty) {
53 if (!dest.isIgnored())
54 return;
55 dest = cgf.createAggTemp(ty, loc, "agg.tmp.ensured");
56 }
57
58public:
59 AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
60 : cgf(cgf), dest(dest) {}
61
62 /// Given an expression with aggregate type that represents a value lvalue,
63 /// this method emits the address of the lvalue, then loads the result into
64 /// DestPtr.
65 void emitAggLoadOfLValue(const Expr *e);
66
67 void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
68 Expr *exprToVisit, ArrayRef<Expr *> args,
69 Expr *arrayFiller);
70
71 void emitFinalDestCopy(QualType type, RValue src);
72
73 /// Perform the final copy to DestPtr, if desired.
74 void emitFinalDestCopy(QualType type, const LValue &src,
77
78 void emitCopy(QualType type, const AggValueSlot &dest,
79 const AggValueSlot &src);
80
81 void emitInitializationToLValue(Expr *e, LValue lv);
82
83 void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
84
85 void emitComparisonResult(const Expr *e, mlir::Location loc,
86 const ComparisonCategoryInfo &cmpInfo,
87 mlir::Value resultValue);
88
89 void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
90
91 void VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
92 emitAggLoadOfLValue(e);
93 }
94
95 void VisitCallExpr(const CallExpr *e);
96 void VisitStmtExpr(const StmtExpr *e) {
97 CIRGenFunction::StmtExprEvaluation eval(cgf);
98 Address retAlloca =
99 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
100 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca, dest);
101 }
102
103 void VisitBinAssign(const BinaryOperator *e) {
104 // For an assignment to work, the value on the right has
105 // to be compatible with the value on the left.
106 assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
107 e->getRHS()->getType()) &&
108 "Invalid assignment");
109
111 e->getRHS()->HasSideEffects(cgf.getContext())) {
112 cgf.cgm.errorNYI(e->getSourceRange(),
113 "block var reference with side effects");
114 return;
115 }
116
117 LValue lhs = cgf.emitLValue(e->getLHS());
118
119 // If we have an atomic type, evaluate into the destination and then
120 // do an atomic copy.
121 if (lhs.getType()->isAtomicType() ||
122 cgf.isLValueSuitableForInlineAtomic(lhs)) {
123 ensureDest(cgf.getLoc(e->getExprLoc()), e->getRHS()->getType());
124 Visit(e->getRHS());
125 cgf.emitAtomicStore(dest.asRValue(), lhs, /*isInit=*/false);
126 return;
127 }
128
129 // Codegen the RHS so that it stores directly into the LHS.
131 AggValueSlot lhsSlot = AggValueSlot::forLValue(
134
135 // A non-volatile aggregate destination might have volatile member.
136 if (!lhsSlot.isVolatile() && cgf.hasVolatileMember(e->getLHS()->getType()))
137 lhsSlot.setVolatile(true);
138
139 cgf.emitAggExpr(e->getRHS(), lhsSlot);
140
141 // Copy into the destination if the assignment isn't ignored.
142 emitFinalDestCopy(e->getType(), lhs);
143
144 if (!dest.isIgnored() && !dest.isExternallyDestructed() &&
146 cgf.pushDestroy(QualType::DK_nontrivial_c_struct, dest.getAddress(),
147 e->getType());
148 }
149
150 void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
151
152 void VisitInitListExpr(InitListExpr *e);
153 void VisitCXXConstructExpr(const CXXConstructExpr *e);
154
155 void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
156 FieldDecl *initializedFieldInUnion,
157 Expr *arrayFiller);
158 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
159 CIRGenFunction::CXXDefaultInitExprScope Scope(cgf, die);
160 Visit(die->getExpr());
161 }
162 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *e) {
163 // Ensure that we have a slot, but if we already do, remember
164 // whether it was externally destructed.
165 bool wasExternallyDestructed = dest.isExternallyDestructed();
166 ensureDest(cgf.getLoc(e->getSourceRange()), e->getType());
167
168 // We're going to push a destructor if there isn't already one.
169 dest.setExternallyDestructed();
170
171 Visit(e->getSubExpr());
172
173 // Push that destructor we promised.
174 if (!wasExternallyDestructed)
175 cgf.emitCXXTemporary(e->getTemporary(), e->getType(), dest.getAddress());
176 }
177 void VisitLambdaExpr(LambdaExpr *e);
178 void VisitExprWithCleanups(ExprWithCleanups *e);
179
180 /// Attempt to look through various unimportant expressions to find a
181 /// cast of the given kind.
182 static Expr *findPeephole(Expr *op, CastKind kind, const ASTContext &ctx) {
183 op = op->IgnoreParenNoopCasts(ctx);
184 if (auto *castE = dyn_cast<CastExpr>(op)) {
185 if (castE->getCastKind() == kind)
186 return castE->getSubExpr();
187 }
188 return nullptr;
189 }
190
191 // Stubs -- These should be moved up when they are implemented.
192 void VisitCastExpr(CastExpr *e) {
193 switch (e->getCastKind()) {
194 case CK_LValueToRValueBitCast: {
195 if (dest.isIgnored()) {
196 cgf.emitAnyExpr(e->getSubExpr(), AggValueSlot::ignored(),
197 /*ignoreResult=*/true);
198 break;
199 }
200
201 LValue sourceLV = cgf.emitLValue(e->getSubExpr());
202 Address sourceAddress =
203 sourceLV.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
204 Address destAddress =
205 dest.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
206
207 mlir::Location loc = cgf.getLoc(e->getExprLoc());
208
209 mlir::Value sizeVal = cgf.getBuilder().getConstInt(
210 loc, cgf.sizeTy,
211 cgf.getContext().getTypeSizeInChars(e->getType()).getQuantity());
212 cgf.getBuilder().createMemCpy(loc, destAddress, sourceAddress, sizeVal);
213
214 break;
215 }
216
217 case CK_NonAtomicToAtomic:
218 case CK_AtomicToNonAtomic: {
219 bool isToAtomic = (e->getCastKind() == CK_NonAtomicToAtomic);
220
221 // Determine the atomic and value types.
222 QualType atomicType = e->getSubExpr()->getType();
223 QualType valueType = e->getType();
224 if (isToAtomic)
225 std::swap(atomicType, valueType);
226
227 assert(atomicType->isAtomicType());
228 assert(cgf.getContext().hasSameUnqualifiedType(
229 valueType, atomicType->castAs<AtomicType>()->getValueType()));
230
231 // Just recurse normally if we're ignoring the result or the
232 // atomic type doesn't change representation.
233 if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(atomicType))
234 return Visit(e->getSubExpr());
235
236 // These two cases are reverses of each other; try to peephole them.
237 CastKind peepholeTarget =
238 (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
239
240 // These two cases are reverses of each other; try to peephole them.
241 if (Expr *op =
242 findPeephole(e->getSubExpr(), peepholeTarget, cgf.getContext())) {
243 assert(cgf.getContext().hasSameUnqualifiedType(op->getType(),
244 e->getType()) &&
245 "peephole significantly changed types?");
246 return Visit(op);
247 }
248
249 // If we're converting an r-value of non-atomic type to an r-value
250 // of atomic type, just emit directly into the relevant sub-object.
251 if (isToAtomic) {
252 AggValueSlot valueDest = dest;
253 if (!valueDest.isIgnored() && cgf.cgm.isPaddedAtomicType(atomicType)) {
254 // Zero-initialize. (Strictly speaking, we only need to initialize
255 // the padding at the end, but this is simpler.)
256 mlir::Location loc = cgf.getLoc(e->getExprLoc());
257 if (!dest.isZeroed())
258 cgf.emitNullInitialization(loc, dest.getAddress(), atomicType);
259
260 Address valueAddr = cgf.getBuilder().createGetMember(
261 loc, valueDest.getAddress(), "value_addr", 0,
262 cgf.cgm.getDataLayout());
263
265 valueDest = AggValueSlot::forAddr(
266 valueAddr, valueDest.getQualifiers(),
267 valueDest.isExternallyDestructed(),
270 }
271
272 cgf.emitAggExpr(e->getSubExpr(), valueDest);
273 return;
274 }
275
276 mlir::Location loc = cgf.getLoc(e->getExprLoc());
277 AggValueSlot atomicSlot = cgf.createAggTemp(atomicType, loc);
278 cgf.emitAggExpr(e->getSubExpr(), atomicSlot);
279
280 Address valueAddr = cgf.getBuilder().createGetMember(
281 loc, atomicSlot.getAddress(), "value_addr", 0,
282 cgf.cgm.getDataLayout());
283 RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile());
284 return emitFinalDestCopy(valueType, rvalue);
285 }
286 case CK_LValueToRValue:
287 // If we're loading from a volatile type, force the destination
288 // into existence.
290 cgf.cgm.errorNYI(e->getSourceRange(),
291 "AggExprEmitter: volatile lvalue-to-rvalue cast");
292 [[fallthrough]];
293 case CK_NoOp:
294 case CK_UserDefinedConversion:
295 case CK_ConstructorConversion:
296 assert(cgf.getContext().hasSameUnqualifiedType(e->getSubExpr()->getType(),
297 e->getType()) &&
298 "Implicit cast types must be compatible");
299 Visit(e->getSubExpr());
300 break;
301 case CK_ToUnion: {
302 if (dest.isIgnored()) {
303 cgf.emitAnyExpr(e->getSubExpr(), AggValueSlot::ignored(),
304 /*ignoreResult=*/true);
305 break;
306 }
307 QualType ty = e->getSubExpr()->getType();
308 Address castPtr = dest.getAddress().withElementType(cgf.getBuilder(),
309 cgf.convertType(ty));
310 emitInitializationToLValue(e->getSubExpr(),
311 cgf.makeAddrLValue(castPtr, ty));
312 break;
313 }
314 default:
315 cgf.cgm.errorNYI(e->getSourceRange(),
316 std::string("AggExprEmitter: VisitCastExpr: ") +
317 e->getCastKindName());
318 break;
319 }
320 }
321 void VisitStmt(Stmt *s) {
322 cgf.cgm.errorNYI(s->getSourceRange(),
323 std::string("AggExprEmitter::VisitStmt: ") +
324 s->getStmtClassName());
325 }
326 void VisitParenExpr(ParenExpr *pe) { Visit(pe->getSubExpr()); }
327 void VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
328 Visit(ge->getResultExpr());
329 }
330 void VisitCoawaitExpr(CoawaitExpr *e) {
331 cgf.emitCoawaitExpr(*e, dest, dest.isIgnored());
332 }
333 void VisitCoyieldExpr(CoyieldExpr *e) {
334 cgf.emitCoyieldExpr(*e, dest, dest.isIgnored());
335 }
336 void VisitUnaryCoawait(UnaryOperator *e) { Visit(e->getSubExpr()); }
337 void VisitUnaryExtension(UnaryOperator *e) { Visit(e->getSubExpr()); }
338 void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
339 Visit(e->getReplacement());
340 }
341 void VisitPackIndexingExpr(PackIndexingExpr *e) {
342 Visit(e->getSelectedExpr());
343 }
344 void VisitConstantExpr(ConstantExpr *e) {
345 mlir::Location loc = cgf.getLoc(e->getSourceRange());
346 ensureDest(loc, e->getType());
347
348 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
349 QualType ty = e->getType();
350
351 // If the destination's tail padding may overlap another object's
352 // storage (e.g. a [[no_unique_address]] member or base), only store
353 // the type's data size rather than its full size, so we don't
354 // clobber bytes that belong to that other object. In particular, a
355 // genuinely empty class has a data size of zero, so nothing should
356 // be stored at all.
357 if (dest.mayOverlap()) {
358 CharUnits dataSize =
359 cgf.getContext().getTypeInfoDataSizeInChars(ty).Width;
360 if (dataSize.isZero())
361 return;
362
363 if (dataSize != cgf.getContext().getTypeSizeInChars(ty)) {
364 Address temp = cgf.createMemTemp(ty, loc);
365 mlir::Value resultVal = cgf.getBuilder().getConstant(
366 loc, mlir::cast<mlir::TypedAttr>(result));
367 cgf.getBuilder().createStore(loc, resultVal, temp);
368 cgf.getBuilder().createCopy(dest.getAddress(), temp,
369 /*isVolatile=*/false,
370 /*skipTailPadding=*/true);
371 return;
372 }
373 }
374
375 mlir::Value resultVal = cgf.getBuilder().getConstant(
376 loc, mlir::cast<mlir::TypedAttr>(result));
377 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), ty);
378 cgf.emitStoreThroughLValue(RValue::get(resultVal), destLVal);
379 return;
380 }
381
382 // It isn't clear that it is possible to get to here, but this branch is
383 // present in classic codegen, so we leave it here too.
384 return Visit(e->getSubExpr());
385 }
386 void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
387 void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
388 void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
389 void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
390
391 void VisitPredefinedExpr(const PredefinedExpr *e) { emitAggLoadOfLValue(e); }
392 void VisitBinaryOperator(const BinaryOperator *e) {
393 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI)
394 VisitPointerToDataMemberBinaryOperator(e);
395 else
396 cgf.cgm.errorUnsupported(e, "aggregate binary expression");
397 }
398 void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *e) {
399 LValue lv = cgf.emitPointerToDataMemberBinaryExpr(e);
400 emitFinalDestCopy(e->getType(), lv);
401 }
402 void VisitBinComma(const BinaryOperator *e) {
403 cgf.emitIgnoredExpr(e->getLHS());
404 Visit(e->getRHS());
405 }
406 void VisitBinCmp(const BinaryOperator *e) {
407 assert(cgf.getContext().hasSameType(e->getLHS()->getType(),
408 e->getRHS()->getType()));
409 const ComparisonCategoryInfo &cmpInfo =
410 cgf.getContext().CompCategories.getInfoForType(e->getType());
411 assert(cmpInfo.Record->isTriviallyCopyable() &&
412 "cannot copy non-trivially copyable aggregate");
413
414 QualType argTy = e->getLHS()->getType();
415
416 if (!argTy->isIntegralOrEnumerationType() && !argTy->isRealFloatingType() &&
417 !argTy->isNullPtrType() && !argTy->isPointerType() &&
418 !argTy->isMemberPointerType() && !argTy->isAnyComplexType())
419 cgf.cgm.errorNYI(e->getBeginLoc(), "aggregate three-way comparison");
420
421 mlir::Location loc = cgf.getLoc(e->getSourceRange());
422 CIRGenBuilderTy &builder = cgf.getBuilder();
423
424 if (e->getType()->isAnyComplexType())
425 cgf.cgm.errorNYI(e->getBeginLoc(), "VisitBinCmp: complex type");
426
427 if (e->getType()->isAggregateType())
428 cgf.cgm.errorNYI(e->getBeginLoc(), "VisitBinCmp: aggregate type");
429
430 mlir::Value lhs = cgf.emitAnyExpr(e->getLHS()).getValue();
431 mlir::Value rhs = cgf.emitAnyExpr(e->getRHS()).getValue();
432
433 mlir::Value resultScalar;
434 if (argTy->isNullPtrType()) {
435 resultScalar =
436 builder.getConstInt(loc, cmpInfo.getEqualOrEquiv()->getIntValue());
437 } else {
438 llvm::APSInt ltRes = cmpInfo.getLess()->getIntValue();
439 llvm::APSInt eqRes = cmpInfo.getEqualOrEquiv()->getIntValue();
440 llvm::APSInt gtRes = cmpInfo.getGreater()->getIntValue();
441 if (!cmpInfo.isPartial()) {
442 cir::CmpOrdering ordering = cmpInfo.isStrong()
443 ? cir::CmpOrdering::Strong
444 : cir::CmpOrdering::Weak;
445 resultScalar = builder.createThreeWayCmpTotalOrdering(
446 loc, lhs, rhs, ltRes, eqRes, gtRes, ordering);
447 } else {
448 // Partial ordering.
449 llvm::APSInt unorderedRes = cmpInfo.getUnordered()->getIntValue();
450 resultScalar = builder.createThreeWayCmpPartialOrdering(
451 loc, lhs, rhs, ltRes, eqRes, gtRes, unorderedRes);
452 }
453 }
454
455 emitComparisonResult(e, loc, cmpInfo, resultScalar);
456 }
457
458 void VisitTypeTraitExpr(const TypeTraitExpr *e) {
459 assert(e->isStoredAsComparisonResult() &&
460 "expected a strong_ordering type trait with a stored value");
461
462 const ComparisonCategoryInfo &cmpInfo =
463 cgf.getContext().CompCategories.getInfoForType(e->getType());
464 const auto result =
465 ComparisonCategoryResult(e->getAPValue().getInt().getZExtValue());
466 mlir::Location loc = cgf.getLoc(e->getSourceRange());
467 mlir::Value resultValue = cgf.getBuilder().getConstInt(
468 loc, cmpInfo.getValueInfo(result)->getIntValue());
469
470 emitComparisonResult(e, loc, cmpInfo, resultValue);
471 }
472
473 void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
474 Visit(e->getSemanticForm());
475 }
476 void VisitObjCMessageExpr(ObjCMessageExpr *e) {
477 cgf.cgm.errorNYI(e->getSourceRange(),
478 "AggExprEmitter: VisitObjCMessageExpr");
479 }
480 void VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
481 cgf.cgm.errorNYI(e->getSourceRange(),
482 "AggExprEmitter: VisitObjCIVarRefExpr");
483 }
484
485 void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e) {
486 AggValueSlot dest = ensureSlot(cgf.getLoc(e->getExprLoc()), e->getType());
487 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
488 emitInitializationToLValue(e->getBase(), destLV);
489 VisitInitListExpr(e->getUpdater());
490 }
491 void VisitAbstractConditionalOperator(const AbstractConditionalOperator *e) {
492 mlir::Location loc = cgf.getLoc(e->getSourceRange());
493
494 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
495
496 // Emit the condition before opening the conditional evaluation, so that
497 // the cleanup scope of any temporary the condition creates encloses the
498 // one the evaluation opens.
499 mlir::Value condV = cgf.emitOpOnBoolExpr(loc, e->getCond());
500 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
501
502 // Save whether the destination's lifetime is externally managed.
503 bool isExternallyDestructed = dest.isExternallyDestructed();
504 bool destructNonTrivialCStruct =
505 !isExternallyDestructed &&
507 isExternallyDestructed |= destructNonTrivialCStruct;
508
509 // emitIfOnBoolValue terminates each region; an unconditional yield here
510 // would keep alive the dead block a noreturn arm leaves behind.
511 cgf.emitIfOnBoolValue(
512 condV, loc,
513 /*thenBuilder=*/
514 [&](mlir::OpBuilder &b, mlir::Location loc) {
515 eval.beginEvaluation();
516 {
517 CIRGenFunction::LexicalScope lexScope{cgf, loc,
518 b.getInsertionBlock()};
519 cgf.curLexScope->setAsTernary();
520 dest.setExternallyDestructed(isExternallyDestructed);
522 Visit(e->getTrueExpr());
523 }
524 eval.endEvaluation();
525 },
526 loc,
527 /*elseBuilder=*/
528 [&](mlir::OpBuilder &b, mlir::Location loc) {
529 eval.beginEvaluation();
530 {
531 CIRGenFunction::LexicalScope lexScope{cgf, loc,
532 b.getInsertionBlock()};
533 cgf.curLexScope->setAsTernary();
534
535 // If the result of an agg expression is unused, then the emission
536 // of the LHS might need to create a destination slot. That's fine
537 // with us, and we can safely emit the RHS into the same slot, but
538 // we shouldn't claim that it's already being destructed.
539 dest.setExternallyDestructed(isExternallyDestructed);
541 Visit(e->getFalseExpr());
542 }
543 eval.endEvaluation();
544 },
545 loc);
546
547 if (destructNonTrivialCStruct)
548 cgf.cgm.errorNYI(
549 e->getSourceRange(),
550 "Abstract conditional aggregate: destructNonTrivialCStruct");
551 }
552 void VisitChooseExpr(const ChooseExpr *e) { Visit(e->getChosenSubExpr()); }
553 void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) {
554 visitCXXParenListOrInitListExpr(e, e->getInitExprs(),
556 e->getArrayFiller());
557 }
558
559 void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *e) {
560 CIRGenFunction::OpaqueValueMapping binding(cgf, e->getCommonExpr());
561 uint64_t numElements = e->getArraySize().getZExtValue();
562
563 if (!numElements)
564 return;
565
566 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
567
568 if (!e->getType()->isConstantArrayType())
569 cgf.cgm.errorNYI(e->getSourceRange(),
570 "VisitArrayInitLoopExpr: Non-constant array");
571
572 Address dest = ensureSlot(loc, e->getType()).getAddress();
573 cir::ArrayType arrayTy = cast<cir::ArrayType>(dest.getElementType());
574
575 emitArrayInit(dest, arrayTy, e->getType(),
576 const_cast<ArrayInitLoopExpr *>(e), {}, e->getSubExpr());
577 }
578
579 void VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
580 QualType ty = e->getType();
581 mlir::Location loc = cgf.getLoc(e->getSourceRange());
582 AggValueSlot slot = ensureSlot(loc, ty);
583 emitNullInitializationToLValue(loc,
584 cgf.makeAddrLValue(slot.getAddress(), ty));
585 }
586 void VisitNoInitExpr(NoInitExpr *e) {
587 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitNoInitExpr");
588 }
589 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
590 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
591 Visit(dae->getExpr());
592 }
593 void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *e) {
594 AggValueSlot slot =
595 ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
596 cgf.emitInheritedCXXConstructorCall(e->getConstructor(),
597 e->constructsVBase(), slot.getAddress(),
598 e->inheritedFromVBase(), e);
599 }
600
601 /// Emit the initializer for a std::initializer_list initialized with a
602 /// real initializer list.
603 void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *e) {
604 ASTContext &ctx = cgf.getContext();
605 CIRGenBuilderTy &builder = cgf.getBuilder();
606 mlir::Location loc = cgf.getLoc(e->getExprLoc());
607
608 LValue array = cgf.emitLValue(e->getSubExpr());
609 assert(array.isSimple() && "initializer_list array not a simple lvalue");
610 Address arrayPtr = array.getAddress();
611
612 const ConstantArrayType *arrayType =
614 assert(arrayType && "std::initializer_list constructed from non-array");
615
616 auto *record = e->getType()->castAsRecordDecl();
617 assert(record->getNumFields() == 2 &&
618 "Expected std::initializer_list to only have two fields");
619
620 RecordDecl::field_iterator field = record->field_begin();
621 assert(field != record->field_end() &&
622 ctx.hasSameType(field->getType()->getPointeeType(),
623 arrayType->getElementType()) &&
624 "Expected std::initializer_list first field to be const E *");
625
626 // Start pointer.
627 AggValueSlot dest = ensureSlot(loc, e->getType());
628 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
629 LValue start =
630 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
631
632 mlir::Value arrayStart = arrayPtr.emitRawPointer();
633 cgf.emitStoreThroughLValue(RValue::get(arrayStart), start);
634 ++field;
635 assert(field != record->field_end() &&
636 "Expected std::initializer_list to have two fields");
637
638 cir::ConstantOp size = builder.getConstInt(loc, arrayType->getSize());
639 LValue endOrLength =
640 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
641 if (ctx.hasSameType(field->getType(), ctx.getSizeType())) {
642 // Length.
643 cgf.emitStoreThroughLValue(RValue::get(size), endOrLength);
644 } else {
645 // End pointer.
646 assert(field->getType()->isPointerType() &&
647 ctx.hasSameType(field->getType()->getPointeeType(),
648 arrayType->getElementType()) &&
649 "Expected std::initializer_list second field to be const E *");
650 mlir::Value arrayEnd = builder.createPtrStride(loc, arrayStart, size);
651 cgf.emitStoreThroughLValue(RValue::get(arrayEnd), endOrLength);
652 }
653 }
654
655 void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
656 cgf.cgm.errorNYI(e->getSourceRange(),
657 "AggExprEmitter: VisitCXXScalarValueInitExpr");
658 }
659 void VisitCXXTypeidExpr(CXXTypeidExpr *e) { emitAggLoadOfLValue(e); }
660 void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {
661 Visit(e->getSubExpr());
662 }
663 void VisitOpaqueValueExpr(OpaqueValueExpr *e) {
664 cgf.cgm.errorNYI(e->getSourceRange(),
665 "AggExprEmitter: VisitOpaqueValueExpr");
666 }
667
668 void VisitPseudoObjectExpr(PseudoObjectExpr *e) {
669 cgf.cgm.errorNYI(e->getSourceRange(),
670 "AggExprEmitter: VisitPseudoObjectExpr");
671 }
672
673 void VisitVAArgExpr(VAArgExpr *e) {
674 // emitVAArg returns an aggregate value (not a pointer) at the CIR level.
675 // ABI-specific pointer handling will be done later in LoweringPrepare.
676 mlir::Value vaArgValue = cgf.emitVAArg(e);
677
678 // Create a temporary alloca to hold the aggregate value.
679 mlir::Location loc = cgf.getLoc(e->getSourceRange());
680 Address tmpAddr = cgf.createMemTemp(e->getType(), loc, "vaarg.tmp");
681
682 // Store the va_arg result into the temporary.
683 cgf.emitAggregateStore(vaArgValue, tmpAddr);
684
685 // Create an LValue from the temporary address.
686 LValue tmpLValue = cgf.makeAddrLValue(tmpAddr, e->getType());
687
688 // Copy the aggregate value from temporary to destination.
689 emitFinalDestCopy(e->getType(), tmpLValue);
690 }
691
692 void VisitCXXThrowExpr(const CXXThrowExpr *e) { cgf.emitCXXThrowExpr(e); }
693 void VisitAtomicExpr(AtomicExpr *e) {
694 RValue result = cgf.emitAtomicExpr(e);
695 emitFinalDestCopy(e->getType(), result);
696 }
697};
698
699} // namespace
700
701/// Given an expression with aggregate type that represents a value lvalue, this
702/// method emits the address of the lvalue, then loads the result into DestPtr.
703void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
704 LValue lv = cgf.emitLValue(e);
705
706 // If the type of the l-value is atomic, then do an atomic load.
707 if (lv.getType()->isAtomicType() || cgf.isLValueSuitableForInlineAtomic(lv)) {
708 cgf.emitAtomicLoad(lv, e->getExprLoc(), dest);
709 return;
710 }
711
712 emitFinalDestCopy(e->getType(), lv);
713}
714
715void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
716 if (dest.isPotentiallyAliased() && e->getType().isPODType(cgf.getContext())) {
717 // For a POD type, just emit a load of the lvalue + a copy, because our
718 // compound literal might alias the destination.
719 emitAggLoadOfLValue(e);
720 return;
721 }
722
723 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
724
725 // Block-scope compound literals are destroyed at the end of the enclosing
726 // scope in C.
727 bool destruct =
728 !cgf.getLangOpts().CPlusPlus && !slot.isExternallyDestructed();
729 if (destruct)
731
732 cgf.emitAggExpr(e->getInitializer(), slot);
733
734 if (destruct)
735 if ([[maybe_unused]] QualType::DestructionKind dtorKind =
737 cgf.cgm.errorNYI(e->getSourceRange(), "compound literal with destructor");
738}
739
740void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
741 QualType arrayQTy, Expr *e,
742 ArrayRef<Expr *> args, Expr *arrayFiller) {
743 CIRGenBuilderTy &builder = cgf.getBuilder();
744 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
745
746 const uint64_t numInitElements = args.size();
747
748 bool setArrayInitLoopExprScope = isa<ArrayInitLoopExpr>(e);
749
750 const QualType elementType =
751 cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
752
753 const QualType elementPtrType = cgf.getContext().getPointerType(elementType);
754
755 const mlir::Type cirElementType = cgf.convertType(elementType);
756 const cir::PointerType cirElementPtrType =
757 builder.getPointerTo(cirElementType, destPtr.getAddressSpace());
758
759 auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,
760 cir::CastKind::array_to_ptrdecay,
761 destPtr.getPointer());
762
763 const CharUnits elementSize =
764 cgf.getContext().getTypeSizeInChars(elementType);
765 const CharUnits elementAlign =
766 destPtr.getAlignment().alignmentOfArrayElement(elementSize);
767
768 // Destroy already-constructed elements if a later initializer throws.
769 // The cleanup is deactivated when this initialization finishes.
770 QualType::DestructionKind dtorKind = elementType.isDestructedType();
771 Address endOfInit = Address::invalid();
772 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
773
774 if (dtorKind && cgf.getLangOpts().Exceptions) {
775 endOfInit = cgf.createTempAlloca(cirElementPtrType, cgf.getPointerAlign(),
776 loc, "arrayinit.endOfInit");
777 builder.createStore(loc, begin, endOfInit);
778
779 cgf.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType,
780 elementAlign,
781 cgf.getDestroyer(dtorKind));
782 }
783
784 // The 'current element to initialize'. The invariants on this
785 // variable are complicated. Essentially, after each iteration of
786 // the loop, it points to the last initialized element, except
787 // that it points to the beginning of the array before any
788 // elements have been initialized.
789 mlir::Value element = begin;
790
791 // Don't build the 'one' before the cycle to avoid
792 // emmiting the redundant `cir.const 1` instrs.
793 mlir::Value one;
794
795 // Emit the explicit initializers.
796 for (uint64_t i = 0; i != numInitElements; ++i) {
797 // Advance to the next element.
798 if (i > 0) {
799 one = builder.getConstantInt(loc, cgf.ptrDiffTy, i);
800 element = builder.createPtrStride(loc, begin, one);
801
802 // Tell the cleanup that it needs to destroy up to this element.
803 if (endOfInit.isValid())
804 builder.createStore(loc, element, endOfInit);
805 }
806
807 const Address address = Address(element, cirElementType, elementAlign);
808 const LValue elementLV = cgf.makeAddrLValue(address, elementType);
809 emitInitializationToLValue(args[i], elementLV);
810 }
811
812 const uint64_t numArrayElements = arrayTy.getSize();
813
814 // Check whether there's a non-trivial array-fill expression.
815 const bool hasTrivialFiller = CodeGenUtils::isTrivialFiller(arrayFiller);
816
817 // Any remaining elements need to be zero-initialized, possibly
818 // using the filler expression. We can skip this if the we're
819 // emitting to zeroed memory.
820 if (numInitElements != numArrayElements &&
821 !(dest.isZeroed() && hasTrivialFiller &&
822 cgf.getTypes().isZeroInitializable(elementType))) {
823 // Advance to the start of the rest of the array.
824 if (numInitElements) {
825 one = builder.getConstantInt(loc, cgf.ptrDiffTy, 1);
826 element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
827 element, one);
828
829 if (endOfInit.isValid())
830 builder.createStore(loc, element, endOfInit);
831 }
832
833 // Allocate the temporary variable
834 // to store the pointer to first unitialized element
835 const Address tmpAddr = cgf.createTempAlloca(
836 cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");
837 LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType);
838 cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
839
840 // Compute the end of array
841 cir::ConstantOp numArrayElementsConst = builder.getConstInt(
842 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), numArrayElements);
843 mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
844 begin, numArrayElementsConst);
845
846 builder.createDoWhile(
847 loc,
848 /*condBuilder=*/
849 [&](mlir::OpBuilder &b, mlir::Location loc) {
850 cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
851 cir::CmpOp cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
852 currentElement, end);
853 builder.createCondition(cmp);
854 },
855 /*bodyBuilder=*/
856 [&](mlir::OpBuilder &b, mlir::Location loc) {
857 cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
858
859 // Emit the actual filler expression.
860 LValue elementLV = cgf.makeAddrLValue(
861 Address(currentElement, cirElementType, elementAlign),
862 elementType);
863
864 mlir::Value idx;
865 if (setArrayInitLoopExprScope)
866 idx = cir::PtrDiffOp::create(b, loc, cgf.ptrDiffTy, currentElement,
867 begin);
868
869 CIRGenFunction::ArrayInitLoopExprScope loopExprScope(
870 cgf, setArrayInitLoopExprScope, idx);
871
872 // C++17 [class.temporary]p5:
873 // "when a default constructor is called to initialize an element of
874 // an array with no corresponding initializer [...] the destruction
875 // of every temporary created in a default argument is sequenced
876 // before the construction of the next array element, if any."
877 if (arrayFiller) {
878 CIRGenFunction::FullExprCleanupScope scope(cgf, arrayFiller);
879 scope.deferLifetimeExtendedCleanups();
880 emitInitializationToLValue(arrayFiller, elementLV);
881 } else {
882 emitNullInitializationToLValue(loc, elementLV);
883 }
884
885 // Advance pointer and store them to temporary variable
886 cir::ConstantOp one = builder.getConstInt(
887 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), 1);
888 auto nextElement = cir::PtrStrideOp::create(
889 builder, loc, cirElementPtrType, currentElement, one);
890
891 // Tell the EH cleanup that we finished with the last element.
892 if (endOfInit.isValid())
893 builder.createStore(loc, nextElement, endOfInit);
894
895 cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
896
897 builder.createYield(loc);
898 });
899 }
900}
901
902/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
903void AggExprEmitter::emitFinalDestCopy(QualType type, RValue src) {
904 assert(src.isAggregate() && "value must be aggregate value!");
905 LValue srcLV = cgf.makeAddrLValue(src.getAggregateAddress(), type);
906 emitFinalDestCopy(type, srcLV, CIRGenFunction::EVK_RValue);
907}
908
909/// Perform the final copy to destPtr, if desired.
910void AggExprEmitter::emitFinalDestCopy(
911 QualType type, const LValue &src,
912 CIRGenFunction::ExprValueKind srcValueKind) {
913 // If dest is ignored, then we're evaluating an aggregate expression
914 // in a context that doesn't care about the result. Note that loads
915 // from volatile l-values force the existence of a non-ignored
916 // destination.
917 if (dest.isIgnored())
918 return;
919
920 if (srcValueKind == CIRGenFunction::EVK_RValue) {
921 if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) {
922 cgf.cgm.errorNYI("emitFinalDestCopy: EVK_RValue & PCK_Struct");
923 }
924 } else {
925 if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
926 cgf.cgm.errorNYI("emitFinalDestCopy: !EVK_RValue & PCK_Struct");
927 }
928 }
929
933
934 AggValueSlot srcAgg = AggValueSlot::forLValue(src, AggValueSlot::IsDestructed,
937 emitCopy(type, dest, srcAgg);
938}
939
940/// Perform a copy from the source into the destination.
941///
942/// \param type - the type of the aggregate being copied; qualifiers are
943/// ignored
944void AggExprEmitter::emitCopy(QualType type, const AggValueSlot &dest,
945 const AggValueSlot &src) {
947
948 // If the result of the assignment is used, copy the LHS there also.
949 // It's volatile if either side is. Use the minimum alignment of
950 // the two sides.
951 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), type);
952 LValue srcLV = cgf.makeAddrLValue(src.getAddress(), type);
954 cgf.emitAggregateCopy(destLV, srcLV, type, dest.mayOverlap(),
955 dest.isVolatile() || src.isVolatile());
956}
957
958void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
959 const QualType type = lv.getType();
960
962 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
963 return emitNullInitializationToLValue(loc, lv);
964 }
965
966 if (isa<NoInitExpr>(e))
967 return;
968
969 if (type->isReferenceType()) {
970 RValue rv = cgf.emitReferenceBindingToExpr(e);
971 return cgf.emitStoreThroughLValue(rv, lv);
972 }
973
974 switch (cgf.getEvaluationKind(type)) {
975 case cir::TEK_Complex:
976 cgf.emitComplexExprIntoLValue(e, lv, /*isInit*/ true);
977 break;
982 dest.isZeroed()));
983
984 return;
985 case cir::TEK_Scalar:
986 if (lv.isSimple())
987 cgf.emitScalarInit(e, lv);
988 else
990 return;
991 }
992}
993
994void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *e) {
995 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
996 cgf.emitCXXConstructExpr(e, slot);
997}
998
999void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
1000 LValue lv) {
1001 const QualType type = lv.getType();
1002
1003 // If the destination slot is already zeroed out before the aggregate is
1004 // copied into it, we don't have to emit any zeros here.
1005 if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
1006 return;
1007
1008 if (cgf.hasScalarEvaluationKind(type)) {
1009 // For non-aggregates, we can store the appropriate null constant.
1010 mlir::Value null = cgf.cgm.emitNullConstant(type, loc);
1011 if (lv.isSimple()) {
1012 cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
1013 return;
1014 }
1015
1017 return;
1018 }
1019
1020 // There's a potential optimization opportunity in combining
1021 // memsets; that would be easy for arrays, but relatively
1022 // difficult for structures with the current code.
1023 cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
1024}
1025
1026void AggExprEmitter::emitComparisonResult(const Expr *e, mlir::Location loc,
1027 const ComparisonCategoryInfo &cmpInfo,
1028 mlir::Value resultValue) {
1029 // Create the return value in the destination slot.
1030 ensureDest(loc, e->getType());
1031 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->getType());
1032
1033 // Emit the address of the first (and only) field in the comparison category
1034 // type, and initialize it from the constant integer value produced above.
1035 const FieldDecl *resultField = *cmpInfo.Record->field_begin();
1036 LValue fieldLVal = cgf.emitLValueForFieldInitialization(
1037 destLVal, resultField, resultField->getName());
1038 cgf.emitStoreThroughLValue(RValue::get(resultValue), fieldLVal);
1039}
1040
1041void AggExprEmitter::VisitLambdaExpr(LambdaExpr *e) {
1042 CIRGenFunction::SourceLocRAIIObject loc{cgf, e->getSourceRange()};
1043 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
1044 LValue slotLV = cgf.makeAddrLValue(slot.getAddress(), e->getType());
1045
1046 // We'll need to enter cleanup scopes in case any of the element
1047 // initializers throws an exception or contains branch out of the expressions.
1048 CIRGenFunction::CleanupDeactivationScope deactivationScope(cgf);
1049
1050 for (auto [curField, capture, captureInit] : llvm::zip(
1051 e->getLambdaClass()->fields(), e->captures(), e->capture_inits())) {
1052 // Pick a name for the field.
1053 llvm::StringRef fieldName = curField->getName();
1054 if (capture.capturesVariable()) {
1055 assert(!curField->isBitField() && "lambdas don't have bitfield members!");
1056 ValueDecl *v = capture.getCapturedVar();
1057 fieldName = v->getName();
1058 cgf.cgm.lambdaFieldToName[curField] = fieldName;
1059 } else if (capture.capturesThis()) {
1060 cgf.cgm.lambdaFieldToName[curField] = "this";
1061 } else {
1062 cgf.cgm.errorNYI(e->getSourceRange(), "Unhandled capture kind");
1063 cgf.cgm.lambdaFieldToName[curField] = "unhandled-capture-kind";
1064 }
1065
1066 // Emit initialization
1067 LValue lv =
1068 cgf.emitLValueForFieldInitialization(slotLV, curField, fieldName);
1069 if (curField->hasCapturedVLAType())
1070 cgf.cgm.errorNYI(e->getSourceRange(), "lambda captured VLA type");
1071
1072 emitInitializationToLValue(captureInit, lv);
1073
1074 // Push a destructor if necessary.
1075 if (QualType::DestructionKind dtorKind =
1076 curField->getType().isDestructedType()) {
1077 assert(lv.isSimple());
1079 curField->getType(),
1080 cgf.getDestroyer(dtorKind), false);
1081 }
1082 }
1083}
1084
1085void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1086 CIRGenFunction::FullExprCleanupScope fullExprScope(cgf, e->getSubExpr());
1087 Visit(e->getSubExpr());
1088}
1089
1090void AggExprEmitter::VisitCallExpr(const CallExpr *e) {
1091 if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
1092 cgf.cgm.errorNYI(e->getSourceRange(), "reference return type");
1093 return;
1094 }
1095
1096 withReturnValueSlot(
1097 e, [&](ReturnValueSlot slot) { return cgf.emitCallExpr(e, slot); });
1098}
1099
1100void AggExprEmitter::withReturnValueSlot(
1101 const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
1102 QualType retTy = e->getType();
1103
1105 bool requiresDestruction =
1107 if (requiresDestruction)
1108 cgf.cgm.errorNYI(
1109 e->getSourceRange(),
1110 "withReturnValueSlot: return value requiring destruction is NYI");
1111
1112 // If it makes no observable difference, save a memcpy + temporary.
1113 //
1114 // We need to always provide our own temporary if destruction is required.
1115 // Otherwise, fn will emit its own, notice that it's "unused", and end its
1116 // lifetime before we have the chance to emit a proper destructor call.
1119
1120 Address retAddr = dest.getAddress();
1122
1125 fn(ReturnValueSlot(retAddr));
1126}
1127
1128void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
1129 if (e->hadArrayRangeDesignator())
1130 llvm_unreachable("GNU array range designator extension");
1131
1132 if (e->isTransparent())
1133 return Visit(e->getInit(0));
1134
1135 visitCXXParenListOrInitListExpr(
1136 e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());
1137}
1138
1139void AggExprEmitter::visitCXXParenListOrInitListExpr(
1140 Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
1141 Expr *arrayFiller) {
1142
1143 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
1144 const AggValueSlot dest = ensureSlot(loc, e->getType());
1145
1146 if (e->getType()->isConstantArrayType()) {
1147 cir::ArrayType arrayTy =
1149 emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,
1150 arrayFiller);
1151 return;
1152 } else if (e->getType()->isVariableArrayType()) {
1153 cgf.cgm.errorNYI(e->getSourceRange(),
1154 "visitCXXParenListOrInitListExpr variable array type");
1155 return;
1156 }
1157
1158 if (e->getType()->isArrayType()) {
1159 cgf.cgm.errorNYI(e->getSourceRange(),
1160 "visitCXXParenListOrInitListExpr array type");
1161 return;
1162 }
1163
1164 assert(e->getType()->isRecordType() && "Only support structs/unions here!");
1165
1166 // Do struct initialization; this code just sets each individual member
1167 // to the approprate value. This makes bitfield support automatic;
1168 // the disadvantage is that the generated code is more difficult for
1169 // the optimizer, especially with bitfields.
1170 unsigned numInitElements = args.size();
1171 auto *record = e->getType()->castAsRecordDecl();
1172
1173 // We'll need to enter cleanup scopes in case any of the element
1174 // initializers throws an exception.
1175 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
1176
1177 unsigned curInitIndex = 0;
1178
1179 // Emit initialization of base classes.
1180 if (auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) {
1181 assert(numInitElements >= cxxrd->getNumBases() &&
1182 "missing initializer for base class");
1183 for (auto &base : cxxrd->bases()) {
1184 assert(!base.isVirtual() && "should not see vbases here");
1185 CXXRecordDecl *baseRD = base.getType()->getAsCXXRecordDecl();
1187 loc, dest.getAddress(), cxxrd, baseRD,
1188 /*baseIsVirtual=*/false);
1190 AggValueSlot aggSlot = AggValueSlot::forAddr(
1191 address, Qualifiers(), AggValueSlot::IsDestructed,
1193 cgf.getOverlapForBaseInit(cxxrd, baseRD, false));
1194 cgf.emitAggExpr(args[curInitIndex++], aggSlot);
1195
1196 if (QualType::DestructionKind dtorKind =
1197 base.getType().isDestructedType())
1198 cgf.pushDestroyAndDeferDeactivation(dtorKind, address, base.getType());
1199 }
1200 }
1201
1202 // Prepare a 'this' for CXXDefaultInitExprs.
1203 CIRGenFunction::FieldConstructionScope fcScope(cgf, dest.getAddress());
1204
1205 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
1206
1207 if (record->isUnion()) {
1208 // Only initialize one field of a union. The field itself is
1209 // specified by the initializer list.
1210 if (!initializedFieldInUnion) {
1211 // Empty union; we have nothing to do.
1212
1213 // Make sure that it's really an empty and not a failure of
1214 // semantic analysis.
1215 assert(llvm::all_of(record->fields(),
1216 [](const FieldDecl *f) {
1217 return f->isUnnamedBitField() ||
1218 f->isAnonymousStructOrUnion();
1219 }) &&
1220 "Only unnamed bitfields or anonymous class allowed");
1221 return;
1222 }
1223
1224 // FIXME: volatility
1225 FieldDecl *initedField = initializedFieldInUnion;
1226
1227 LValue fieldLV = cgf.emitLValueForFieldInitialization(
1228 destLV, initedField, initedField->getName());
1229
1230 if (numInitElements) {
1231 // Store the initializer into the field
1232 emitInitializationToLValue(args[0], fieldLV);
1233 } else {
1234 // Default-initialize to null.
1235 emitNullInitializationToLValue(loc, fieldLV);
1236 }
1237 return;
1238 }
1239
1240 // Here we iterate over the fields; this makes it simpler to both
1241 // default-initialize fields and skip over unnamed fields.
1242 for (const FieldDecl *field : record->fields()) {
1243 // We're done once we hit the flexible array member.
1244 if (field->getType()->isIncompleteArrayType())
1245 break;
1246
1247 // Always skip anonymous bitfields.
1248 if (field->isUnnamedBitField())
1249 continue;
1250
1251 // We're done if we reach the end of the explicit initializers, we
1252 // have a zeroed object, and the rest of the fields are
1253 // zero-initializable.
1254 if (curInitIndex == numInitElements && dest.isZeroed() &&
1256 break;
1257 LValue lv =
1258 cgf.emitLValueForFieldInitialization(destLV, field, field->getName());
1259 // We never generate write-barriers for initialized fields.
1261
1262 if (curInitIndex < numInitElements) {
1263 // Store the initializer into the field.
1264 CIRGenFunction::SourceLocRAIIObject loc{cgf, record->getSourceRange()};
1265 emitInitializationToLValue(args[curInitIndex++], lv);
1266 } else {
1267 // We're out of initializers; default-initialize to null
1268 emitNullInitializationToLValue(cgf.getLoc(e->getSourceRange()), lv);
1269 }
1270
1271 // Push a destructor if necessary.
1272 // FIXME: if we have an array of structures, all explicitly
1273 // initialized, we can end up pushing a linear number of cleanups.
1274 if (QualType::DestructionKind dtorKind =
1275 field->getType().isDestructedType()) {
1276 assert(lv.isSimple());
1278 field->getType(),
1279 cgf.getDestroyer(dtorKind), false);
1280 }
1281
1282 // From classic codegen, maybe not useful for CIR:
1283 // If the GEP didn't get used because of a dead zero init or something
1284 // else, clean it up for -O0 builds and general tidiness.
1285 }
1286}
1287
1288// TODO(cir): This could be shared with classic codegen.
1290 const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual) {
1291 // If the most-derived object is a field declared with [[no_unique_address]],
1292 // the tail padding of any virtual base could be reused for other subobjects
1293 // of that field's class.
1294 if (isVirtual)
1296
1297 // Empty bases can overlap earlier bases.
1298 if (baseRD->isEmpty())
1300
1301 // If the base class is laid out entirely within the nvsize of the derived
1302 // class, its tail padding cannot yet be initialized, so we can issue
1303 // stores at the full width of the base class.
1304 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1305 if (layout.getBaseClassOffset(baseRD) +
1306 getContext().getASTRecordLayout(baseRD).getSize() <=
1307 layout.getNonVirtualSize())
1309
1310 // The tail padding may contain values we need to preserve.
1312}
1313
1315 AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
1316}
1317
1319 AggValueSlot::Overlap_t mayOverlap,
1320 bool isVolatile) {
1321 // TODO(cir): this function needs improvements, commented code for now since
1322 // this will be touched again soon.
1323 assert(!ty->isAnyComplexType() && "Unexpected copy of complex");
1324
1325 Address destPtr = dest.getAddress();
1326 Address srcPtr = src.getAddress();
1327
1328 if (getLangOpts().CPlusPlus) {
1329 if (auto *record = ty->getAsCXXRecordDecl()) {
1330 assert((record->hasTrivialCopyConstructor() ||
1331 record->hasTrivialCopyAssignment() ||
1332 record->hasTrivialMoveConstructor() ||
1333 record->hasTrivialMoveAssignment() ||
1334 record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&
1335 "Trying to aggregate-copy a type without a trivial copy/move "
1336 "constructor or assignment operator");
1337 // Ignore empty classes in C++.
1338 if (record->isEmpty())
1339 return;
1340 }
1341 }
1342
1344
1345 // Aggregate assignment turns into llvm.memcpy. This is almost valid per
1346 // C99 6.5.16.1p3, which states "If the value being stored in an object is
1347 // read from another object that overlaps in anyway the storage of the first
1348 // object, then the overlap shall be exact and the two objects shall have
1349 // qualified or unqualified versions of a compatible type."
1350 //
1351 // memcpy is not defined if the source and destination pointers are exactly
1352 // equal, but other compilers do this optimization, and almost every memcpy
1353 // implementation handles this case safely. If there is a libc that does not
1354 // safely handle this, we can add a target hook.
1355
1356 // Get data size info for this aggregate. Don't copy the tail padding if this
1357 // might be a potentially-overlapping subobject, since the tail padding might
1358 // be occupied by a different object. Otherwise, copying it is fine.
1359 TypeInfoChars typeInfo;
1360 if (mayOverlap)
1361 typeInfo = getContext().getTypeInfoDataSizeInChars(ty);
1362 else
1363 typeInfo = getContext().getTypeInfoInChars(ty);
1364
1366
1367 // Don't do any of the memmove_collectable tests if GC isn't set.
1368 if (cgm.getLangOpts().getGC() != LangOptions::NonGC)
1369 cgm.errorNYI("emitAggregateCopy: GC");
1370
1371 // If the data size (excluding tail padding) differs from the full type size,
1372 // use skip_tail_padding to avoid clobbering tail padding that may be occupied
1373 // by other objects (e.g. fields marked with [[no_unique_address]]).
1374 CharUnits dataSize = typeInfo.Width;
1375 bool skipTailPadding =
1376 mayOverlap && dataSize != getContext().getTypeSizeInChars(ty);
1377 // NOTE(cir): original codegen would normally convert destPtr and srcPtr to
1378 // i8* since memcpy operates on bytes. We don't need that in CIR because
1379 // cir.copy will operate on any CIR pointer that points to a sized type.
1380 builder.createCopy(destPtr, srcPtr, isVolatile, skipTailPadding);
1381
1383}
1384
1385// TODO(cir): This could be shared with classic codegen.
1388 if (!fd->hasAttr<NoUniqueAddressAttr>() || !fd->getType()->isRecordType())
1390
1391 // Empty fields can overlap earlier fields.
1392 if (fd->getType()->getAsCXXRecordDecl()->isEmpty())
1394
1395 // If the field lies entirely within the enclosing class's nvsize, its tail
1396 // padding cannot overlap any already-initialized object. (The only subobjects
1397 // with greater addresses that might already be initialized are vbases.)
1398 const RecordDecl *classRD = fd->getParent();
1399 const ASTRecordLayout &layout = getContext().getASTRecordLayout(classRD);
1400 if (layout.getFieldOffset(fd->getFieldIndex()) +
1401 getContext().getTypeSize(fd->getType()) <=
1402 (uint64_t)getContext().toBits(layout.getNonVirtualSize()))
1404
1405 // The tail padding may contain values we need to preserve.
1407}
1408
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.
Defines the clang::Expr interface and subclasses for C++ expressions.
*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:573
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...
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Definition Expr.h:4600
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4606
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4612
llvm::APInt getArraySize() const
Definition Expr.h:6076
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition Expr.h:6069
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition Expr.h:6074
QualType getElementType() const
Definition TypeBase.h:3832
Expr * getLHS() const
Definition Expr.h:4157
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4162
SourceLocation getExprLoc() const
Definition Expr.h:4148
Expr * getRHS() const
Definition Expr.h:4159
Opcode getOpcode() const
Definition Expr.h:4152
mlir::ptr::MemorySpaceAttrInterface getAddressSpace() const
Definition Address.h:133
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)
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 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)
void emitScalarInit(const clang::Expr *init, LValue lvalue, bool capturedByInit=false)
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)
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)
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
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)
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
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:1516
const Expr * getSubExpr() const
Definition ExprCXX.h:1520
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1137
bool constructsVBase() const
Determine whether this constructor is actually constructing a base class (rather than a complete obje...
Definition ExprCXX.h:1797
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will call.
Definition ExprCXX.h:1793
bool inheritedFromVBase() const
Determine whether the inherited constructor is inherited from a virtual base of the object we constru...
Definition ExprCXX.h:1807
MutableArrayRef< Expr * > getInitExprs()
Definition ExprCXX.h:5235
FieldDecl * getInitializedFieldInUnion()
Definition ExprCXX.h:5273
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
bool isEmpty() const
Determine whether this is an empty class in the sense of (C++11 [meta.unary.prop]).
Definition DeclCXX.h:1196
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:309
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1635
CastKind getCastKind() const
Definition Expr.h:3789
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1987
Expr * getSubExpr()
Definition Expr.h:3795
This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
Test whether the quantity equals zero.
Definition CharUnits.h:101
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:184
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4953
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:3702
bool hasAttr() const
Definition DeclBase.h:586
InitListExpr * getUpdater() const
Definition Expr.h:6022
This represents one expression.
Definition Expr.h:114
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:3156
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:3728
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:146
Represents a member of a struct/union/class.
Definition Decl.h:3341
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3426
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3577
const Expr * getSubExpr() const
Definition Expr.h:1107
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6554
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
Definition Expr.cpp:2501
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
Definition Expr.h:5515
bool hadArrayRangeDesignator() const
Definition Expr.h:5569
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
Definition Expr.h:5491
const Expr * getInit(unsigned Init) const
Definition Expr.h:5443
ArrayRef< Expr * > inits() const
Definition Expr.h:5441
llvm::iterator_range< capture_init_iterator > capture_inits()
Retrieve the initialization expressions for this lambda's captures.
Definition ExprCXX.h:2088
capture_range captures() const
Retrieve this lambda's captures.
Definition ExprCXX.cpp:1403
CXXRecordDecl * getLambdaClass() const
Retrieve the class that corresponds to the lambda.
Definition ExprCXX.cpp:1432
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4991
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:303
Expr * getSelectedExpr() const
Definition ExprCXX.h:4693
const Expr * getSubExpr() const
Definition Expr.h:2268
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8662
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:2914
@ 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:4506
field_range fields() const
Definition Decl.h:4709
specific_decl_iterator< FieldDecl > field_iterator
Definition Decl.h:4706
field_iterator field_begin() const
Definition Decl.cpp:5383
CompoundStmt * getSubStmt()
Definition Expr.h:4681
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:2958
const APValue & getAPValue() const
Definition ExprCXX.h:2967
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:8918
bool isArrayType() const
Definition TypeBase.h:8914
bool isPointerType() const
Definition TypeBase.h:8815
bool isReferenceType() const
Definition TypeBase.h:8839
bool isVariableArrayType() const
Definition TypeBase.h:8926
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9326
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2631
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8950
bool isMemberPointerType() const
Definition TypeBase.h:8896
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2533
bool isNullPtrType() const
Definition TypeBase.h:9241
bool isRecordType() const
Definition TypeBase.h:8942
Expr * getSubExpr() const
Definition Expr.h:2354
QualType getType() const
Definition Decl.h:725
bool isTrivialFiller(const Expr *E)
Check whether E is a trivial array filler, that is, one that is equivalent to zero-initialization.
bool isBlockVarRef(const Expr *E)
Check whether the value of E is possibly a reference to or into a __block variable.
Definition ExprUtils.cpp:24
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< ArrayType > arrayType
const AstTypeMatcher< AtomicType > atomicType
@ 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 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...