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"
24#include "llvm/IR/Value.h"
25#include <cstdint>
26
27using namespace clang;
28using namespace clang::CIRGen;
29
30namespace {
31class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
32
33 CIRGenFunction &cgf;
34 AggValueSlot dest;
35
36 // Calls `fn` with a valid return value slot, potentially creating a temporary
37 // to do so. If a temporary is created, an appropriate copy into `Dest` will
38 // be emitted, as will lifetime markers.
39 //
40 // The given function should take a ReturnValueSlot, and return an RValue that
41 // points to said slot.
42 void withReturnValueSlot(const Expr *e,
43 llvm::function_ref<RValue(ReturnValueSlot)> fn);
44
45 AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
46 if (!dest.isIgnored())
47 return dest;
48 return cgf.createAggTemp(t, loc, "agg.tmp.ensured");
49 }
50
51 void ensureDest(mlir::Location loc, QualType ty) {
52 if (!dest.isIgnored())
53 return;
54 dest = cgf.createAggTemp(ty, loc, "agg.tmp.ensured");
55 }
56
57public:
58 AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
59 : cgf(cgf), dest(dest) {}
60
61 /// Given an expression with aggregate type that represents a value lvalue,
62 /// this method emits the address of the lvalue, then loads the result into
63 /// DestPtr.
64 void emitAggLoadOfLValue(const Expr *e);
65
66 void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
67 Expr *exprToVisit, ArrayRef<Expr *> args,
68 Expr *arrayFiller);
69
70 void emitFinalDestCopy(QualType type, RValue src);
71
72 /// Perform the final copy to DestPtr, if desired.
73 void emitFinalDestCopy(QualType type, const LValue &src,
76
77 void emitCopy(QualType type, const AggValueSlot &dest,
78 const AggValueSlot &src);
79
80 void emitInitializationToLValue(Expr *e, LValue lv);
81
82 void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
83
84 void emitComparisonResult(const Expr *e, mlir::Location loc,
85 const ComparisonCategoryInfo &cmpInfo,
86 mlir::Value resultValue);
87
88 void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
89
90 void VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
91 emitAggLoadOfLValue(e);
92 }
93
94 void VisitCallExpr(const CallExpr *e);
95 void VisitStmtExpr(const StmtExpr *e) {
96 CIRGenFunction::StmtExprEvaluation eval(cgf);
97 Address retAlloca =
98 cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));
99 (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca, dest);
100 }
101
102 void VisitBinAssign(const BinaryOperator *e) {
103 // For an assignment to work, the value on the right has
104 // to be compatible with the value on the left.
105 assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
106 e->getRHS()->getType()) &&
107 "Invalid assignment");
108
110 e->getRHS()->HasSideEffects(cgf.getContext())) {
111 cgf.cgm.errorNYI(e->getSourceRange(),
112 "block var reference with side effects");
113 return;
114 }
115
116 LValue lhs = cgf.emitLValue(e->getLHS());
117
118 // If we have an atomic type, evaluate into the destination and then
119 // do an atomic copy.
120 if (lhs.getType()->isAtomicType() ||
121 cgf.isLValueSuitableForInlineAtomic(lhs)) {
122 ensureDest(cgf.getLoc(e->getExprLoc()), e->getRHS()->getType());
123 Visit(e->getRHS());
124 cgf.emitAtomicStore(dest.asRValue(), lhs, /*isInit=*/false);
125 return;
126 }
127
128 // Codegen the RHS so that it stores directly into the LHS.
130 AggValueSlot lhsSlot = AggValueSlot::forLValue(
133
134 // A non-volatile aggregate destination might have volatile member.
135 if (!lhsSlot.isVolatile() && cgf.hasVolatileMember(e->getLHS()->getType()))
136 lhsSlot.setVolatile(true);
137
138 cgf.emitAggExpr(e->getRHS(), lhsSlot);
139
140 // Copy into the destination if the assignment isn't ignored.
141 emitFinalDestCopy(e->getType(), lhs);
142
143 if (!dest.isIgnored() && !dest.isExternallyDestructed() &&
145 cgf.pushDestroy(QualType::DK_nontrivial_c_struct, dest.getAddress(),
146 e->getType());
147 }
148
149 void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
150
151 void VisitInitListExpr(InitListExpr *e);
152 void VisitCXXConstructExpr(const CXXConstructExpr *e);
153
154 void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
155 FieldDecl *initializedFieldInUnion,
156 Expr *arrayFiller);
157 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
158 CIRGenFunction::CXXDefaultInitExprScope Scope(cgf, die);
159 Visit(die->getExpr());
160 }
161 void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *e) {
162 // Ensure that we have a slot, but if we already do, remember
163 // whether it was externally destructed.
164 bool wasExternallyDestructed = dest.isExternallyDestructed();
165 ensureDest(cgf.getLoc(e->getSourceRange()), e->getType());
166
167 // We're going to push a destructor if there isn't already one.
168 dest.setExternallyDestructed();
169
170 Visit(e->getSubExpr());
171
172 // Push that destructor we promised.
173 if (!wasExternallyDestructed)
174 cgf.emitCXXTemporary(e->getTemporary(), e->getType(), dest.getAddress());
175 }
176 void VisitLambdaExpr(LambdaExpr *e);
177 void VisitExprWithCleanups(ExprWithCleanups *e);
178
179 /// Attempt to look through various unimportant expressions to find a
180 /// cast of the given kind.
181 static Expr *findPeephole(Expr *op, CastKind kind, const ASTContext &ctx) {
182 op = op->IgnoreParenNoopCasts(ctx);
183 if (auto *castE = dyn_cast<CastExpr>(op)) {
184 if (castE->getCastKind() == kind)
185 return castE->getSubExpr();
186 }
187 return nullptr;
188 }
189
190 // Stubs -- These should be moved up when they are implemented.
191 void VisitCastExpr(CastExpr *e) {
192 switch (e->getCastKind()) {
193 case CK_LValueToRValueBitCast: {
194 if (dest.isIgnored()) {
195 cgf.emitAnyExpr(e->getSubExpr(), AggValueSlot::ignored(),
196 /*ignoreResult=*/true);
197 break;
198 }
199
200 LValue sourceLV = cgf.emitLValue(e->getSubExpr());
201 Address sourceAddress =
202 sourceLV.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
203 Address destAddress =
204 dest.getAddress().withElementType(cgf.getBuilder(), cgf.voidTy);
205
206 mlir::Location loc = cgf.getLoc(e->getExprLoc());
207
208 mlir::Value sizeVal = cgf.getBuilder().getConstInt(
209 loc, cgf.sizeTy,
210 cgf.getContext().getTypeSizeInChars(e->getType()).getQuantity());
211 cgf.getBuilder().createMemCpy(loc, destAddress, sourceAddress, sizeVal);
212
213 break;
214 }
215
216 case CK_NonAtomicToAtomic:
217 case CK_AtomicToNonAtomic: {
218 bool isToAtomic = (e->getCastKind() == CK_NonAtomicToAtomic);
219
220 // Determine the atomic and value types.
221 QualType atomicType = e->getSubExpr()->getType();
222 QualType valueType = e->getType();
223 if (isToAtomic)
224 std::swap(atomicType, valueType);
225
226 assert(atomicType->isAtomicType());
227 assert(cgf.getContext().hasSameUnqualifiedType(
228 valueType, atomicType->castAs<AtomicType>()->getValueType()));
229
230 // Just recurse normally if we're ignoring the result or the
231 // atomic type doesn't change representation.
232 if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(atomicType))
233 return Visit(e->getSubExpr());
234
235 // These two cases are reverses of each other; try to peephole them.
236 CastKind peepholeTarget =
237 (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
238
239 // These two cases are reverses of each other; try to peephole them.
240 if (Expr *op =
241 findPeephole(e->getSubExpr(), peepholeTarget, cgf.getContext())) {
242 assert(cgf.getContext().hasSameUnqualifiedType(op->getType(),
243 e->getType()) &&
244 "peephole significantly changed types?");
245 return Visit(op);
246 }
247
248 // If we're converting an r-value of non-atomic type to an r-value
249 // of atomic type, just emit directly into the relevant sub-object.
250 if (isToAtomic) {
251 AggValueSlot valueDest = dest;
252 if (!valueDest.isIgnored() && cgf.cgm.isPaddedAtomicType(atomicType)) {
253 // Zero-initialize. (Strictly speaking, we only need to initialize
254 // the padding at the end, but this is simpler.)
255 mlir::Location loc = cgf.getLoc(e->getExprLoc());
256 if (!dest.isZeroed())
257 cgf.emitNullInitialization(loc, dest.getAddress(), atomicType);
258
259 Address valueAddr = cgf.getBuilder().createGetMember(
260 loc, valueDest.getAddress(), "value_addr", 0);
261
263 valueDest = AggValueSlot::forAddr(
264 valueAddr, valueDest.getQualifiers(),
265 valueDest.isExternallyDestructed(),
268 }
269
270 cgf.emitAggExpr(e->getSubExpr(), valueDest);
271 return;
272 }
273
274 mlir::Location loc = cgf.getLoc(e->getExprLoc());
275 AggValueSlot atomicSlot = cgf.createAggTemp(atomicType, loc);
276 cgf.emitAggExpr(e->getSubExpr(), atomicSlot);
277
278 Address valueAddr = cgf.getBuilder().createGetMember(
279 loc, atomicSlot.getAddress(), "value_addr", 0);
280 RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile());
281 return emitFinalDestCopy(valueType, rvalue);
282 }
283 case CK_LValueToRValue:
284 // If we're loading from a volatile type, force the destination
285 // into existence.
287 cgf.cgm.errorNYI(e->getSourceRange(),
288 "AggExprEmitter: volatile lvalue-to-rvalue cast");
289 [[fallthrough]];
290 case CK_NoOp:
291 case CK_UserDefinedConversion:
292 case CK_ConstructorConversion:
293 assert(cgf.getContext().hasSameUnqualifiedType(e->getSubExpr()->getType(),
294 e->getType()) &&
295 "Implicit cast types must be compatible");
296 Visit(e->getSubExpr());
297 break;
298 case CK_ToUnion: {
299 if (dest.isIgnored()) {
300 cgf.emitAnyExpr(e->getSubExpr(), AggValueSlot::ignored(),
301 /*ignoreResult=*/true);
302 break;
303 }
304 QualType ty = e->getSubExpr()->getType();
305 Address castPtr = dest.getAddress().withElementType(cgf.getBuilder(),
306 cgf.convertType(ty));
307 emitInitializationToLValue(e->getSubExpr(),
308 cgf.makeAddrLValue(castPtr, ty));
309 break;
310 }
311 default:
312 cgf.cgm.errorNYI(e->getSourceRange(),
313 std::string("AggExprEmitter: VisitCastExpr: ") +
314 e->getCastKindName());
315 break;
316 }
317 }
318 void VisitStmt(Stmt *s) {
319 cgf.cgm.errorNYI(s->getSourceRange(),
320 std::string("AggExprEmitter::VisitStmt: ") +
321 s->getStmtClassName());
322 }
323 void VisitParenExpr(ParenExpr *pe) { Visit(pe->getSubExpr()); }
324 void VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
325 Visit(ge->getResultExpr());
326 }
327 void VisitCoawaitExpr(CoawaitExpr *e) {
328 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCoawaitExpr");
329 }
330 void VisitCoyieldExpr(CoyieldExpr *e) {
331 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCoyieldExpr");
332 }
333 void VisitUnaryCoawait(UnaryOperator *e) {
334 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitUnaryCoawait");
335 }
336 void VisitUnaryExtension(UnaryOperator *e) { Visit(e->getSubExpr()); }
337 void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
338 Visit(e->getReplacement());
339 }
340 void VisitConstantExpr(ConstantExpr *e) {
341 ensureDest(cgf.getLoc(e->getSourceRange()), e->getType());
342
343 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
344 mlir::Value resultVal = cgf.getBuilder().getConstant(
345 cgf.getLoc(e->getSourceRange()), mlir::cast<mlir::TypedAttr>(result));
346 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->getType());
347 cgf.emitStoreThroughLValue(RValue::get(resultVal), destLVal);
348 return;
349 }
350
351 // It isn't clear that it is possible to get to here, but this branch is
352 // present in classic codegen, so we leave it here too.
353 return Visit(e->getSubExpr());
354 }
355 void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }
356 void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }
357 void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }
358 void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);
359
360 void VisitPredefinedExpr(const PredefinedExpr *e) { emitAggLoadOfLValue(e); }
361 void VisitBinaryOperator(const BinaryOperator *e) {
362 if (e->getOpcode() == BO_PtrMemD || e->getOpcode() == BO_PtrMemI)
363 VisitPointerToDataMemberBinaryOperator(e);
364 else
365 cgf.cgm.errorUnsupported(e, "aggregate binary expression");
366 }
367 void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *e) {
368 LValue lv = cgf.emitPointerToDataMemberBinaryExpr(e);
369 emitFinalDestCopy(e->getType(), lv);
370 }
371 void VisitBinComma(const BinaryOperator *e) {
372 cgf.emitIgnoredExpr(e->getLHS());
373 Visit(e->getRHS());
374 }
375 void VisitBinCmp(const BinaryOperator *e) {
376 assert(cgf.getContext().hasSameType(e->getLHS()->getType(),
377 e->getRHS()->getType()));
378 const ComparisonCategoryInfo &cmpInfo =
379 cgf.getContext().CompCategories.getInfoForType(e->getType());
380 assert(cmpInfo.Record->isTriviallyCopyable() &&
381 "cannot copy non-trivially copyable aggregate");
382
383 QualType argTy = e->getLHS()->getType();
384
385 if (!argTy->isIntegralOrEnumerationType() && !argTy->isRealFloatingType() &&
386 !argTy->isNullPtrType() && !argTy->isPointerType() &&
387 !argTy->isMemberPointerType() && !argTy->isAnyComplexType())
388 cgf.cgm.errorNYI(e->getBeginLoc(), "aggregate three-way comparison");
389
390 mlir::Location loc = cgf.getLoc(e->getSourceRange());
391 CIRGenBuilderTy &builder = cgf.getBuilder();
392
393 if (e->getType()->isAnyComplexType())
394 cgf.cgm.errorNYI(e->getBeginLoc(), "VisitBinCmp: complex type");
395
396 if (e->getType()->isAggregateType())
397 cgf.cgm.errorNYI(e->getBeginLoc(), "VisitBinCmp: aggregate type");
398
399 mlir::Value lhs = cgf.emitAnyExpr(e->getLHS()).getValue();
400 mlir::Value rhs = cgf.emitAnyExpr(e->getRHS()).getValue();
401
402 mlir::Value resultScalar;
403 if (argTy->isNullPtrType()) {
404 resultScalar =
405 builder.getConstInt(loc, cmpInfo.getEqualOrEquiv()->getIntValue());
406 } else {
407 llvm::APSInt ltRes = cmpInfo.getLess()->getIntValue();
408 llvm::APSInt eqRes = cmpInfo.getEqualOrEquiv()->getIntValue();
409 llvm::APSInt gtRes = cmpInfo.getGreater()->getIntValue();
410 if (!cmpInfo.isPartial()) {
411 cir::CmpOrdering ordering = cmpInfo.isStrong()
412 ? cir::CmpOrdering::Strong
413 : cir::CmpOrdering::Weak;
414 resultScalar = builder.createThreeWayCmpTotalOrdering(
415 loc, lhs, rhs, ltRes, eqRes, gtRes, ordering);
416 } else {
417 // Partial ordering.
418 llvm::APSInt unorderedRes = cmpInfo.getUnordered()->getIntValue();
419 resultScalar = builder.createThreeWayCmpPartialOrdering(
420 loc, lhs, rhs, ltRes, eqRes, gtRes, unorderedRes);
421 }
422 }
423
424 emitComparisonResult(e, loc, cmpInfo, resultScalar);
425 }
426
427 void VisitTypeTraitExpr(const TypeTraitExpr *e) {
428 assert(e->isStoredAsComparisonResult() &&
429 "expected a strong_ordering type trait with a stored value");
430
431 const ComparisonCategoryInfo &cmpInfo =
432 cgf.getContext().CompCategories.getInfoForType(e->getType());
433 const auto result =
434 ComparisonCategoryResult(e->getAPValue().getInt().getZExtValue());
435 mlir::Location loc = cgf.getLoc(e->getSourceRange());
436 mlir::Value resultValue = cgf.getBuilder().getConstInt(
437 loc, cmpInfo.getValueInfo(result)->getIntValue());
438
439 emitComparisonResult(e, loc, cmpInfo, resultValue);
440 }
441
442 void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
443 Visit(e->getSemanticForm());
444 }
445 void VisitObjCMessageExpr(ObjCMessageExpr *e) {
446 cgf.cgm.errorNYI(e->getSourceRange(),
447 "AggExprEmitter: VisitObjCMessageExpr");
448 }
449 void VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
450 cgf.cgm.errorNYI(e->getSourceRange(),
451 "AggExprEmitter: VisitObjCIVarRefExpr");
452 }
453
454 void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e) {
455 AggValueSlot dest = ensureSlot(cgf.getLoc(e->getExprLoc()), e->getType());
456 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
457 emitInitializationToLValue(e->getBase(), destLV);
458 VisitInitListExpr(e->getUpdater());
459 }
460 void VisitAbstractConditionalOperator(const AbstractConditionalOperator *e) {
461 mlir::Location loc = cgf.getLoc(e->getSourceRange());
462
463 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
464
465 // Emit the condition before opening the conditional evaluation, so that
466 // the cleanup scope of any temporary the condition creates encloses the
467 // one the evaluation opens.
468 mlir::Value condV = cgf.emitOpOnBoolExpr(loc, e->getCond());
469 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
470
471 // Save whether the destination's lifetime is externally managed.
472 bool isExternallyDestructed = dest.isExternallyDestructed();
473 bool destructNonTrivialCStruct =
474 !isExternallyDestructed &&
476 isExternallyDestructed |= destructNonTrivialCStruct;
477
478 // emitIfOnBoolValue terminates each region; an unconditional yield here
479 // would keep alive the dead block a noreturn arm leaves behind.
480 cgf.emitIfOnBoolValue(
481 condV, loc,
482 /*thenBuilder=*/
483 [&](mlir::OpBuilder &b, mlir::Location loc) {
484 eval.beginEvaluation();
485 {
486 CIRGenFunction::LexicalScope lexScope{cgf, loc,
487 b.getInsertionBlock()};
488 cgf.curLexScope->setAsTernary();
489 dest.setExternallyDestructed(isExternallyDestructed);
491 Visit(e->getTrueExpr());
492 }
493 eval.endEvaluation();
494 },
495 loc,
496 /*elseBuilder=*/
497 [&](mlir::OpBuilder &b, mlir::Location loc) {
498 eval.beginEvaluation();
499 {
500 CIRGenFunction::LexicalScope lexScope{cgf, loc,
501 b.getInsertionBlock()};
502 cgf.curLexScope->setAsTernary();
503
504 // If the result of an agg expression is unused, then the emission
505 // of the LHS might need to create a destination slot. That's fine
506 // with us, and we can safely emit the RHS into the same slot, but
507 // we shouldn't claim that it's already being destructed.
508 dest.setExternallyDestructed(isExternallyDestructed);
510 Visit(e->getFalseExpr());
511 }
512 eval.endEvaluation();
513 },
514 loc);
515
516 if (destructNonTrivialCStruct)
517 cgf.cgm.errorNYI(
518 e->getSourceRange(),
519 "Abstract conditional aggregate: destructNonTrivialCStruct");
520 }
521 void VisitChooseExpr(const ChooseExpr *e) { Visit(e->getChosenSubExpr()); }
522 void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) {
523 visitCXXParenListOrInitListExpr(e, e->getInitExprs(),
525 e->getArrayFiller());
526 }
527
528 void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *e) {
529 CIRGenFunction::OpaqueValueMapping binding(cgf, e->getCommonExpr());
530 uint64_t numElements = e->getArraySize().getZExtValue();
531
532 if (!numElements)
533 return;
534
535 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
536
537 if (!e->getType()->isConstantArrayType())
538 cgf.cgm.errorNYI(e->getSourceRange(),
539 "VisitArrayInitLoopExpr: Non-constant array");
540
541 Address dest = ensureSlot(loc, e->getType()).getAddress();
542 cir::ArrayType arrayTy = cast<cir::ArrayType>(dest.getElementType());
543
544 emitArrayInit(dest, arrayTy, e->getType(),
545 const_cast<ArrayInitLoopExpr *>(e), {}, e->getSubExpr());
546 }
547
548 void VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {
549 QualType ty = e->getType();
550 mlir::Location loc = cgf.getLoc(e->getSourceRange());
551 AggValueSlot slot = ensureSlot(loc, ty);
552 emitNullInitializationToLValue(loc,
553 cgf.makeAddrLValue(slot.getAddress(), ty));
554 }
555 void VisitNoInitExpr(NoInitExpr *e) {
556 cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitNoInitExpr");
557 }
558 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
559 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
560 Visit(dae->getExpr());
561 }
562 void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *e) {
563 AggValueSlot slot =
564 ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
565 cgf.emitInheritedCXXConstructorCall(e->getConstructor(),
566 e->constructsVBase(), slot.getAddress(),
567 e->inheritedFromVBase(), e);
568 }
569
570 /// Emit the initializer for a std::initializer_list initialized with a
571 /// real initializer list.
572 void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *e) {
573 ASTContext &ctx = cgf.getContext();
574 CIRGenBuilderTy &builder = cgf.getBuilder();
575 mlir::Location loc = cgf.getLoc(e->getExprLoc());
576
577 LValue array = cgf.emitLValue(e->getSubExpr());
578 assert(array.isSimple() && "initializer_list array not a simple lvalue");
579 Address arrayPtr = array.getAddress();
580
581 const ConstantArrayType *arrayType =
583 assert(arrayType && "std::initializer_list constructed from non-array");
584
585 auto *record = e->getType()->castAsRecordDecl();
586 assert(record->getNumFields() == 2 &&
587 "Expected std::initializer_list to only have two fields");
588
589 RecordDecl::field_iterator field = record->field_begin();
590 assert(field != record->field_end() &&
591 ctx.hasSameType(field->getType()->getPointeeType(),
592 arrayType->getElementType()) &&
593 "Expected std::initializer_list first field to be const E *");
594
595 // Start pointer.
596 AggValueSlot dest = ensureSlot(loc, e->getType());
597 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());
598 LValue start =
599 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
600
601 mlir::Value arrayStart = arrayPtr.emitRawPointer();
602 cgf.emitStoreThroughLValue(RValue::get(arrayStart), start);
603 ++field;
604 assert(field != record->field_end() &&
605 "Expected std::initializer_list to have two fields");
606
607 cir::ConstantOp size = builder.getConstInt(loc, arrayType->getSize());
608 LValue endOrLength =
609 cgf.emitLValueForFieldInitialization(destLV, *field, field->getName());
610 if (ctx.hasSameType(field->getType(), ctx.getSizeType())) {
611 // Length.
612 cgf.emitStoreThroughLValue(RValue::get(size), endOrLength);
613 } else {
614 // End pointer.
615 assert(field->getType()->isPointerType() &&
616 ctx.hasSameType(field->getType()->getPointeeType(),
617 arrayType->getElementType()) &&
618 "Expected std::initializer_list second field to be const E *");
619 mlir::Value arrayEnd = builder.createPtrStride(loc, arrayStart, size);
620 cgf.emitStoreThroughLValue(RValue::get(arrayEnd), endOrLength);
621 }
622 }
623
624 void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {
625 cgf.cgm.errorNYI(e->getSourceRange(),
626 "AggExprEmitter: VisitCXXScalarValueInitExpr");
627 }
628 void VisitCXXTypeidExpr(CXXTypeidExpr *e) { emitAggLoadOfLValue(e); }
629 void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {
630 Visit(e->getSubExpr());
631 }
632 void VisitOpaqueValueExpr(OpaqueValueExpr *e) {
633 cgf.cgm.errorNYI(e->getSourceRange(),
634 "AggExprEmitter: VisitOpaqueValueExpr");
635 }
636
637 void VisitPseudoObjectExpr(PseudoObjectExpr *e) {
638 cgf.cgm.errorNYI(e->getSourceRange(),
639 "AggExprEmitter: VisitPseudoObjectExpr");
640 }
641
642 void VisitVAArgExpr(VAArgExpr *e) {
643 // emitVAArg returns an aggregate value (not a pointer) at the CIR level.
644 // ABI-specific pointer handling will be done later in LoweringPrepare.
645 mlir::Value vaArgValue = cgf.emitVAArg(e);
646
647 // Create a temporary alloca to hold the aggregate value.
648 mlir::Location loc = cgf.getLoc(e->getSourceRange());
649 Address tmpAddr = cgf.createMemTemp(e->getType(), loc, "vaarg.tmp");
650
651 // Store the va_arg result into the temporary.
652 cgf.emitAggregateStore(vaArgValue, tmpAddr);
653
654 // Create an LValue from the temporary address.
655 LValue tmpLValue = cgf.makeAddrLValue(tmpAddr, e->getType());
656
657 // Copy the aggregate value from temporary to destination.
658 emitFinalDestCopy(e->getType(), tmpLValue);
659 }
660
661 void VisitCXXThrowExpr(const CXXThrowExpr *e) { cgf.emitCXXThrowExpr(e); }
662 void VisitAtomicExpr(AtomicExpr *e) {
663 RValue result = cgf.emitAtomicExpr(e);
664 emitFinalDestCopy(e->getType(), result);
665 }
666};
667
668} // namespace
669
670/// Given an expression with aggregate type that represents a value lvalue, this
671/// method emits the address of the lvalue, then loads the result into DestPtr.
672void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
673 LValue lv = cgf.emitLValue(e);
674
675 // If the type of the l-value is atomic, then do an atomic load.
676 if (lv.getType()->isAtomicType() || cgf.isLValueSuitableForInlineAtomic(lv)) {
677 cgf.emitAtomicLoad(lv, e->getExprLoc(), dest);
678 return;
679 }
680
681 emitFinalDestCopy(e->getType(), lv);
682}
683
684void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
685 if (dest.isPotentiallyAliased() && e->getType().isPODType(cgf.getContext())) {
686 // For a POD type, just emit a load of the lvalue + a copy, because our
687 // compound literal might alias the destination.
688 emitAggLoadOfLValue(e);
689 return;
690 }
691
692 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
693
694 // Block-scope compound literals are destroyed at the end of the enclosing
695 // scope in C.
696 bool destruct =
697 !cgf.getLangOpts().CPlusPlus && !slot.isExternallyDestructed();
698 if (destruct)
700
701 cgf.emitAggExpr(e->getInitializer(), slot);
702
703 if (destruct)
704 if ([[maybe_unused]] QualType::DestructionKind dtorKind =
706 cgf.cgm.errorNYI(e->getSourceRange(), "compound literal with destructor");
707}
708
709void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
710 QualType arrayQTy, Expr *e,
711 ArrayRef<Expr *> args, Expr *arrayFiller) {
712 CIRGenBuilderTy &builder = cgf.getBuilder();
713 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
714
715 const uint64_t numInitElements = args.size();
716
717 bool setArrayInitLoopExprScope = isa<ArrayInitLoopExpr>(e);
718
719 const QualType elementType =
720 cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
721
722 const QualType elementPtrType = cgf.getContext().getPointerType(elementType);
723
724 const mlir::Type cirElementType = cgf.convertType(elementType);
725 const cir::PointerType cirElementPtrType =
726 builder.getPointerTo(cirElementType);
727
728 auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,
729 cir::CastKind::array_to_ptrdecay,
730 destPtr.getPointer());
731
732 const CharUnits elementSize =
733 cgf.getContext().getTypeSizeInChars(elementType);
734 const CharUnits elementAlign =
735 destPtr.getAlignment().alignmentOfArrayElement(elementSize);
736
737 // Exception safety requires us to destroy all the already-constructed
738 // members if an initializer throws. For that, we'll need an EH cleanup.
739 QualType::DestructionKind dtorKind = elementType.isDestructedType();
740 Address endOfInit = Address::invalid();
742
743 if (dtorKind && cgf.getLangOpts().Exceptions) {
744 endOfInit = cgf.createTempAlloca(cirElementPtrType, cgf.getPointerAlign(),
745 loc, "arrayinit.endOfInit");
746 builder.createStore(loc, begin, endOfInit);
747
748 cgf.pushIrregularPartialArrayCleanup(begin, endOfInit, elementType,
749 elementAlign,
750 cgf.getDestroyer(dtorKind));
751 }
752
753 // The 'current element to initialize'. The invariants on this
754 // variable are complicated. Essentially, after each iteration of
755 // the loop, it points to the last initialized element, except
756 // that it points to the beginning of the array before any
757 // elements have been initialized.
758 mlir::Value element = begin;
759
760 // Don't build the 'one' before the cycle to avoid
761 // emmiting the redundant `cir.const 1` instrs.
762 mlir::Value one;
763
764 // Emit the explicit initializers.
765 for (uint64_t i = 0; i != numInitElements; ++i) {
766 // Advance to the next element.
767 if (i > 0) {
768 one = builder.getConstantInt(loc, cgf.ptrDiffTy, i);
769 element = builder.createPtrStride(loc, begin, one);
770
771 // Tell the cleanup that it needs to destroy up to this element.
772 if (endOfInit.isValid())
773 builder.createStore(loc, element, endOfInit);
774 }
775
776 const Address address = Address(element, cirElementType, elementAlign);
777 const LValue elementLV = cgf.makeAddrLValue(address, elementType);
778 emitInitializationToLValue(args[i], elementLV);
779 }
780
781 const uint64_t numArrayElements = arrayTy.getSize();
782
783 // Check whether there's a non-trivial array-fill expression.
784 const bool hasTrivialFiller = CodeGenUtils::isTrivialFiller(arrayFiller);
785
786 // Any remaining elements need to be zero-initialized, possibly
787 // using the filler expression. We can skip this if the we're
788 // emitting to zeroed memory.
789 if (numInitElements != numArrayElements &&
790 !(dest.isZeroed() && hasTrivialFiller &&
791 cgf.getTypes().isZeroInitializable(elementType))) {
792 // Advance to the start of the rest of the array.
793 if (numInitElements) {
794 one = builder.getConstantInt(loc, cgf.ptrDiffTy, 1);
795 element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
796 element, one);
797
798 if (endOfInit.isValid())
799 builder.createStore(loc, element, endOfInit);
800 }
801
802 // Allocate the temporary variable
803 // to store the pointer to first unitialized element
804 const Address tmpAddr = cgf.createTempAlloca(
805 cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");
806 LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType);
807 cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
808
809 // Compute the end of array
810 cir::ConstantOp numArrayElementsConst = builder.getConstInt(
811 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), numArrayElements);
812 mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,
813 begin, numArrayElementsConst);
814
815 builder.createDoWhile(
816 loc,
817 /*condBuilder=*/
818 [&](mlir::OpBuilder &b, mlir::Location loc) {
819 cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
820 cir::CmpOp cmp = cir::CmpOp::create(builder, loc, cir::CmpOpKind::ne,
821 currentElement, end);
822 builder.createCondition(cmp);
823 },
824 /*bodyBuilder=*/
825 [&](mlir::OpBuilder &b, mlir::Location loc) {
826 cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
827
828 // Emit the actual filler expression.
829 LValue elementLV = cgf.makeAddrLValue(
830 Address(currentElement, cirElementType, elementAlign),
831 elementType);
832
833 mlir::Value idx;
834 if (setArrayInitLoopExprScope)
835 idx = cir::PtrDiffOp::create(b, loc, cgf.ptrDiffTy, currentElement,
836 begin);
837
838 CIRGenFunction::ArrayInitLoopExprScope loopExprScope(
839 cgf, setArrayInitLoopExprScope, idx);
840
841 if (arrayFiller)
842 emitInitializationToLValue(arrayFiller, elementLV);
843 else
844 emitNullInitializationToLValue(loc, elementLV);
845
846 // Advance pointer and store them to temporary variable
847 cir::ConstantOp one = builder.getConstInt(
848 loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), 1);
849 auto nextElement = cir::PtrStrideOp::create(
850 builder, loc, cirElementPtrType, currentElement, one);
851
852 // Tell the EH cleanup that we finished with the last element.
853 if (endOfInit.isValid())
854 builder.createStore(loc, nextElement, endOfInit);
855
856 cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
857
858 builder.createYield(loc);
859 });
860 }
861}
862
863/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
864void AggExprEmitter::emitFinalDestCopy(QualType type, RValue src) {
865 assert(src.isAggregate() && "value must be aggregate value!");
866 LValue srcLV = cgf.makeAddrLValue(src.getAggregateAddress(), type);
867 emitFinalDestCopy(type, srcLV, CIRGenFunction::EVK_RValue);
868}
869
870/// Perform the final copy to destPtr, if desired.
871void AggExprEmitter::emitFinalDestCopy(
872 QualType type, const LValue &src,
873 CIRGenFunction::ExprValueKind srcValueKind) {
874 // If dest is ignored, then we're evaluating an aggregate expression
875 // in a context that doesn't care about the result. Note that loads
876 // from volatile l-values force the existence of a non-ignored
877 // destination.
878 if (dest.isIgnored())
879 return;
880
881 if (srcValueKind == CIRGenFunction::EVK_RValue) {
882 if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) {
883 cgf.cgm.errorNYI("emitFinalDestCopy: EVK_RValue & PCK_Struct");
884 }
885 } else {
886 if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
887 cgf.cgm.errorNYI("emitFinalDestCopy: !EVK_RValue & PCK_Struct");
888 }
889 }
890
894
895 AggValueSlot srcAgg = AggValueSlot::forLValue(src, AggValueSlot::IsDestructed,
898 emitCopy(type, dest, srcAgg);
899}
900
901/// Perform a copy from the source into the destination.
902///
903/// \param type - the type of the aggregate being copied; qualifiers are
904/// ignored
905void AggExprEmitter::emitCopy(QualType type, const AggValueSlot &dest,
906 const AggValueSlot &src) {
908
909 // If the result of the assignment is used, copy the LHS there also.
910 // It's volatile if either side is. Use the minimum alignment of
911 // the two sides.
912 LValue destLV = cgf.makeAddrLValue(dest.getAddress(), type);
913 LValue srcLV = cgf.makeAddrLValue(src.getAddress(), type);
915 cgf.emitAggregateCopy(destLV, srcLV, type, dest.mayOverlap(),
916 dest.isVolatile() || src.isVolatile());
917}
918
919void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
920 const QualType type = lv.getType();
921
923 const mlir::Location loc = cgf.getLoc(e->getSourceRange());
924 return emitNullInitializationToLValue(loc, lv);
925 }
926
927 if (isa<NoInitExpr>(e))
928 return;
929
930 if (type->isReferenceType()) {
931 RValue rv = cgf.emitReferenceBindingToExpr(e);
932 return cgf.emitStoreThroughLValue(rv, lv);
933 }
934
935 switch (cgf.getEvaluationKind(type)) {
936 case cir::TEK_Complex:
937 cgf.emitComplexExprIntoLValue(e, lv, /*isInit*/ true);
938 break;
943 dest.isZeroed()));
944
945 return;
946 case cir::TEK_Scalar:
947 if (lv.isSimple())
948 cgf.emitScalarInit(e, lv);
949 else
951 return;
952 }
953}
954
955void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *e) {
956 AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
957 cgf.emitCXXConstructExpr(e, slot);
958}
959
960void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
961 LValue lv) {
962 const QualType type = lv.getType();
963
964 // If the destination slot is already zeroed out before the aggregate is
965 // copied into it, we don't have to emit any zeros here.
966 if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
967 return;
968
969 if (cgf.hasScalarEvaluationKind(type)) {
970 // For non-aggregates, we can store the appropriate null constant.
971 mlir::Value null = cgf.cgm.emitNullConstant(type, loc);
972 if (lv.isSimple()) {
973 cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
974 return;
975 }
976
978 return;
979 }
980
981 // There's a potential optimization opportunity in combining
982 // memsets; that would be easy for arrays, but relatively
983 // difficult for structures with the current code.
984 cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
985}
986
987void AggExprEmitter::emitComparisonResult(const Expr *e, mlir::Location loc,
988 const ComparisonCategoryInfo &cmpInfo,
989 mlir::Value resultValue) {
990 // Create the return value in the destination slot.
991 ensureDest(loc, e->getType());
992 LValue destLVal = cgf.makeAddrLValue(dest.getAddress(), e->getType());
993
994 // Emit the address of the first (and only) field in the comparison category
995 // type, and initialize it from the constant integer value produced above.
996 const FieldDecl *resultField = *cmpInfo.Record->field_begin();
997 LValue fieldLVal = cgf.emitLValueForFieldInitialization(
998 destLVal, resultField, resultField->getName());
999 cgf.emitStoreThroughLValue(RValue::get(resultValue), fieldLVal);
1000}
1001
1002void AggExprEmitter::VisitLambdaExpr(LambdaExpr *e) {
1003 CIRGenFunction::SourceLocRAIIObject loc{cgf, 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{cgf, record->getSourceRange()};
1226 emitInitializationToLValue(args[curInitIndex++], lv);
1227 } else {
1228 // We're out of initializers; default-initialize to null
1229 emitNullInitializationToLValue(cgf.getLoc(e->getSourceRange()), lv);
1230 }
1231
1232 // Push a destructor if necessary.
1233 // FIXME: if we have an array of structures, all explicitly
1234 // initialized, we can end up pushing a linear number of cleanups.
1235 if (QualType::DestructionKind dtorKind =
1236 field->getType().isDestructedType()) {
1237 assert(lv.isSimple());
1239 field->getType(),
1240 cgf.getDestroyer(dtorKind), false);
1241 }
1242
1243 // From classic codegen, maybe not useful for CIR:
1244 // If the GEP didn't get used because of a dead zero init or something
1245 // else, clean it up for -O0 builds and general tidiness.
1246 }
1247}
1248
1249// TODO(cir): This could be shared with classic codegen.
1251 const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual) {
1252 // If the most-derived object is a field declared with [[no_unique_address]],
1253 // the tail padding of any virtual base could be reused for other subobjects
1254 // of that field's class.
1255 if (isVirtual)
1257
1258 // If the base class is laid out entirely within the nvsize of the derived
1259 // class, its tail padding cannot yet be initialized, so we can issue
1260 // stores at the full width of the base class.
1261 const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
1262 if (layout.getBaseClassOffset(baseRD) +
1263 getContext().getASTRecordLayout(baseRD).getSize() <=
1264 layout.getNonVirtualSize())
1266
1267 // The tail padding may contain values we need to preserve.
1269}
1270
1272 AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
1273}
1274
1276 AggValueSlot::Overlap_t mayOverlap,
1277 bool isVolatile) {
1278 // TODO(cir): this function needs improvements, commented code for now since
1279 // this will be touched again soon.
1280 assert(!ty->isAnyComplexType() && "Unexpected copy of complex");
1281
1282 Address destPtr = dest.getAddress();
1283 Address srcPtr = src.getAddress();
1284
1285 if (getLangOpts().CPlusPlus) {
1286 if (auto *record = ty->getAsCXXRecordDecl()) {
1287 assert((record->hasTrivialCopyConstructor() ||
1288 record->hasTrivialCopyAssignment() ||
1289 record->hasTrivialMoveConstructor() ||
1290 record->hasTrivialMoveAssignment() ||
1291 record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&
1292 "Trying to aggregate-copy a type without a trivial copy/move "
1293 "constructor or assignment operator");
1294 // Ignore empty classes in C++.
1295 if (record->isEmpty())
1296 return;
1297 }
1298 }
1299
1301
1302 // Aggregate assignment turns into llvm.memcpy. This is almost valid per
1303 // C99 6.5.16.1p3, which states "If the value being stored in an object is
1304 // read from another object that overlaps in anyway the storage of the first
1305 // object, then the overlap shall be exact and the two objects shall have
1306 // qualified or unqualified versions of a compatible type."
1307 //
1308 // memcpy is not defined if the source and destination pointers are exactly
1309 // equal, but other compilers do this optimization, and almost every memcpy
1310 // implementation handles this case safely. If there is a libc that does not
1311 // safely handle this, we can add a target hook.
1312
1313 // Get data size info for this aggregate. Don't copy the tail padding if this
1314 // might be a potentially-overlapping subobject, since the tail padding might
1315 // be occupied by a different object. Otherwise, copying it is fine.
1316 TypeInfoChars typeInfo;
1317 if (mayOverlap)
1318 typeInfo = getContext().getTypeInfoDataSizeInChars(ty);
1319 else
1320 typeInfo = getContext().getTypeInfoInChars(ty);
1321
1323
1324 // Don't do any of the memmove_collectable tests if GC isn't set.
1325 if (cgm.getLangOpts().getGC() != LangOptions::NonGC)
1326 cgm.errorNYI("emitAggregateCopy: GC");
1327
1328 // If the data size (excluding tail padding) differs from the full type size,
1329 // use skip_tail_padding to avoid clobbering tail padding that may be occupied
1330 // by other objects (e.g. fields marked with [[no_unique_address]]).
1331 CharUnits dataSize = typeInfo.Width;
1332 bool skipTailPadding =
1333 mayOverlap && dataSize != getContext().getTypeSizeInChars(ty);
1334 // NOTE(cir): original codegen would normally convert destPtr and srcPtr to
1335 // i8* since memcpy operates on bytes. We don't need that in CIR because
1336 // cir.copy will operate on any CIR pointer that points to a sized type.
1337 builder.createCopy(destPtr, srcPtr, isVolatile, skipTailPadding);
1338
1340}
1341
1342// TODO(cir): This could be shared with classic codegen.
1345 if (!fd->hasAttr<NoUniqueAddressAttr>() || !fd->getType()->isRecordType())
1347
1348 // If the field lies entirely within the enclosing class's nvsize, its tail
1349 // padding cannot overlap any already-initialized object. (The only subobjects
1350 // with greater addresses that might already be initialized are vbases.)
1351 const RecordDecl *classRD = fd->getParent();
1352 const ASTRecordLayout &layout = getContext().getASTRecordLayout(classRD);
1353 if (layout.getFieldOffset(fd->getFieldIndex()) +
1354 getContext().getTypeSize(fd->getType()) <=
1355 (uint64_t)getContext().toBits(layout.getNonVirtualSize()))
1357
1358 // The tail padding may contain values we need to preserve.
1360}
1361
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.
*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:512
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:4575
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Definition Expr.h:4581
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Definition Expr.h:4587
llvm::APInt getArraySize() const
Definition Expr.h:6040
OpaqueValueExpr * getCommonExpr() const
Get the common subexpression shared by all initializations (the source array).
Definition Expr.h:6033
Expr * getSubExpr() const
Get the initializer to use for each array element.
Definition Expr.h:6038
QualType getElementType() const
Definition TypeBase.h:3825
Expr * getLHS() const
Definition Expr.h:4132
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4137
SourceLocation getExprLoc() const
Definition Expr.h:4123
Expr * getRHS() const
Definition Expr.h:4134
Opcode getOpcode() const
Definition Expr.h:4127
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:1515
const Expr * getSubExpr() const
Definition ExprCXX.h:1519
Expr * getExpr()
Get the initialization expression that will be used.
Definition ExprCXX.cpp:1138
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
MutableArrayRef< Expr * > getInitExprs()
Definition ExprCXX.h:5234
FieldDecl * getInitializedFieldInUnion()
Definition ExprCXX.h:5272
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isTriviallyCopyable() const
Determine whether this class is considered trivially copyable per (C++11 [class]p6).
Definition DeclCXX.cpp:613
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
Definition ExprCXX.h:308
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition Expr.cpp:1631
CastKind getCastKind() const
Definition Expr.h:3764
static const char * getCastKindName(CastKind CK)
Definition Expr.cpp:1981
Expr * getSubExpr()
Definition Expr.h:3770
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
Definition CharUnits.h:214
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Definition Expr.h:4928
bool isPartial() const
True iff the comparison is not totally ordered.
const ValueInfo * getLess() const
const ValueInfo * getUnordered() const
const CXXRecordDecl * Record
The declaration for the comparison category type from the standard library.
const ValueInfo * getValueInfo(ComparisonCategoryResult ValueKind) const
bool isStrong() const
True iff the comparison is "strong".
const ValueInfo * getGreater() const
const ValueInfo * getEqualOrEquiv() const
const Expr * getInitializer() const
Definition Expr.h:3677
bool hasAttr() const
Definition DeclBase.h:585
InitListExpr * getUpdater() const
Definition Expr.h:5986
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
Definition Expr.cpp:3150
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3722
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3295
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3380
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3531
const Expr * getSubExpr() const
Definition Expr.h:1082
Expr * getResultExpr()
Return the result expression of this controlling expression.
Definition Expr.h:6518
bool isTransparent() const
Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...
Definition Expr.cpp:2495
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
Definition Expr.h:5479
bool hadArrayRangeDesignator() const
Definition Expr.h:5533
Expr * getArrayFiller()
If this initializer list initializes an array with more elements than there are initializers in the l...
Definition Expr.h:5455
const Expr * getInit(unsigned Init) const
Definition Expr.h:5407
ArrayRef< Expr * > inits() const
Definition Expr.h:5405
llvm::iterator_range< capture_init_iterator > capture_inits()
Retrieve the initialization expressions for this lambda's captures.
Definition ExprCXX.h:2087
capture_range captures() const
Retrieve this lambda's captures.
Definition ExprCXX.cpp:1404
CXXRecordDecl * getLambdaClass() const
Retrieve the class that corresponds to the lambda.
Definition ExprCXX.cpp:1433
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4990
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
const Expr * getSubExpr() const
Definition Expr.h:2243
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8512
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:2912
@ PCK_Struct
The type is a struct containing a field whose type is neither PCK_Trivial nor PCK_VolatileTrivial.
Definition TypeBase.h:1533
Represents a struct/union/class.
Definition Decl.h:4460
field_range fields() const
Definition Decl.h:4663
specific_decl_iterator< FieldDecl > field_iterator
Definition Decl.h:4660
field_iterator field_begin() const
Definition Decl.cpp:5340
CompoundStmt * getSubStmt()
Definition Expr.h:4656
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
const char * getStmtClassName() const
Definition Stmt.cpp:86
bool isStoredAsComparisonResult() const
Definition ExprCXX.h:2957
const APValue & getAPValue() const
Definition ExprCXX.h:2966
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantArrayType() const
Definition TypeBase.h:8768
bool isArrayType() const
Definition TypeBase.h:8764
bool isPointerType() const
Definition TypeBase.h:8665
bool isReferenceType() const
Definition TypeBase.h:8689
bool isVariableArrayType() const
Definition TypeBase.h:8776
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9159
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2627
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8800
bool isMemberPointerType() const
Definition TypeBase.h:8746
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2529
bool isNullPtrType() const
Definition TypeBase.h:9074
bool isRecordType() const
Definition TypeBase.h:8792
Expr * getSubExpr() const
Definition Expr.h:2329
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 cleanupDeactivationScope()
static bool aggValueSlotVolatile()
static bool cudaSupport()
static bool incrementProfileCounter()
clang::CharUnits getPointerAlign() const
llvm::APSInt getIntValue() const
Get the constant integer value used by this variable to represent the comparison category result type...