Skip to content

Commit b6746b0

Browse files
authored
[CIR] Upstream namepsace handling (llvm#137253)
This adds the handlers for Decl::Namespace and Decl::UsingDirective (which is needed for anonymous namespaces).
1 parent fdbf073 commit b6746b0

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenDecl.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,11 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
260260

261261
void CIRGenFunction::emitDecl(const Decl &d) {
262262
switch (d.getKind()) {
263+
case Decl::Namespace:
264+
llvm_unreachable("Declaration should not be in declstmts!");
265+
263266
case Decl::Record: // struct/union/class X;
267+
case Decl::UsingDirective: // using namespace X; [C++]
264268
assert(!cir::MissingFeatures::generateDebugInfo());
265269
return;
266270
case Decl::Var: {

clang/lib/CIR/CodeGen/CIRGenModule.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,20 @@ CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {
621621
return getCIRLinkageForDeclarator(vd, linkage, isConstant);
622622
}
623623

624+
void CIRGenModule::emitDeclContext(const DeclContext *dc) {
625+
for (Decl *decl : dc->decls()) {
626+
// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
627+
// are themselves considered "top-level", so EmitTopLevelDecl on an
628+
// ObjCImplDecl does not recursively visit them. We need to do that in
629+
// case they're nested inside another construct (LinkageSpecDecl /
630+
// ExportDecl) that does stop them from being considered "top-level".
631+
if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
632+
errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
633+
634+
emitTopLevelDecl(decl);
635+
}
636+
}
637+
624638
// Emit code for a single top level declaration.
625639
void CIRGenModule::emitTopLevelDecl(Decl *decl) {
626640

@@ -654,12 +668,18 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
654668
emitGlobalOpenACCDecl(cast<OpenACCDeclareDecl>(decl));
655669
break;
656670

671+
case Decl::UsingDirective: // using namespace X; [C++]
657672
case Decl::Typedef:
658673
case Decl::TypeAlias: // using foo = bar; [C++11]
659674
case Decl::Record:
660675
case Decl::CXXRecord:
661676
assert(!cir::MissingFeatures::generateDebugInfo());
662677
break;
678+
679+
// C++ Decls
680+
case Decl::Namespace:
681+
emitDeclContext(cast<NamespaceDecl>(decl));
682+
break;
663683
}
664684
}
665685

clang/lib/CIR/CodeGen/CIRGenModule.h

+3
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ class CIRGenModule : public CIRGenTypeCache {
170170

171171
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd);
172172

173+
// C++ related functions.
174+
void emitDeclContext(const DeclContext *dc);
175+
173176
/// Return the result of value-initializing the given type, i.e. a null
174177
/// expression of the given type.
175178
mlir::Value emitNullConstant(QualType t, mlir::Location loc);

clang/test/CIR/CodeGen/namespace.cpp

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
2+
3+
// Test anonymous namespace.
4+
namespace {
5+
int g1 = 1;
6+
7+
// Note: This causes a warning about the function being undefined, but we
8+
// currently have a problem with duplicate definitions when we call functions.
9+
// This should be updated when that problem is fixed.
10+
void f1(void);
11+
}
12+
13+
14+
// Test named namespace.
15+
namespace test {
16+
int g2 = 2;
17+
void f2(void);
18+
19+
// Test nested namespace.
20+
namespace test2 {
21+
int g3 = 3;
22+
void f3(void);
23+
}
24+
}
25+
26+
// CHECK-DAG: cir.global internal @_ZN12_GLOBAL__N_12g1E = #cir.int<1> : !s32i
27+
// CHECK-DAG: cir.global external @_ZN4test2g2E = #cir.int<2> : !s32i
28+
// CHECK-DAG: cir.global external @_ZN4test5test22g3E = #cir.int<3> : !s32i
29+
// CHECK-DAG: cir.func @_ZN12_GLOBAL__N_12f1Ev()
30+
// CHECK-DAG: cir.func @_ZN4test2f2Ev()
31+
// CHECK-DAG: cir.func @_ZN4test5test22f3Ev()
32+
33+
using namespace test;
34+
35+
// Test global function.
36+
int f4(void) {
37+
f1();
38+
f2();
39+
test2::f3();
40+
return g1 + g2 + test2::g3;
41+
}
42+
43+
// The namespace gets added during name mangling, so this is wrong but expected.
44+
// CHECK: cir.func @_Z2f4v()
45+
// CHECK: cir.call @_ZN12_GLOBAL__N_12f1Ev()
46+
// CHECK: cir.call @_ZN4test2f2Ev()
47+
// CHECK: cir.call @_ZN4test5test22f3Ev()
48+
// CHECK: %[[G1_ADDR:.*]] = cir.get_global @_ZN12_GLOBAL__N_12g1E : !cir.ptr<!s32i>
49+
// CHECK: %[[G1_VAL:.*]] = cir.load %[[G1_ADDR]] : !cir.ptr<!s32i>, !s32i
50+
// CHECK: %[[G2_ADDR:.*]] = cir.get_global @_ZN4test2g2E : !cir.ptr<!s32i>
51+
// CHECK: %[[G2_VAL:.*]] = cir.load %[[G2_ADDR]] : !cir.ptr<!s32i>, !s32i
52+
// CHECK: %[[SUM:.*]] = cir.binop(add, %[[G1_VAL]], %[[G2_VAL]]) nsw : !s32i
53+
// CHECK: %[[G3_ADDR:.*]] = cir.get_global @_ZN4test5test22g3E : !cir.ptr<!s32i>
54+
// CHECK: %[[G3_VAL:.*]] = cir.load %[[G3_ADDR]] : !cir.ptr<!s32i>, !s32i
55+
// CHECK: %[[SUM2:.*]] = cir.binop(add, %[[SUM]], %[[G3_VAL]]) nsw : !s32i

0 commit comments

Comments
 (0)