diff options
author | Andy Kaylor <akaylor@nvidia.com> | 2025-04-24 16:42:36 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-24 16:42:36 -0700 |
commit | b6746b06574686a587587acafb38881ca848089c (patch) | |
tree | d7686bcf30db5d1dd997ec600525abc97c3e2ce5 /clang | |
parent | fdbf073a86573c9ac4d595fac8e06d252ce1469f (diff) | |
download | llvm-b6746b06574686a587587acafb38881ca848089c.zip llvm-b6746b06574686a587587acafb38881ca848089c.tar.gz llvm-b6746b06574686a587587acafb38881ca848089c.tar.bz2 |
[CIR] Upstream namepsace handling (#137253)
This adds the handlers for Decl::Namespace and Decl::UsingDirective
(which is needed for anonymous namespaces).
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenModule.cpp | 20 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenModule.h | 3 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/namespace.cpp | 55 |
4 files changed, 82 insertions, 0 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index d7cbb4f..8026f22 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -260,7 +260,11 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d, void CIRGenFunction::emitDecl(const Decl &d) { switch (d.getKind()) { + case Decl::Namespace: + llvm_unreachable("Declaration should not be in declstmts!"); + case Decl::Record: // struct/union/class X; + case Decl::UsingDirective: // using namespace X; [C++] assert(!cir::MissingFeatures::generateDebugInfo()); return; case Decl::Var: { diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 0b266df..0f4193b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -621,6 +621,20 @@ CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) { return getCIRLinkageForDeclarator(vd, linkage, isConstant); } +void CIRGenModule::emitDeclContext(const DeclContext *dc) { + for (Decl *decl : dc->decls()) { + // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope + // are themselves considered "top-level", so EmitTopLevelDecl on an + // ObjCImplDecl does not recursively visit them. We need to do that in + // case they're nested inside another construct (LinkageSpecDecl / + // ExportDecl) that does stop them from being considered "top-level". + if (auto *oid = dyn_cast<ObjCImplDecl>(decl)) + errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl"); + + emitTopLevelDecl(decl); + } +} + // Emit code for a single top level declaration. void CIRGenModule::emitTopLevelDecl(Decl *decl) { @@ -654,12 +668,18 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) { emitGlobalOpenACCDecl(cast<OpenACCDeclareDecl>(decl)); break; + case Decl::UsingDirective: // using namespace X; [C++] case Decl::Typedef: case Decl::TypeAlias: // using foo = bar; [C++11] case Decl::Record: case Decl::CXXRecord: assert(!cir::MissingFeatures::generateDebugInfo()); break; + + // C++ Decls + case Decl::Namespace: + emitDeclContext(cast<NamespaceDecl>(decl)); + break; } } diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index 1c14959..ea30903a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -170,6 +170,9 @@ public: void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd); + // C++ related functions. + void emitDeclContext(const DeclContext *dc); + /// Return the result of value-initializing the given type, i.e. a null /// expression of the given type. mlir::Value emitNullConstant(QualType t, mlir::Location loc); diff --git a/clang/test/CIR/CodeGen/namespace.cpp b/clang/test/CIR/CodeGen/namespace.cpp new file mode 100644 index 0000000..cfeb17b --- /dev/null +++ b/clang/test/CIR/CodeGen/namespace.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s + +// Test anonymous namespace. +namespace { + int g1 = 1; + + // Note: This causes a warning about the function being undefined, but we + // currently have a problem with duplicate definitions when we call functions. + // This should be updated when that problem is fixed. + void f1(void); +} + + +// Test named namespace. +namespace test { + int g2 = 2; + void f2(void); + + // Test nested namespace. + namespace test2 { + int g3 = 3; + void f3(void); + } +} + +// CHECK-DAG: cir.global internal @_ZN12_GLOBAL__N_12g1E = #cir.int<1> : !s32i +// CHECK-DAG: cir.global external @_ZN4test2g2E = #cir.int<2> : !s32i +// CHECK-DAG: cir.global external @_ZN4test5test22g3E = #cir.int<3> : !s32i +// CHECK-DAG: cir.func @_ZN12_GLOBAL__N_12f1Ev() +// CHECK-DAG: cir.func @_ZN4test2f2Ev() +// CHECK-DAG: cir.func @_ZN4test5test22f3Ev() + +using namespace test; + +// Test global function. +int f4(void) { + f1(); + f2(); + test2::f3(); + return g1 + g2 + test2::g3; +} + +// The namespace gets added during name mangling, so this is wrong but expected. +// CHECK: cir.func @_Z2f4v() +// CHECK: cir.call @_ZN12_GLOBAL__N_12f1Ev() +// CHECK: cir.call @_ZN4test2f2Ev() +// CHECK: cir.call @_ZN4test5test22f3Ev() +// CHECK: %[[G1_ADDR:.*]] = cir.get_global @_ZN12_GLOBAL__N_12g1E : !cir.ptr<!s32i> +// CHECK: %[[G1_VAL:.*]] = cir.load %[[G1_ADDR]] : !cir.ptr<!s32i>, !s32i +// CHECK: %[[G2_ADDR:.*]] = cir.get_global @_ZN4test2g2E : !cir.ptr<!s32i> +// CHECK: %[[G2_VAL:.*]] = cir.load %[[G2_ADDR]] : !cir.ptr<!s32i>, !s32i +// CHECK: %[[SUM:.*]] = cir.binop(add, %[[G1_VAL]], %[[G2_VAL]]) nsw : !s32i +// CHECK: %[[G3_ADDR:.*]] = cir.get_global @_ZN4test5test22g3E : !cir.ptr<!s32i> +// CHECK: %[[G3_VAL:.*]] = cir.load %[[G3_ADDR]] : !cir.ptr<!s32i>, !s32i +// CHECK: %[[SUM2:.*]] = cir.binop(add, %[[SUM]], %[[G3_VAL]]) nsw : !s32i |