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 if (arrayFiller)
873 emitInitializationToLValue(arrayFiller, elementLV);
874 else
875 emitNullInitializationToLValue(loc, elementLV);
876
877 // Advance pointer and store them to temporary variable
878 cir::ConstantOp one = builder.getConstInt(
879 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), 1);
880 auto nextElement = cir::PtrStrideOp::create(
881 builder, loc, cirElementPtrType, currentElement, one);
882
883 // Tell the EH cleanup that we finished with the last element.
884 if (endOfInit.isValid())
885 builder.createStore(loc, nextElement, endOfInit);
886
887 cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
888
889 builder.createYield(loc);
890 });
891 }
892}
893
894/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
895void AggExprEmitter::emitFinalDestCopy(QualType type, RValue src) {
896 assert(src.isAggregate() && "value must be aggregate value!");
897 LValue srcLV = cgf.makeAddrLValue(src.getAggregateAddress(), type);
898 emitFinalDestCopy(type, srcLV, CIRGenFunction::EVK_RValue);
899}
900
901/// Perform the final copy to destPtr, if desired.
902void AggExprEmitter::emitFinalDestCopy(
903 QualType type, const LValue &src,
904 CIRGenFunction::ExprValueKind srcValueKind) {
905 // If dest is ignored, then we're evaluating an aggregate expression
906 // in a context that doesn't care about the result. Note that loads
907 // from volatile l-values force the existence of a non-ignored
908 // destination.
909 if (dest.isIgnored())
910 return;
911
912 if (srcValueKind == CIRGenFunction::EVK_RValue) {
913 if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) {
914 cgf.cgm.errorNYI("emitFinalDestCopy: EVK_RValue & PCK_Struct");
915 }
916 } else {
917 if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
918 cgf.cgm.errorNYI("emitFinalDestCopy: !EVK_RValue & PCK_Struct");
919 }
920 }
921
925
926 AggValueSlot srcAgg = AggValueSlot::forLValue(src, AggValueSlot::IsDestructed,
929 emitCopy(type, dest, srcAgg);
930}
931
932/// Perform a copy from the source into the destination.
933///
934/// \param type - the type of the aggregate being copied; qualifiers are
935/// ignored
936void AggExprEmitter::emitCopy(QualType type, const AggValueSlot &dest,
937 const AggValueSlot &src) {
939
940 // If the result of the assignment is used, copy the LHS there also.
941 // It's volatile if either side is. Use the minimum alignment of
942 // the two sides.
943 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), type);
944 LValue srcLV = cgf.makeAddrLValue(src.getAddress(), type);
946 cgf.emitAggregateCopy(destLV, srcLV, type, dest.mayOverlap(),
947 dest.isVolatile() || src.isVolatile());
948}
949
950void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
951 const QualType type = lv.getType();
952
954 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
955 return emitNullInitializationToLValue(loc, lv);
956 }
957
958 if (isa<NoInitExpr>(e))
959 return;
960
961 if (type->isReferenceType()) {
962 RValue rv = cgf.emitReferenceBindingToExpr(e);
963 return cgf.emitStoreThroughLValue(rv, lv);
964 }
965
966 switch (cgf.getEvaluationKind(type)) {
967 case cir::TEK_Complex:
968 cgf.emitComplexExprIntoLValue(e, lv, /*isInit*/ true);
969 break;
974 dest.isZeroed()));
975
976 return;
977 case cir::TEK_Scalar:
978 if (lv.isSimple())
979 cgf.emitScalarInit(e, lv);
980 else
982 return;
983 }
984}
985
986void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *e) {
987 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
988 cgf.emitCXXConstructExpr(e, slot);
989}
990
991void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
992 LValue lv) {
993 const QualType type = lv.getType();
994
995 // If the destination slot is already zeroed out before the aggregate is
996 // copied into it, we don't have to emit any zeros here.
997 if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
998 return;
999
1000 if (cgf.hasScalarEvaluationKind(type)) {
1001 // For non-aggregates, we can store the appropriate null constant.
1002 mlir::Value null = cgf.cgm.emitNullConstant(type, loc);
1003 if (lv.isSimple()) {
1004 cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
1005 return;
1006 }
1007
1009 return;
1010 }
1011
1012 // There's a potential optimization opportunity in combining
1013 // memsets; that would be easy for arrays, but relatively
1014 // difficult for structures with the current code.
1015 cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
1016}
1017
1018void AggExprEmitter::emitComparisonResult(const Expr *e, mlir::Location loc,
1019 const ComparisonCategoryInfo &cmpInfo,
1020 mlir::Value resultValue) {
1021 // Create the return value in the destination slot.
1022 ensureDest(loc, e->getType());
1023 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->getType());
1024
1025 // Emit the address of the first (and only) field in the comparison category
1026 // type, and initialize it from the constant integer value produced above.
1027 const FieldDecl *resultField = *cmpInfo.Record->field_begin();
1028 LValue fieldLVal = cgf.emitLValueForFieldInitialization(
1029 destLVal, resultField, resultField->getName());
1030 cgf.emitStoreThroughLValue(RValue::get(resultValue), fieldLVal);
1031}
1032
1033void AggExprEmitter::VisitLambdaExpr(LambdaExpr *e) {
1034 CIRGenFunction::SourceLocRAIIObject loc{cgf, e->getSourceRange()};
1035 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
1036 LValue slotLV = cgf.makeAddrLValue(slot.getAddress(), e->getType());
1037
1038 // We'll need to enter cleanup scopes in case any of the element
1039 // initializers throws an exception or contains branch out of the expressions.
1040 CIRGenFunction::CleanupDeactivationScope deactivationScope(cgf);
1041
1042 for (auto [curField, capture, captureInit] : llvm::zip(
1043 e->getLambdaClass()->fields(), e->captures(), e->capture_inits())) {
1044 // Pick a name for the field.
1045 llvm::StringRef fieldName = curField->getName();
1046 if (capture.capturesVariable()) {
1047 assert(!curField->isBitField() && "lambdas don't have bitfield members!");
1048 ValueDecl *v = capture.getCapturedVar();
1049 fieldName = v->getName();
1050 cgf.cgm.lambdaFieldToName[curField] = fieldName;
1051 } else if (capture.capturesThis()) {
1052 cgf.cgm.lambdaFieldToName[curField] = "this";
1053 } else {
1054 cgf.cgm.errorNYI(e->getSourceRange(), "Unhandled capture kind");
1055 cgf.cgm.lambdaFieldToName[curField] = "unhandled-capture-kind";
1056 }
1057
1058 // Emit initialization
1059 LValue lv =
1060 cgf.emitLValueForFieldInitialization(slotLV, curField, fieldName);
1061 if (curField->hasCapturedVLAType())
1062 cgf.cgm.errorNYI(e->getSourceRange(), "lambda captured VLA type");
1063
1064 emitInitializationToLValue(captureInit, lv);
1065
1066 // Push a destructor if necessary.
1067 if (QualType::DestructionKind dtorKind =
1068 curField->getType().isDestructedType()) {
1069 assert(lv.isSimple());
1071 curField->getType(),
1072 cgf.getDestroyer(dtorKind), false);
1073 }
1074 }
1075}
1076
1077void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1078 CIRGenFunction::FullExprCleanupScope fullExprScope(cgf, e->getSubExpr());
1079 Visit(e->getSubExpr());
1080}
1081
1082void AggExprEmitter::VisitCallExpr(const CallExpr *e) {
1083 if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
1084 cgf.cgm.errorNYI(e->getSourceRange(), "reference return type");
1085 return;
1086 }
1087
1088 withReturnValueSlot(
1089 e, [&](ReturnValueSlot slot) { return cgf.emitCallExpr(e, slot); });
1090}
1091
1092void AggExprEmitter::withReturnValueSlot(
1093 const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
1094 QualType retTy = e->getType();
1095
1097 bool requiresDestruction =
1099 if (requiresDestruction)
1100 cgf.cgm.errorNYI(
1101 e->getSourceRange(),
1102 "withReturnValueSlot: return value requiring destruction is NYI");
1103
1104 // If it makes no observable difference, save a memcpy + temporary.
1105 //
1106 // We need to always provide our own temporary if destruction is required.
1107 // Otherwise, fn will emit its own, notice that it's "unused", and end its
1108 // lifetime before we have the chance to emit a proper destructor call.
1111
1112 Address retAddr = dest.getAddress();
1114
1117 fn(ReturnValueSlot(retAddr));
1118}
1119
1120void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
1121 if (e->hadArrayRangeDesignator())
1122 llvm_unreachable("GNU array range designator extension");
1123
1124 if (e->isTransparent())
1125 return Visit(e->getInit(0));
1126
1127 visitCXXParenListOrInitListExpr(
1128 e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());
1129}
1130
1131void AggExprEmitter::visitCXXParenListOrInitListExpr(
1132 Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
1133 Expr *arrayFiller) {
1134
1135 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
1136 const AggValueSlot dest = ensureSlot(loc, e->getType());
1137
1138 if (e->getType()->isConstantArrayType()) {
1139 cir::ArrayType arrayTy =
1141 emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,
1142 arrayFiller);
1143 return;
1144 } else if (e->getType()->isVariableArrayType()) {
1145 cgf.cgm.errorNYI(e->getSourceRange(),
1146 "visitCXXParenListOrInitListExpr variable array type");
1147 return;
1148 }
1149
1150 if (e->getType()->isArrayType()) {
1151 cgf.cgm.errorNYI(e->getSourceRange(),
1152 "visitCXXParenListOrInitListExpr array type");
1153 return;
1154 }
1155
1156 assert(e->getType()->isRecordType() && "Only support structs/unions here!");
1157
1158 // Do struct initialization; this code just sets each individual member
1159 // to the approprate value. This makes bitfield support automatic;
1160 // the disadvantage is that the generated code is more difficult for
1161 // the optimizer, especially with bitfields.
1162 unsigned numInitElements = args.size();
1163 auto *record = e->getType()->castAsRecordDecl();
1164
1165 // We'll need to enter cleanup scopes in case any of the element
1166 // initializers throws an exception.
1167 CIRGenFunction::CleanupDeactivationScope deactivateCleanups(cgf);
1168
1169 unsigned curInitIndex = 0;
1170
1171 // Emit initialization of base classes.
1172 if (auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) {
1173 assert(numInitElements >= cxxrd->getNumBases() &&
1174 "missing initializer for base class");
1175 for (auto &base : cxxrd->bases()) {
1176 assert(!base.isVirtual() && "should not see vbases here");
1177 CXXRecordDecl *baseRD = base.getType()->getAsCXXRecordDecl();
1179 loc, dest.getAddress(), cxxrd, baseRD,
1180 /*baseIsVirtual=*/false);
1182 AggValueSlot aggSlot = AggValueSlot::forAddr(
1183 address, Qualifiers(), AggValueSlot::IsDestructed,
1185 cgf.getOverlapForBaseInit(cxxrd, baseRD, false));
1186 cgf.emitAggExpr(args[curInitIndex++], aggSlot);
1187
1188 if (QualType::DestructionKind dtorKind =
1189 base.getType().isDestructedType())
1190 cgf.pushDestroyAndDeferDeactivation(dtorKind, address, base.getType());
1191 }
1192 }
1193
1194 // Prepare a 'this' for CXXDefaultInitExprs.
1195 CIRGenFunction::FieldConstructionScope fcScope(cgf, dest.getAddress());
1196
1197 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
1198
1199 if (record->isUnion()) {
1200 // Only initialize one field of a union. The field itself is
1201 // specified by the initializer list.
1202 if (!initializedFieldInUnion) {
1203 // Empty union; we have nothing to do.
1204
1205 // Make sure that it's really an empty and not a failure of
1206 // semantic analysis.
1207 assert(llvm::all_of(record->fields(),
1208 [](const FieldDecl *f) {
1209 return f->isUnnamedBitField() ||
1210 f->isAnonymousStructOrUnion();
1211 }) &&
1212 "Only unnamed bitfields or anonymous class allowed");
1213 return;
1214 }
1215
1216 // FIXME: volatility
1217 FieldDecl *initedField = initializedFieldInUnion;
1218
1219 LValue fieldLV = cgf.emitLValueForFieldInitialization(
1220 destLV, initedField, initedField->getName());
1221
1222 if (numInitElements) {
1223 // Store the initializer into the field
1224 emitInitializationToLValue(args[0], fieldLV);
1225 } else {
1226 // Default-initialize to null.
1227 emitNullInitializationToLValue(loc, fieldLV);
1228 }
1229 return;
1230 }
1231
1232 // Here we iterate over the fields; this makes it simpler to both
1233 // default-initialize fields and skip over unnamed fields.
1234 for (const FieldDecl *field : record->fields()) {
1235 // We're done once we hit the flexible array member.
1236 if (field->getType()->isIncompleteArrayType())
1237 break;
1238
1239 // Always skip anonymous bitfields.
1240 if (field->isUnnamedBitField())
1241 continue;
1242
1243 // We're done if we reach the end of the explicit initializers, we
1244 // have a zeroed object, and the rest of the fields are
1245 // zero-initializable.
1246 if (curInitIndex == numInitElements && dest.isZeroed() &&
1248 break;
1249 LValue lv =
1250 cgf.emitLValueForFieldInitialization(destLV, field, field->getName());
1251 // We never generate write-barriers for initialized fields.
1253
1254 if (curInitIndex < numInitElements) {
1255 // Store the initializer into the field.
1256 CIRGenFunction::SourceLocRAIIObject loc{cgf, record->getSourceRange()};
1257 emitInitializationToLValue(args[curInitIndex++], lv);
1258 } else {
1259 // We're out of initializers; default-initialize to null
1260 emitNullInitializationToLValue(cgf.getLoc(e->getSourceRange()), lv);
1261 }
1262
1263 // Push a destructor if necessary.
1264 // FIXME: if we have an array of structures, all explicitly
1265 // initialized, we can end up pushing a linear number of cleanups.
1266 if (QualType::DestructionKind dtorKind =
1267 field->getType().isDestructedType()) {
1268 assert(lv.isSimple());
1270 field->getType(),
1271 cgf.getDestroyer(dtorKind), false);
1272 }
1273
1274 // From classic codegen, maybe not useful for CIR:
1275 // If the GEP didn't get used because of a dead zero init or something
1276 // else, clean it up for -O0 builds and general tidiness.
1277 }
1278}
1279
1280// TODO(cir): This could be shared with classic codegen.
1282 const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual) {
1283 // If the most-derived object is a field declared with [[no_unique_address]],
1284 // the tail padding of any virtual base could be reused for other subobjects
1285 // of that field's class.
1286 if (isVirtual)
1288
1289 // Empty bases can overlap earlier bases.
1290 if (baseRD->isEmpty())
1292
1293 // If the base class is laid out entirely within the nvsize of the derived
1294 // class, its tail padding cannot yet be initialized, so we can issue
1295 // stores at the full width of the base class.
1296 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1297 if (layout.getBaseClassOffset(baseRD) +
1298 getContext().getASTRecordLayout(baseRD).getSize() <=
1299 layout.getNonVirtualSize())
1301
1302 // The tail padding may contain values we need to preserve.
1304}
1305
1307 AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
1308}
1309
1311 AggValueSlot::Overlap_t mayOverlap,
1312 bool isVolatile) {
1313 // TODO(cir): this function needs improvements, commented code for now since
1314 // this will be touched again soon.
1315 assert(!ty->isAnyComplexType() && "Unexpected copy of complex");
1316
1317 Address destPtr = dest.getAddress();
1318 Address srcPtr = src.getAddress();
1319
1320 if (getLangOpts().CPlusPlus) {
1321 if (auto *record = ty->getAsCXXRecordDecl()) {
1322 assert((record->hasTrivialCopyConstructor() ||
1323 record->hasTrivialCopyAssignment() ||
1324 record->hasTrivialMoveConstructor() ||
1325 record->hasTrivialMoveAssignment() ||
1326 record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&
1327 "Trying to aggregate-copy a type without a trivial copy/move "
1328 "constructor or assignment operator");
1329 // Ignore empty classes in C++.
1330 if (record->isEmpty())
1331 return;
1332 }
1333 }
1334
1336
1337 // Aggregate assignment turns into llvm.memcpy. This is almost valid per
1338 // C99 6.5.16.1p3, which states "If the value being stored in an object is
1339 // read from another object that overlaps in anyway the storage of the first
1340 // object, then the overlap shall be exact and the two objects shall have
1341 // qualified or unqualified versions of a compatible type."
1342 //
1343 // memcpy is not defined if the source and destination pointers are exactly
1344 // equal, but other compilers do this optimization, and almost every memcpy
1345 // implementation handles this case safely. If there is a libc that does not
1346 // safely handle this, we can add a target hook.
1347
1348 // Get data size info for this aggregate. Don't copy the tail padding if this
1349 // might be a potentially-overlapping subobject, since the tail padding might
1350 // be occupied by a different object. Otherwise, copying it is fine.
1351 TypeInfoChars typeInfo;
1352 if (mayOverlap)
1353 typeInfo = getContext().getTypeInfoDataSizeInChars(ty);
1354 else
1355 typeInfo = getContext().getTypeInfoInChars(ty);
1356
1358
1359 // Don't do any of the memmove_collectable tests if GC isn't set.
1360 if (cgm.getLangOpts().getGC() != LangOptions::NonGC)
1361 cgm.errorNYI("emitAggregateCopy: GC");
1362
1363 // If the data size (excluding tail padding) differs from the full type size,
1364 // use skip_tail_padding to avoid clobbering tail padding that may be occupied
1365 // by other objects (e.g. fields marked with [[no_unique_address]]).
1366 CharUnits dataSize = typeInfo.Width;
1367 bool skipTailPadding =
1368 mayOverlap && dataSize != getContext().getTypeSizeInChars(ty);
1369 // NOTE(cir): original codegen would normally convert destPtr and srcPtr to
1370 // i8* since memcpy operates on bytes. We don't need that in CIR because
1371 // cir.copy will operate on any CIR pointer that points to a sized type.
1372 builder.createCopy(destPtr, srcPtr, isVolatile, skipTailPadding);
1373
1375}
1376
1377// TODO(cir): This could be shared with classic codegen.
1380 if (!fd->hasAttr<NoUniqueAddressAttr>() || !fd->getType()->isRecordType())
1382
1383 // Empty fields can overlap earlier fields.
1384 if (fd->getType()->getAsCXXRecordDecl()->isEmpty())
1386
1387 // If the field lies entirely within the enclosing class's nvsize, its tail
1388 // padding cannot overlap any already-initialized object. (The only subobjects
1389 // with greater addresses that might already be initialized are vbases.)
1390 const RecordDecl *classRD = fd->getParent();
1391 const ASTRecordLayout &layout = getContext().getASTRecordLayout(classRD);
1392 if (layout.getFieldOffset(fd->getFieldIndex()) +
1393 getContext().getTypeSize(fd->getType()) <=
1394 (uint64_t)getContext().toBits(layout.getNonVirtualSize()))
1396
1397 // The tail padding may contain values we need to preserve.
1399}
1400
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:4579
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4585
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4591
llvm::APInt getArraySize() const
Definition Expr.h:6044
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition Expr.h:6037
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition Expr.h:6042
QualType getElementType() const
Definition TypeBase.h:3832
Expr * getLHS() const
Definition Expr.h:4136
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4141
SourceLocation getExprLoc() const
Definition Expr.h:4127
Expr * getRHS() const
Definition Expr.h:4138
Opcode getOpcode() const
Definition Expr.h:4131
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:3768
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1987
Expr * getSubExpr()
Definition Expr.h:3774
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:4932
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:3681
bool hasAttr() const
Definition DeclBase.h:585
InitListExpr * getUpdater() const
Definition Expr.h:5990
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: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:145
Represents a member of a struct/union/class.
Definition Decl.h:3299
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3384
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3535
const Expr * getSubExpr() const
Definition Expr.h:1086
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6522
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:5483
bool hadArrayRangeDesignator() const
Definition Expr.h:5537
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
Definition Expr.h:5459
const Expr * getInit(unsigned Init) const
Definition Expr.h:5411
ArrayRef< Expr * > inits() const
Definition Expr.h:5409
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:302
Expr * getSelectedExpr() const
Definition ExprCXX.h:4693
const Expr * getSubExpr() const
Definition Expr.h:2247
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8530
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:2916
@ 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:4464
field_range fields() const
Definition Decl.h:4667
specific_decl_iterator< FieldDecl > field_iterator
Definition Decl.h:4664
field_iterator field_begin() const
Definition Decl.cpp:5356
CompoundStmt * getSubStmt()
Definition Expr.h:4660
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:8786
bool isArrayType() const
Definition TypeBase.h:8782
bool isPointerType() const
Definition TypeBase.h:8683
bool isReferenceType() const
Definition TypeBase.h:8707
bool isVariableArrayType() const
Definition TypeBase.h:8794
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9194
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:8818
bool isMemberPointerType() const
Definition TypeBase.h:8764
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2533
bool isNullPtrType() const
Definition TypeBase.h:9109
bool isRecordType() const
Definition TypeBase.h:8810
Expr * getSubExpr() const
Definition Expr.h:2333
QualType getType() const
Definition Decl.h:724
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...