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