1//===----------------------------------------------------------------------===//
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 Constant Expr nodes as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Address.h"
14#include "CIRGenConstantEmitter.h"
15#include "CIRGenFunction.h"
16#include "CIRGenModule.h"
17#include "CIRGenRecordLayout.h"
18#include "mlir/IR/Attributes.h"
19#include "mlir/IR/BuiltinAttributeInterfaces.h"
20#include "mlir/IR/BuiltinAttributes.h"
21#include "clang/AST/APValue.h"
22#include "clang/AST/ASTContext.h"
23#include "clang/AST/Attr.h"
24#include "clang/AST/OperationKinds.h"
25#include "clang/AST/RecordLayout.h"
26#include "clang/AST/StmtVisitor.h"
27#include "clang/Basic/Builtins.h"
28#include "clang/Basic/Specifiers.h"
29#include "clang/CIR/Dialect/IR/CIRAttrs.h"
30#include "clang/CIR/Dialect/IR/CIRTypes.h"
31#include "llvm/ADT/STLExtras.h"
32#include "llvm/ADT/Sequence.h"
33#include "llvm/Support/ErrorHandling.h"
34
35using namespace clang;
36using namespace clang::CIRGen;
37
38//===----------------------------------------------------------------------===//
39// ConstExprEmitter
40//===----------------------------------------------------------------------===//
41
42// This class only needs to handle arrays, structs and unions.
43//
44// In LLVM codegen, when outside C++11 mode, those types are not constant
45// folded, while all other types are handled by constant folding.
46//
47// In CIR codegen, instead of folding things here, we should defer that work
48// to MLIR: do not attempt to do much here.
49class ConstExprEmitter
50 : public StmtVisitor<ConstExprEmitter, mlir::Attribute, QualType> {
51 CIRGenModule &cgm;
52 LLVM_ATTRIBUTE_UNUSED ConstantEmitter &emitter;
53
54public:
55 ConstExprEmitter(ConstantEmitter &emitter)
56 : cgm(emitter.cgm), emitter(emitter) {}
57
58 //===--------------------------------------------------------------------===//
59 // Visitor Methods
60 //===--------------------------------------------------------------------===//
61
62 mlir::Attribute VisitStmt(Stmt *S, QualType T) { return {}; }
63
64 mlir::Attribute VisitConstantExpr(ConstantExpr *ce, QualType t) {
65 if (mlir::Attribute result = emitter.tryEmitConstantExpr(ce))
66 return result;
67 return Visit(ce->getSubExpr(), t);
68 }
69
70 mlir::Attribute VisitParenExpr(ParenExpr *pe, QualType t) {
71 return Visit(pe->getSubExpr(), t);
72 }
73
74 mlir::Attribute
75 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe,
76 QualType t) {
77 return Visit(pe->getReplacement(), t);
78 }
79
80 mlir::Attribute VisitGenericSelectionExpr(GenericSelectionExpr *ge,
81 QualType t) {
82 return Visit(ge->getResultExpr(), t);
83 }
84
85 mlir::Attribute VisitChooseExpr(ChooseExpr *ce, QualType t) {
86 return Visit(ce->getChosenSubExpr(), t);
87 }
88
89 mlir::Attribute VisitCompoundLiteralExpr(CompoundLiteralExpr *e, QualType t) {
90 return Visit(e->getInitializer(), t);
91 }
92
93 mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {
94 if (isa<ExplicitCastExpr>(Val: e))
95 cgm.errorNYI(e->getBeginLoc(),
96 "ConstExprEmitter::VisitCastExpr explicit cast");
97
98 Expr *subExpr = e->getSubExpr();
99
100 switch (e->getCastKind()) {
101 case CK_ToUnion:
102 case CK_AddressSpaceConversion:
103 case CK_ReinterpretMemberPointer:
104 case CK_DerivedToBaseMemberPointer:
105 case CK_BaseToDerivedMemberPointer:
106 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");
107 return {};
108
109 case CK_LValueToRValue:
110 case CK_AtomicToNonAtomic:
111 case CK_NonAtomicToAtomic:
112 case CK_NoOp:
113 case CK_ConstructorConversion:
114 return Visit(subExpr, destType);
115
116 case CK_IntToOCLSampler:
117 llvm_unreachable("global sampler variables are not generated");
118
119 case CK_Dependent:
120 llvm_unreachable("saw dependent cast!");
121
122 case CK_BuiltinFnToFnPtr:
123 llvm_unreachable("builtin functions are handled elsewhere");
124
125 // These will never be supported.
126 case CK_ObjCObjectLValueCast:
127 case CK_ARCProduceObject:
128 case CK_ARCConsumeObject:
129 case CK_ARCReclaimReturnedObject:
130 case CK_ARCExtendBlockObject:
131 case CK_CopyAndAutoreleaseBlockObject:
132 return {};
133
134 // These don't need to be handled here because Evaluate knows how to
135 // evaluate them in the cases where they can be folded.
136 case CK_BitCast:
137 case CK_ToVoid:
138 case CK_Dynamic:
139 case CK_LValueBitCast:
140 case CK_LValueToRValueBitCast:
141 case CK_NullToMemberPointer:
142 case CK_UserDefinedConversion:
143 case CK_CPointerToObjCPointerCast:
144 case CK_BlockPointerToObjCPointerCast:
145 case CK_AnyPointerToBlockPointerCast:
146 case CK_ArrayToPointerDecay:
147 case CK_FunctionToPointerDecay:
148 case CK_BaseToDerived:
149 case CK_DerivedToBase:
150 case CK_UncheckedDerivedToBase:
151 case CK_MemberPointerToBoolean:
152 case CK_VectorSplat:
153 case CK_FloatingRealToComplex:
154 case CK_FloatingComplexToReal:
155 case CK_FloatingComplexToBoolean:
156 case CK_FloatingComplexCast:
157 case CK_FloatingComplexToIntegralComplex:
158 case CK_IntegralRealToComplex:
159 case CK_IntegralComplexToReal:
160 case CK_IntegralComplexToBoolean:
161 case CK_IntegralComplexCast:
162 case CK_IntegralComplexToFloatingComplex:
163 case CK_PointerToIntegral:
164 case CK_PointerToBoolean:
165 case CK_NullToPointer:
166 case CK_IntegralCast:
167 case CK_BooleanToSignedIntegral:
168 case CK_IntegralToPointer:
169 case CK_IntegralToBoolean:
170 case CK_IntegralToFloating:
171 case CK_FloatingToIntegral:
172 case CK_FloatingToBoolean:
173 case CK_FloatingCast:
174 case CK_FloatingToFixedPoint:
175 case CK_FixedPointToFloating:
176 case CK_FixedPointCast:
177 case CK_FixedPointToBoolean:
178 case CK_FixedPointToIntegral:
179 case CK_IntegralToFixedPoint:
180 case CK_ZeroToOCLOpaqueType:
181 case CK_MatrixCast:
182 case CK_HLSLArrayRValue:
183 case CK_HLSLVectorTruncation:
184 case CK_HLSLElementwiseCast:
185 case CK_HLSLAggregateSplatCast:
186 return {};
187 }
188 llvm_unreachable("Invalid CastKind");
189 }
190
191 mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
192 cgm.errorNYI(die->getBeginLoc(),
193 "ConstExprEmitter::VisitCXXDefaultInitExpr");
194 return {};
195 }
196
197 mlir::Attribute VisitExprWithCleanups(ExprWithCleanups *e, QualType t) {
198 // Since this about constant emission no need to wrap this under a scope.
199 return Visit(e->getSubExpr(), t);
200 }
201
202 mlir::Attribute VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e,
203 QualType t) {
204 return Visit(e->getSubExpr(), t);
205 }
206
207 mlir::Attribute VisitImplicitValueInitExpr(ImplicitValueInitExpr *E,
208 QualType T) {
209 cgm.errorNYI(E->getBeginLoc(),
210 "ConstExprEmitter::VisitImplicitValueInitExpr");
211 return {};
212 }
213
214 mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
215 if (ile->isTransparent())
216 return Visit(ile->getInit(Init: 0), t);
217
218 if (ile->getType()->isArrayType()) {
219 // If we return null here, the non-constant initializer will take care of
220 // it, but we would prefer to handle it here.
221 assert(!cir::MissingFeatures::constEmitterArrayILE());
222 return {};
223 }
224
225 if (ile->getType()->isRecordType()) {
226 cgm.errorNYI(ile->getBeginLoc(), "ConstExprEmitter: record ILE");
227 return {};
228 }
229
230 if (ile->getType()->isVectorType()) {
231 // If we return null here, the non-constant initializer will take care of
232 // it, but we would prefer to handle it here.
233 assert(!cir::MissingFeatures::constEmitterVectorILE());
234 return {};
235 }
236
237 return {};
238 }
239
240 mlir::Attribute VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e,
241 QualType destType) {
242 mlir::Attribute c = Visit(e->getBase(), destType);
243 if (!c)
244 return {};
245
246 cgm.errorNYI(e->getBeginLoc(),
247 "ConstExprEmitter::VisitDesignatedInitUpdateExpr");
248 return {};
249 }
250
251 mlir::Attribute VisitCXXConstructExpr(CXXConstructExpr *e, QualType ty) {
252 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCXXConstructExpr");
253 return {};
254 }
255
256 mlir::Attribute VisitStringLiteral(StringLiteral *e, QualType t) {
257 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitStringLiteral");
258 return {};
259 }
260
261 mlir::Attribute VisitObjCEncodeExpr(ObjCEncodeExpr *e, QualType t) {
262 cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitObjCEncodeExpr");
263 return {};
264 }
265
266 mlir::Attribute VisitUnaryExtension(const UnaryOperator *e, QualType t) {
267 return Visit(e->getSubExpr(), t);
268 }
269
270 // Utility methods
271 mlir::Type convertType(QualType t) { return cgm.convertType(t); }
272};
273
274// TODO(cir): this can be shared with LLVM's codegen
275static QualType getNonMemoryType(CIRGenModule &cgm, QualType type) {
276 if (const auto *at = type->getAs<AtomicType>()) {
277 return cgm.getASTContext().getQualifiedType(T: at->getValueType(),
278 Qs: type.getQualifiers());
279 }
280 return type;
281}
282
283static mlir::Attribute
284emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
285 mlir::Type commonElementType, unsigned arrayBound,
286 SmallVectorImpl<mlir::TypedAttr> &elements,
287 mlir::TypedAttr filler) {
288 const CIRGenBuilderTy &builder = cgm.getBuilder();
289
290 unsigned nonzeroLength = arrayBound;
291 if (elements.size() < nonzeroLength && builder.isNullValue(filler))
292 nonzeroLength = elements.size();
293
294 if (nonzeroLength == elements.size()) {
295 while (nonzeroLength > 0 &&
296 builder.isNullValue(elements[nonzeroLength - 1]))
297 --nonzeroLength;
298 }
299
300 if (nonzeroLength == 0)
301 return cir::ZeroAttr::get(desiredType);
302
303 const unsigned trailingZeroes = arrayBound - nonzeroLength;
304
305 // Add a zeroinitializer array filler if we have lots of trailing zeroes.
306 if (trailingZeroes >= 8) {
307 assert(elements.size() >= nonzeroLength &&
308 "missing initializer for non-zero element");
309 } else if (elements.size() != arrayBound) {
310 elements.resize(arrayBound, filler);
311
312 if (filler.getType() != commonElementType)
313 commonElementType = {};
314 }
315
316 if (commonElementType) {
317 SmallVector<mlir::Attribute, 4> eles;
318 eles.reserve(elements.size());
319
320 for (const auto &element : elements)
321 eles.push_back(element);
322
323 return cir::ConstArrayAttr::get(
324 cir::ArrayType::get(commonElementType, arrayBound),
325 mlir::ArrayAttr::get(builder.getContext(), eles));
326 }
327
328 cgm.errorNYI(feature: "array with different type elements");
329 return {};
330}
331
332//===----------------------------------------------------------------------===//
333// ConstantEmitter
334//===----------------------------------------------------------------------===//
335
336mlir::Attribute ConstantEmitter::tryEmitForInitializer(const VarDecl &d) {
337 initializeNonAbstract();
338 return markIfFailed(tryEmitPrivateForVarInit(d));
339}
340
341void ConstantEmitter::finalize(cir::GlobalOp gv) {
342 assert(initializedNonAbstract &&
343 "finalizing emitter that was used for abstract emission?");
344 assert(!finalized && "finalizing emitter multiple times");
345 assert(!gv.isDeclaration());
346#ifndef NDEBUG
347 // Note that we might also be Failed.
348 finalized = true;
349#endif // NDEBUG
350}
351
352mlir::Attribute
353ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &d) {
354 AbstractStateRAII state(*this, true);
355 return tryEmitPrivateForVarInit(d);
356}
357
358ConstantEmitter::~ConstantEmitter() {
359 assert((!initializedNonAbstract || finalized || failed) &&
360 "not finalized after being initialized for non-abstract emission");
361}
362
363mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &d) {
364 // Make a quick check if variable can be default NULL initialized
365 // and avoid going through rest of code which may do, for c++11,
366 // initialization of memory to all NULLs.
367 if (!d.hasLocalStorage()) {
368 QualType ty = cgm.getASTContext().getBaseElementType(d.getType());
369 if (ty->isRecordType()) {
370 if (const auto *e = dyn_cast_or_null<CXXConstructExpr>(Val: d.getInit())) {
371 const CXXConstructorDecl *cd = e->getConstructor();
372 // FIXME: we should probably model this more closely to C++ than
373 // just emitting a global with zero init (mimic what we do for trivial
374 // assignments and whatnots). Since this is for globals shouldn't
375 // be a problem for the near future.
376 if (cd->isTrivial() && cd->isDefaultConstructor()) {
377 const auto *cxxrd =
378 cast<CXXRecordDecl>(Val: ty->getAs<RecordType>()->getDecl());
379 if (cxxrd->getNumBases() != 0) {
380 // There may not be anything additional to do here, but this will
381 // force us to pause and test this path when it is supported.
382 cgm.errorNYI(feature: "tryEmitPrivateForVarInit: cxx record with bases");
383 return {};
384 }
385 if (!cgm.getTypes().isZeroInitializable(cxxrd)) {
386 // To handle this case, we really need to go through
387 // emitNullConstant, but we need an attribute, not a value
388 cgm.errorNYI(
389 feature: "tryEmitPrivateForVarInit: non-zero-initializable cxx record");
390 return {};
391 }
392 return cir::ZeroAttr::get(cgm.convertType(d.getType()));
393 }
394 }
395 }
396 }
397 inConstantContext = d.hasConstantInitialization();
398
399 const Expr *e = d.getInit();
400 assert(e && "No initializer to emit");
401
402 QualType destType = d.getType();
403
404 if (!destType->isReferenceType()) {
405 QualType nonMemoryDestType = getNonMemoryType(cgm, type: destType);
406 if (mlir::Attribute c = ConstExprEmitter(*this).Visit(const_cast<Expr *>(e),
407 nonMemoryDestType))
408 return emitForMemory(c, destType);
409 }
410
411 // Try to emit the initializer. Note that this can allow some things that
412 // are not allowed by tryEmitPrivateForMemory alone.
413 if (APValue *value = d.evaluateValue())
414 return tryEmitPrivateForMemory(*value, destType);
415
416 return {};
417}
418
419mlir::Attribute ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *ce) {
420 if (!ce->hasAPValueResult())
421 return {};
422
423 QualType retType = ce->getType();
424 if (ce->isGLValue())
425 retType = cgm.getASTContext().getLValueReferenceType(T: retType);
426
427 return emitAbstract(ce->getBeginLoc(), ce->getAPValueResult(), retType);
428}
429
430mlir::Attribute ConstantEmitter::tryEmitPrivateForMemory(const APValue &value,
431 QualType destType) {
432 QualType nonMemoryDestType = getNonMemoryType(cgm, type: destType);
433 mlir::Attribute c = tryEmitPrivate(value, nonMemoryDestType);
434 return (c ? emitForMemory(c, destType) : nullptr);
435}
436
437mlir::Attribute ConstantEmitter::emitAbstract(SourceLocation loc,
438 const APValue &value,
439 QualType destType) {
440 AbstractStateRAII state(*this, true);
441 mlir::Attribute c = tryEmitPrivate(value, destType);
442 if (!c)
443 cgm.errorNYI(loc, "emitAbstract failed, emit null constaant");
444 return c;
445}
446
447mlir::Attribute ConstantEmitter::emitForMemory(mlir::Attribute c,
448 QualType destType) {
449 // For an _Atomic-qualified constant, we may need to add tail padding.
450 if (destType->getAs<AtomicType>()) {
451 cgm.errorNYI(feature: "emitForMemory: atomic type");
452 return {};
453 }
454
455 return c;
456}
457
458mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
459 QualType destType) {
460 auto &builder = cgm.getBuilder();
461 switch (value.getKind()) {
462 case APValue::None:
463 case APValue::Indeterminate:
464 cgm.errorNYI(feature: "ConstExprEmitter::tryEmitPrivate none or indeterminate");
465 return {};
466 case APValue::Int: {
467 mlir::Type ty = cgm.convertType(destType);
468 if (mlir::isa<cir::BoolType>(ty))
469 return builder.getCIRBoolAttr(value.getInt().getZExtValue());
470 assert(mlir::isa<cir::IntType>(ty) && "expected integral type");
471 return cgm.getBuilder().getAttr<cir::IntAttr>(ty, value.getInt());
472 }
473 case APValue::Float: {
474 const llvm::APFloat &init = value.getFloat();
475 if (&init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
476 !cgm.getASTContext().getLangOpts().NativeHalfType &&
477 cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {
478 cgm.errorNYI(feature: "ConstExprEmitter::tryEmitPrivate half");
479 return {};
480 }
481
482 mlir::Type ty = cgm.convertType(destType);
483 assert(mlir::isa<cir::CIRFPTypeInterface>(ty) &&
484 "expected floating-point type");
485 return cgm.getBuilder().getAttr<cir::FPAttr>(ty, init);
486 }
487 case APValue::Array: {
488 const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(T: destType);
489 const QualType arrayElementTy = arrayTy->getElementType();
490 const unsigned numElements = value.getArraySize();
491 const unsigned numInitElts = value.getArrayInitializedElts();
492
493 mlir::Attribute filler;
494 if (value.hasArrayFiller()) {
495 filler = tryEmitPrivate(value.getArrayFiller(), arrayElementTy);
496 if (!filler)
497 return {};
498 }
499
500 SmallVector<mlir::TypedAttr, 16> elements;
501 if (filler && builder.isNullValue(filler))
502 elements.reserve(numInitElts + 1);
503 else
504 elements.reserve(numInitElts);
505
506 mlir::Type commonElementType;
507 for (unsigned i = 0; i < numInitElts; ++i) {
508 const APValue &arrayElement = value.getArrayInitializedElt(I: i);
509 const mlir::Attribute element =
510 tryEmitPrivateForMemory(arrayElement, arrayElementTy);
511 if (!element)
512 return {};
513
514 const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);
515 if (i == 0)
516 commonElementType = elementTyped.getType();
517 else if (elementTyped.getType() != commonElementType) {
518 commonElementType = {};
519 }
520
521 elements.push_back(elementTyped);
522 }
523
524 mlir::TypedAttr typedFiller = llvm::cast_or_null<mlir::TypedAttr>(filler);
525 if (filler && !typedFiller)
526 cgm.errorNYI(feature: "array filler should always be typed");
527
528 mlir::Type desiredType = cgm.convertType(destType);
529 return emitArrayConstant(cgm, desiredType, commonElementType, numElements,
530 elements, typedFiller);
531 }
532 case APValue::Vector: {
533 const QualType elementType =
534 destType->castAs<VectorType>()->getElementType();
535 const unsigned numElements = value.getVectorLength();
536
537 SmallVector<mlir::Attribute, 16> elements;
538 elements.reserve(numElements);
539
540 for (unsigned i = 0; i < numElements; ++i) {
541 const mlir::Attribute element =
542 tryEmitPrivateForMemory(value.getVectorElt(i), elementType);
543 if (!element)
544 return {};
545 elements.push_back(element);
546 }
547
548 const auto desiredVecTy =
549 mlir::cast<cir::VectorType>(cgm.convertType(destType));
550
551 return cir::ConstVectorAttr::get(
552 desiredVecTy,
553 mlir::ArrayAttr::get(cgm.getBuilder().getContext(), elements));
554 }
555 case APValue::MemberPointer: {
556 cgm.errorNYI(feature: "ConstExprEmitter::tryEmitPrivate member pointer");
557 return {};
558 }
559 case APValue::LValue: {
560
561 if (value.getLValueBase()) {
562 cgm.errorNYI(feature: "non-null pointer initialization");
563 } else {
564
565 mlir::Type desiredType = cgm.convertType(destType);
566 if (const cir::PointerType ptrType =
567 mlir::dyn_cast<cir::PointerType>(desiredType)) {
568 return builder.getConstPtrAttr(ptrType,
569 value.getLValueOffset().getQuantity());
570 } else {
571 llvm_unreachable("non-pointer variable initialized with a pointer");
572 }
573 }
574 return {};
575 }
576 case APValue::Struct:
577 case APValue::Union:
578 cgm.errorNYI(feature: "ConstExprEmitter::tryEmitPrivate struct or union");
579 return {};
580 case APValue::ComplexInt:
581 case APValue::ComplexFloat: {
582 mlir::Type desiredType = cgm.convertType(destType);
583 cir::ComplexType complexType =
584 mlir::dyn_cast<cir::ComplexType>(desiredType);
585
586 mlir::Type complexElemTy = complexType.getElementType();
587 if (isa<cir::IntType>(complexElemTy)) {
588 llvm::APSInt real = value.getComplexIntReal();
589 llvm::APSInt imag = value.getComplexIntImag();
590 return builder.getAttr<cir::ConstComplexAttr>(
591 complexType, builder.getAttr<cir::IntAttr>(complexElemTy, real),
592 builder.getAttr<cir::IntAttr>(complexElemTy, imag));
593 }
594
595 assert(isa<cir::CIRFPTypeInterface>(complexElemTy) &&
596 "expected floating-point type");
597 llvm::APFloat real = value.getComplexFloatReal();
598 llvm::APFloat imag = value.getComplexFloatImag();
599 return builder.getAttr<cir::ConstComplexAttr>(
600 complexType, builder.getAttr<cir::FPAttr>(complexElemTy, real),
601 builder.getAttr<cir::FPAttr>(complexElemTy, imag));
602 }
603 case APValue::FixedPoint:
604 case APValue::AddrLabelDiff:
605 cgm.errorNYI(
606 feature: "ConstExprEmitter::tryEmitPrivate fixed point, addr label diff");
607 return {};
608 }
609 llvm_unreachable("Unknown APValue kind");
610}
611
612mlir::Value CIRGenModule::emitNullConstant(QualType t, mlir::Location loc) {
613 if (t->getAs<PointerType>()) {
614 return builder.getNullPtr(getTypes().convertTypeForMem(t), loc);
615 }
616
617 if (getTypes().isZeroInitializable(ty: t))
618 return builder.getNullValue(getTypes().convertTypeForMem(t), loc);
619
620 if (getASTContext().getAsConstantArrayType(T: t)) {
621 errorNYI(feature: "CIRGenModule::emitNullConstant ConstantArrayType");
622 }
623
624 if (t->getAs<RecordType>())
625 errorNYI(feature: "CIRGenModule::emitNullConstant RecordType");
626
627 assert(t->isMemberDataPointerType() &&
628 "Should only see pointers to data members here!");
629
630 errorNYI(feature: "CIRGenModule::emitNullConstant unsupported type");
631 return {};
632}
633

source code of clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp