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 Decl nodes as CIR code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenConstantEmitter.h"
14#include "CIRGenFunction.h"
15#include "mlir/IR/Location.h"
16#include "clang/AST/Attr.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclOpenACC.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/ExprCXX.h"
21#include "clang/CIR/MissingFeatures.h"
22
23using namespace clang;
24using namespace clang::CIRGen;
25
26CIRGenFunction::AutoVarEmission
27CIRGenFunction::emitAutoVarAlloca(const VarDecl &d) {
28 QualType ty = d.getType();
29 if (ty.getAddressSpace() != LangAS::Default)
30 cgm.errorNYI(d.getSourceRange(), "emitAutoVarAlloca: address space");
31
32 mlir::Location loc = getLoc(d.getSourceRange());
33
34 CIRGenFunction::AutoVarEmission emission(d);
35 emission.IsEscapingByRef = d.isEscapingByref();
36 if (emission.IsEscapingByRef)
37 cgm.errorNYI(d.getSourceRange(),
38 "emitAutoVarDecl: decl escaping by reference");
39
40 CharUnits alignment = getContext().getDeclAlign(D: &d);
41
42 // If the type is variably-modified, emit all the VLA sizes for it.
43 if (ty->isVariablyModifiedType())
44 cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: variably modified type");
45
46 Address address = Address::invalid();
47 if (!ty->isConstantSizeType())
48 cgm.errorNYI(d.getSourceRange(), "emitAutoVarDecl: non-constant size type");
49
50 // A normal fixed sized variable becomes an alloca in the entry block,
51 mlir::Type allocaTy = convertTypeForMem(ty);
52 // Create the temp alloca and declare variable using it.
53 address = createTempAlloca(allocaTy, alignment, loc, d.getName());
54 declare(address.getPointer(), &d, ty, getLoc(d.getSourceRange()), alignment);
55
56 emission.Addr = address;
57 setAddrOfLocalVar(vd: &d, addr: address);
58
59 return emission;
60}
61
62/// Determine whether the given initializer is trivial in the sense
63/// that it requires no code to be generated.
64bool CIRGenFunction::isTrivialInitializer(const Expr *init) {
65 if (!init)
66 return true;
67
68 if (const CXXConstructExpr *construct = dyn_cast<CXXConstructExpr>(Val: init))
69 if (CXXConstructorDecl *constructor = construct->getConstructor())
70 if (constructor->isTrivial() && constructor->isDefaultConstructor() &&
71 !construct->requiresZeroInitialization())
72 return true;
73
74 return false;
75}
76
77void CIRGenFunction::emitAutoVarInit(
78 const CIRGenFunction::AutoVarEmission &emission) {
79 assert(emission.Variable && "emission was not valid!");
80
81 // If this was emitted as a global constant, we're done.
82 if (emission.wasEmittedAsGlobal())
83 return;
84
85 const VarDecl &d = *emission.Variable;
86
87 QualType type = d.getType();
88
89 // If this local has an initializer, emit it now.
90 const Expr *init = d.getInit();
91
92 // Initialize the variable here if it doesn't have a initializer and it is a
93 // C struct that is non-trivial to initialize or an array containing such a
94 // struct.
95 if (!init && type.isNonTrivialToPrimitiveDefaultInitialize() ==
96 QualType::PDIK_Struct) {
97 cgm.errorNYI(d.getSourceRange(),
98 "emitAutoVarInit: non-trivial to default initialize");
99 return;
100 }
101
102 const Address addr = emission.Addr;
103
104 // Check whether this is a byref variable that's potentially
105 // captured and moved by its own initializer. If so, we'll need to
106 // emit the initializer first, then copy into the variable.
107 assert(!cir::MissingFeatures::opAllocaCaptureByInit());
108
109 // Note: constexpr already initializes everything correctly.
110 LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
111 (d.isConstexpr()
112 ? LangOptions::TrivialAutoVarInitKind::Uninitialized
113 : (d.getAttr<UninitializedAttr>()
114 ? LangOptions::TrivialAutoVarInitKind::Uninitialized
115 : getContext().getLangOpts().getTrivialAutoVarInit()));
116
117 auto initializeWhatIsTechnicallyUninitialized = [&](Address addr) {
118 if (trivialAutoVarInit ==
119 LangOptions::TrivialAutoVarInitKind::Uninitialized)
120 return;
121
122 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: trivial initialization");
123 };
124
125 if (isTrivialInitializer(init)) {
126 initializeWhatIsTechnicallyUninitialized(addr);
127 return;
128 }
129
130 mlir::Attribute constant;
131 if (emission.IsConstantAggregate ||
132 d.mightBeUsableInConstantExpressions(C: getContext())) {
133 // FIXME: Differently from LLVM we try not to emit / lower too much
134 // here for CIR since we are interested in seeing the ctor in some
135 // analysis later on. So CIR's implementation of ConstantEmitter will
136 // frequently return an empty Attribute, to signal we want to codegen
137 // some trivial ctor calls and whatnots.
138 constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(d);
139 if (constant && !mlir::isa<cir::ZeroAttr>(constant) &&
140 (trivialAutoVarInit !=
141 LangOptions::TrivialAutoVarInitKind::Uninitialized)) {
142 cgm.errorNYI(d.getSourceRange(), "emitAutoVarInit: constant aggregate");
143 return;
144 }
145 }
146
147 // NOTE(cir): In case we have a constant initializer, we can just emit a
148 // store. But, in CIR, we wish to retain any ctor calls, so if it is a
149 // CXX temporary object creation, we ensure the ctor call is used deferring
150 // its removal/optimization to the CIR lowering.
151 if (!constant || isa<CXXTemporaryObjectExpr>(Val: init)) {
152 initializeWhatIsTechnicallyUninitialized(addr);
153 LValue lv = makeAddrLValue(addr, ty: type, source: AlignmentSource::Decl);
154 emitExprAsInit(init, d: &d, lvalue: lv);
155 // In case lv has uses it means we indeed initialized something
156 // out of it while trying to build the expression, mark it as such.
157 mlir::Value val = lv.getAddress().getPointer();
158 assert(val && "Should have an address");
159 auto allocaOp = dyn_cast_or_null<cir::AllocaOp>(val.getDefiningOp());
160 assert(allocaOp && "Address should come straight out of the alloca");
161
162 if (!allocaOp.use_empty())
163 allocaOp.setInitAttr(mlir::UnitAttr::get(&getMLIRContext()));
164 return;
165 }
166
167 // FIXME(cir): migrate most of this file to use mlir::TypedAttr directly.
168 auto typedConstant = mlir::dyn_cast<mlir::TypedAttr>(constant);
169 assert(typedConstant && "expected typed attribute");
170 if (!emission.IsConstantAggregate) {
171 // For simple scalar/complex initialization, store the value directly.
172 LValue lv = makeAddrLValue(addr, ty: type);
173 assert(init && "expected initializer");
174 mlir::Location initLoc = getLoc(init->getSourceRange());
175 // lv.setNonGC(true);
176 return emitStoreThroughLValue(
177 RValue::src: get(builder.getConstant(initLoc, typedConstant)), dst: lv);
178 }
179}
180
181void CIRGenFunction::emitAutoVarCleanups(
182 const CIRGenFunction::AutoVarEmission &emission) {
183 const VarDecl &d = *emission.Variable;
184
185 // Check the type for a cleanup.
186 if (d.needsDestruction(Ctx: getContext()))
187 cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: type cleanup");
188
189 assert(!cir::MissingFeatures::opAllocaPreciseLifetime());
190
191 // Handle the cleanup attribute.
192 if (d.hasAttr<CleanupAttr>())
193 cgm.errorNYI(d.getSourceRange(), "emitAutoVarCleanups: CleanupAttr");
194}
195
196/// Emit code and set up symbol table for a variable declaration with auto,
197/// register, or no storage class specifier. These turn into simple stack
198/// objects, globals depending on target.
199void CIRGenFunction::emitAutoVarDecl(const VarDecl &d) {
200 CIRGenFunction::AutoVarEmission emission = emitAutoVarAlloca(d);
201 emitAutoVarInit(emission);
202 emitAutoVarCleanups(emission);
203}
204
205void CIRGenFunction::emitVarDecl(const VarDecl &d) {
206 // If the declaration has external storage, don't emit it now, allow it to be
207 // emitted lazily on its first use.
208 if (d.hasExternalStorage())
209 return;
210
211 if (d.getStorageDuration() != SD_Automatic) {
212 // Static sampler variables translated to function calls.
213 if (d.getType()->isSamplerT()) {
214 // Nothing needs to be done here, but let's flag it as an error until we
215 // have a test. It requires OpenCL support.
216 cgm.errorNYI(d.getSourceRange(), "emitVarDecl static sampler type");
217 return;
218 }
219
220 cir::GlobalLinkageKind linkage =
221 cgm.getCIRLinkageVarDefinition(&d, /*IsConstant=*/false);
222
223 // FIXME: We need to force the emission/use of a guard variable for
224 // some variables even if we can constant-evaluate them because
225 // we can't guarantee every translation unit will constant-evaluate them.
226
227 return emitStaticVarDecl(d, linkage);
228 }
229
230 if (d.getType().getAddressSpace() == LangAS::opencl_local)
231 cgm.errorNYI(d.getSourceRange(), "emitVarDecl openCL address space");
232
233 assert(d.hasLocalStorage());
234
235 CIRGenFunction::VarDeclContext varDeclCtx{*this, &d};
236 return emitAutoVarDecl(d);
237}
238
239static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d) {
240 if (cgm.getLangOpts().CPlusPlus)
241 return cgm.getMangledName(gd: &d).str();
242
243 // If this isn't C++, we don't need a mangled name, just a pretty one.
244 assert(!d.isExternallyVisible() && "name shouldn't matter");
245 std::string contextName;
246 const DeclContext *dc = d.getDeclContext();
247 if (auto *cd = dyn_cast<CapturedDecl>(Val: dc))
248 dc = cast<DeclContext>(Val: cd->getNonClosureContext());
249 if (const auto *fd = dyn_cast<FunctionDecl>(Val: dc))
250 contextName = std::string(cgm.getMangledName(gd: fd));
251 else if (isa<BlockDecl>(Val: dc))
252 cgm.errorNYI(d.getSourceRange(), "block decl context for static var");
253 else if (isa<ObjCMethodDecl>(Val: dc))
254 cgm.errorNYI(d.getSourceRange(), "ObjC decl context for static var");
255 else
256 cgm.errorNYI(d.getSourceRange(), "Unknown context for static var decl");
257
258 contextName += "." + d.getNameAsString();
259 return contextName;
260}
261
262// TODO(cir): LLVM uses a Constant base class. Maybe CIR could leverage an
263// interface for all constants?
264cir::GlobalOp
265CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &d,
266 cir::GlobalLinkageKind linkage) {
267 // In general, we don't always emit static var decls once before we reference
268 // them. It is possible to reference them before emitting the function that
269 // contains them, and it is possible to emit the containing function multiple
270 // times.
271 if (cir::GlobalOp existingGV = getStaticLocalDeclAddress(&d))
272 return existingGV;
273
274 QualType ty = d.getType();
275 assert(ty->isConstantSizeType() && "VLAs can't be static");
276
277 // Use the label if the variable is renamed with the asm-label extension.
278 if (d.hasAttr<AsmLabelAttr>())
279 errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: asm label");
280
281 std::string name = getStaticDeclName(cgm&: *this, d);
282
283 mlir::Type lty = getTypes().convertTypeForMem(ty);
284 assert(!cir::MissingFeatures::addressSpace());
285
286 if (d.hasAttr<LoaderUninitializedAttr>() || d.hasAttr<CUDASharedAttr>())
287 errorNYI(d.getSourceRange(),
288 "getOrCreateStaticVarDecl: LoaderUninitializedAttr");
289 assert(!cir::MissingFeatures::addressSpace());
290
291 mlir::Attribute init = builder.getZeroInitAttr(convertType(ty));
292
293 cir::GlobalOp gv = builder.createVersionedGlobal(
294 getModule(), getLoc(d.getLocation()), name, lty, linkage);
295 // TODO(cir): infer visibility from linkage in global op builder.
296 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
297 gv.setInitialValueAttr(init);
298 gv.setAlignment(getASTContext().getDeclAlign(D: &d).getAsAlign().value());
299
300 if (supportsCOMDAT() && gv.isWeakForLinker())
301 gv.setComdat(true);
302
303 assert(!cir::MissingFeatures::opGlobalThreadLocal());
304
305 setGVProperties(gv, &d);
306
307 // OG checks if the expected address space, denoted by the type, is the
308 // same as the actual address space indicated by attributes. If they aren't
309 // the same, an addrspacecast is emitted when this variable is accessed.
310 // In CIR however, cir.get_global already carries that information in
311 // !cir.ptr type - if this global is in OpenCL local address space, then its
312 // type would be !cir.ptr<..., addrspace(offload_local)>. Therefore we don't
313 // need an explicit address space cast in CIR: they will get emitted when
314 // lowering to LLVM IR.
315
316 // Ensure that the static local gets initialized by making sure the parent
317 // function gets emitted eventually.
318 const Decl *dc = cast<Decl>(Val: d.getDeclContext());
319
320 // We can't name blocks or captured statements directly, so try to emit their
321 // parents.
322 if (isa<BlockDecl>(Val: dc) || isa<CapturedDecl>(Val: dc)) {
323 dc = dc->getNonClosureContext();
324 // FIXME: Ensure that global blocks get emitted.
325 if (!dc)
326 errorNYI(d.getSourceRange(), "non-closure context");
327 }
328
329 GlobalDecl gd;
330 if (isa<CXXConstructorDecl>(Val: dc))
331 errorNYI(d.getSourceRange(), "C++ constructors static var context");
332 else if (isa<CXXDestructorDecl>(Val: dc))
333 errorNYI(d.getSourceRange(), "C++ destructors static var context");
334 else if (const auto *fd = dyn_cast<FunctionDecl>(Val: dc))
335 gd = GlobalDecl(fd);
336 else {
337 // Don't do anything for Obj-C method decls or global closures. We should
338 // never defer them.
339 assert(isa<ObjCMethodDecl>(dc) && "unexpected parent code decl");
340 }
341 if (gd.getDecl() && cir::MissingFeatures::openMP()) {
342 // Disable emission of the parent function for the OpenMP device codegen.
343 errorNYI(d.getSourceRange(), "OpenMP");
344 }
345
346 return gv;
347}
348
349/// Add the initializer for 'd' to the global variable that has already been
350/// created for it. If the initializer has a different type than gv does, this
351/// may free gv and return a different one. Otherwise it just returns gv.
352cir::GlobalOp CIRGenFunction::addInitializerToStaticVarDecl(
353 const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
354 ConstantEmitter emitter(*this);
355 mlir::TypedAttr init =
356 mlir::cast<mlir::TypedAttr>(emitter.tryEmitForInitializer(d));
357
358 // If constant emission failed, then this should be a C++ static
359 // initializer.
360 if (!init) {
361 cgm.errorNYI(d.getSourceRange(), "static var without initializer");
362 return gv;
363 }
364
365 // TODO(cir): There should be debug code here to assert that the decl size
366 // matches the CIR data layout type alloc size, but the code for calculating
367 // the type alloc size is not implemented yet.
368 assert(!cir::MissingFeatures::dataLayoutTypeAllocSize());
369
370 // The initializer may differ in type from the global. Rewrite
371 // the global to match the initializer. (We have to do this
372 // because some types, like unions, can't be completely represented
373 // in the LLVM type system.)
374 if (gv.getSymType() != init.getType()) {
375 gv.setSymType(init.getType());
376
377 // Normally this should be done with a call to cgm.replaceGlobal(oldGV, gv),
378 // but since at this point the current block hasn't been really attached,
379 // there's no visibility into the GetGlobalOp corresponding to this Global.
380 // Given those constraints, thread in the GetGlobalOp and update it
381 // directly.
382 assert(!cir::MissingFeatures::addressSpace());
383 gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
384 }
385
386 bool needsDtor =
387 d.needsDestruction(Ctx: getContext()) == QualType::DK_cxx_destructor;
388
389 assert(!cir::MissingFeatures::opGlobalConstant());
390 gv.setInitialValueAttr(init);
391
392 emitter.finalize(gv);
393
394 if (needsDtor) {
395 // We have a constant initializer, but a nontrivial destructor. We still
396 // need to perform a guarded "initialization" in order to register the
397 // destructor.
398 cgm.errorNYI(d.getSourceRange(), "C++ guarded init");
399 }
400
401 return gv;
402}
403
404void CIRGenFunction::emitStaticVarDecl(const VarDecl &d,
405 cir::GlobalLinkageKind linkage) {
406 // Check to see if we already have a global variable for this
407 // declaration. This can happen when double-emitting function
408 // bodies, e.g. with complete and base constructors.
409 cir::GlobalOp globalOp = cgm.getOrCreateStaticVarDecl(d, linkage);
410 // TODO(cir): we should have a way to represent global ops as values without
411 // having to emit a get global op. Sometimes these emissions are not used.
412 mlir::Value addr = builder.createGetGlobal(globalOp);
413 auto getAddrOp = mlir::cast<cir::GetGlobalOp>(addr.getDefiningOp());
414
415 CharUnits alignment = getContext().getDeclAlign(D: &d);
416
417 // Store into LocalDeclMap before generating initializer to handle
418 // circular references.
419 mlir::Type elemTy = convertTypeForMem(d.getType());
420 setAddrOfLocalVar(vd: &d, addr: Address(addr, elemTy, alignment));
421
422 // We can't have a VLA here, but we can have a pointer to a VLA,
423 // even though that doesn't really make any sense.
424 // Make sure to evaluate VLA bounds now so that we have them for later.
425 if (d.getType()->isVariablyModifiedType()) {
426 cgm.errorNYI(d.getSourceRange(),
427 "emitStaticVarDecl: variably modified type");
428 }
429
430 // Save the type in case adding the initializer forces a type change.
431 mlir::Type expectedType = addr.getType();
432
433 cir::GlobalOp var = globalOp;
434
435 assert(!cir::MissingFeatures::cudaSupport());
436
437 // If this value has an initializer, emit it.
438 if (d.getInit())
439 var = addInitializerToStaticVarDecl(d, var, getAddrOp);
440
441 var.setAlignment(alignment.getAsAlign().value());
442
443 // There are a lot of attributes that need to be handled here. Until
444 // we start to support them, we just report an error if there are any.
445 if (d.hasAttrs())
446 cgm.errorNYI(d.getSourceRange(), "static var with attrs");
447
448 if (cgm.getCodeGenOpts().KeepPersistentStorageVariables)
449 cgm.errorNYI(d.getSourceRange(), "static var keep persistent storage");
450
451 // From traditional codegen:
452 // We may have to cast the constant because of the initializer
453 // mismatch above.
454 //
455 // FIXME: It is really dangerous to store this in the map; if anyone
456 // RAUW's the GV uses of this constant will be invalid.
457 mlir::Value castedAddr =
458 builder.createBitcast(getAddrOp.getAddr(), expectedType);
459 localDeclMap.find(Val: &d)->second = Address(castedAddr, elemTy, alignment);
460 cgm.setStaticLocalDeclAddress(&d, var);
461
462 assert(!cir::MissingFeatures::sanitizers());
463 assert(!cir::MissingFeatures::generateDebugInfo());
464}
465
466void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,
467 LValue lvalue, bool capturedByInit) {
468 assert(!cir::MissingFeatures::objCLifetime());
469
470 SourceLocRAIIObject locRAII{*this, loc};
471 mlir::Value value = emitScalarExpr(init);
472 if (capturedByInit) {
473 cgm.errorNYI(init->getSourceRange(), "emitScalarInit: captured by init");
474 return;
475 }
476 assert(!cir::MissingFeatures::emitNullabilityCheck());
477 emitStoreThroughLValue(RValue::src: get(value), dst: lvalue, isInit: true);
478}
479
480void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
481 LValue lvalue, bool capturedByInit) {
482 SourceLocRAIIObject loc{*this, getLoc(init->getSourceRange())};
483 if (capturedByInit) {
484 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
485 return;
486 }
487
488 QualType type = d->getType();
489
490 if (type->isReferenceType()) {
491 RValue rvalue = emitReferenceBindingToExpr(e: init);
492 if (capturedByInit)
493 cgm.errorNYI(init->getSourceRange(), "emitExprAsInit: captured by init");
494 emitStoreThroughLValue(src: rvalue, dst: lvalue);
495 return;
496 }
497 switch (CIRGenFunction::getEvaluationKind(type)) {
498 case cir::TEK_Scalar:
499 emitScalarInit(init, getLoc(d->getSourceRange()), lvalue);
500 return;
501 case cir::TEK_Complex: {
502 mlir::Value complex = emitComplexExpr(init);
503 if (capturedByInit)
504 cgm.errorNYI(init->getSourceRange(),
505 "emitExprAsInit: complex type captured by init");
506 mlir::Location loc = getLoc(init->getExprLoc());
507 emitStoreOfComplex(loc, complex, lvalue,
508 /*isInit*/ true);
509 return;
510 }
511 case cir::TEK_Aggregate:
512 // The overlap flag here should be calculated.
513 assert(!cir::MissingFeatures::aggValueSlotMayOverlap());
514 emitAggExpr(e: init,
515 slot: AggValueSlot::forLValue(LV: lvalue, isDestructed: AggValueSlot::IsDestructed,
516 isAliased: AggValueSlot::IsNotAliased,
517 mayOverlap: AggValueSlot::MayOverlap));
518 return;
519 }
520 llvm_unreachable("bad evaluation kind");
521}
522
523void CIRGenFunction::emitDecl(const Decl &d) {
524 switch (d.getKind()) {
525 case Decl::BuiltinTemplate:
526 case Decl::TranslationUnit:
527 case Decl::ExternCContext:
528 case Decl::Namespace:
529 case Decl::UnresolvedUsingTypename:
530 case Decl::ClassTemplateSpecialization:
531 case Decl::ClassTemplatePartialSpecialization:
532 case Decl::VarTemplateSpecialization:
533 case Decl::VarTemplatePartialSpecialization:
534 case Decl::TemplateTypeParm:
535 case Decl::UnresolvedUsingValue:
536 case Decl::NonTypeTemplateParm:
537 case Decl::CXXDeductionGuide:
538 case Decl::CXXMethod:
539 case Decl::CXXConstructor:
540 case Decl::CXXDestructor:
541 case Decl::CXXConversion:
542 case Decl::Field:
543 case Decl::MSProperty:
544 case Decl::IndirectField:
545 case Decl::ObjCIvar:
546 case Decl::ObjCAtDefsField:
547 case Decl::ParmVar:
548 case Decl::ImplicitParam:
549 case Decl::ClassTemplate:
550 case Decl::VarTemplate:
551 case Decl::FunctionTemplate:
552 case Decl::TypeAliasTemplate:
553 case Decl::TemplateTemplateParm:
554 case Decl::ObjCMethod:
555 case Decl::ObjCCategory:
556 case Decl::ObjCProtocol:
557 case Decl::ObjCInterface:
558 case Decl::ObjCCategoryImpl:
559 case Decl::ObjCImplementation:
560 case Decl::ObjCProperty:
561 case Decl::ObjCCompatibleAlias:
562 case Decl::PragmaComment:
563 case Decl::PragmaDetectMismatch:
564 case Decl::AccessSpec:
565 case Decl::LinkageSpec:
566 case Decl::Export:
567 case Decl::ObjCPropertyImpl:
568 case Decl::FileScopeAsm:
569 case Decl::Friend:
570 case Decl::FriendTemplate:
571 case Decl::Block:
572 case Decl::OutlinedFunction:
573 case Decl::Captured:
574 case Decl::UsingShadow:
575 case Decl::ConstructorUsingShadow:
576 case Decl::ObjCTypeParam:
577 case Decl::Binding:
578 case Decl::UnresolvedUsingIfExists:
579 case Decl::HLSLBuffer:
580 case Decl::HLSLRootSignature:
581 llvm_unreachable("Declaration should not be in declstmts!");
582
583 case Decl::Function: // void X();
584 case Decl::EnumConstant: // enum ? { X = ? }
585 case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
586 case Decl::Label: // __label__ x;
587 case Decl::Import:
588 case Decl::MSGuid: // __declspec(uuid("..."))
589 case Decl::TemplateParamObject:
590 case Decl::OMPThreadPrivate:
591 case Decl::OMPAllocate:
592 case Decl::OMPCapturedExpr:
593 case Decl::OMPRequires:
594 case Decl::Empty:
595 case Decl::Concept:
596 case Decl::LifetimeExtendedTemporary:
597 case Decl::RequiresExprBody:
598 case Decl::UnnamedGlobalConstant:
599 // None of these decls require codegen support.
600 return;
601
602 case Decl::Enum: // enum X;
603 case Decl::Record: // struct/union/class X;
604 case Decl::CXXRecord: // struct/union/class X; [C++]
605 case Decl::NamespaceAlias:
606 case Decl::Using: // using X; [C++]
607 case Decl::UsingEnum: // using enum X; [C++]
608 case Decl::UsingDirective: // using namespace X; [C++]
609 assert(!cir::MissingFeatures::generateDebugInfo());
610 return;
611 case Decl::Var: {
612 const VarDecl &vd = cast<VarDecl>(Val: d);
613 assert(vd.isLocalVarDecl() &&
614 "Should not see file-scope variables inside a function!");
615 emitVarDecl(d: vd);
616 return;
617 }
618 case Decl::OpenACCDeclare:
619 emitOpenACCDeclare(d: cast<OpenACCDeclareDecl>(Val: d));
620 return;
621 case Decl::OpenACCRoutine:
622 emitOpenACCRoutine(d: cast<OpenACCRoutineDecl>(Val: d));
623 return;
624 case Decl::Typedef: // typedef int X;
625 case Decl::TypeAlias: { // using X = int; [C++0x]
626 QualType ty = cast<TypedefNameDecl>(Val: d).getUnderlyingType();
627 assert(!cir::MissingFeatures::generateDebugInfo());
628 if (ty->isVariablyModifiedType())
629 cgm.errorNYI(d.getSourceRange(), "emitDecl: variably modified type");
630 return;
631 }
632 case Decl::ImplicitConceptSpecialization:
633 case Decl::TopLevelStmt:
634 case Decl::UsingPack:
635 case Decl::Decomposition: // This could be moved to join Decl::Var
636 case Decl::OMPDeclareReduction:
637 case Decl::OMPDeclareMapper:
638 cgm.errorNYI(d.getSourceRange(),
639 std::string("emitDecl: unhandled decl type: ") +
640 d.getDeclKindName());
641 }
642}
643
644void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
645 SourceLocation loc) {
646 if (!sanOpts.has(K: SanitizerKind::NullabilityAssign))
647 return;
648
649 assert(!cir::MissingFeatures::sanitizers());
650}
651

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