[clang] [OpenMP] Fix infinite loop on recursive initializers (PR #126269)

Joseph Huber via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 7 09:53:08 PST 2025


https://github.com/jhuber6 updated https://github.com/llvm/llvm-project/pull/126269

>From f41096aa802fe80ae50882ecd610ef1a3cf5cee5 Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Fri, 7 Feb 2025 11:20:16 -0600
Subject: [PATCH 1/2] [OpenMP] Fix infinite recursion on global initializers

Summary:
If the user tried to initialize a gobal declare target variable with
itself the compiler will hang forever. Add a visited set to make sure
this stops.

Fixes: https://github.com/llvm/llvm-project/issues/69194
---
 clang/lib/Sema/SemaOpenMP.cpp                 | 4 ++++
 clang/test/OpenMP/declare_target_messages.cpp | 5 +++++
 2 files changed, 9 insertions(+)

diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index b060039d188a1bc..91e459c64030a0b 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -22819,8 +22819,12 @@ class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
   void declareTargetInitializer(Decl *TD) {
     A = TD->getAttr<OMPDeclareTargetDeclAttr>();
     DeclVector.push_back(cast<VarDecl>(TD));
+    llvm::DenseSet<Decl *> Visited;
     while (!DeclVector.empty()) {
       VarDecl *TargetVarDecl = DeclVector.pop_back_val();
+      if (!Visited.insert(TargetVarDecl).second)
+        continue;
+
       if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
           TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
         if (Expr *Ex = TargetVarDecl->getInit())
diff --git a/clang/test/OpenMP/declare_target_messages.cpp b/clang/test/OpenMP/declare_target_messages.cpp
index ce5a833b3866a9b..3c0e766cf72ca8e 100644
--- a/clang/test/OpenMP/declare_target_messages.cpp
+++ b/clang/test/OpenMP/declare_target_messages.cpp
@@ -33,6 +33,11 @@
 // RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp51,ompvar,omp45-to-51,omp5-and-51,omp5-or-later,omp5-or-later-var,omp45-to-51-var,omp45-to-51-clause,host-5-and-51,no-host5-and-51 -fopenmp %{limit} -o - %s
 // RUN: %clang_cc1 %{common_opts_mac} -verify=expected,omp52,ompvar,omp5-or-later,omp5-or-later-var %{openmp60} %{limit} -o - %s
 
+#pragma omp begin declare target
+static int gg;
+// expected-warning at +1 {{variable 'recursive' is uninitialized when used within its own initialization}}
+int recursive = recursive ^ 3 + gg;
+#pragma omp end declare target
 
 // expected-error at +1 {{unexpected OpenMP directive '#pragma omp end declare target'}}
 #pragma omp end declare target 

>From 3d832b91a2e9f4ea1e9a9d32b1d74079d1cfd65e Mon Sep 17 00:00:00 2001
From: Joseph Huber <huberjn at outlook.com>
Date: Fri, 7 Feb 2025 11:52:58 -0600
Subject: [PATCH 2/2] comments

---
 clang/lib/Sema/SemaOpenMP.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 91e459c64030a0b..376995d624e2830 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -22819,7 +22819,7 @@ class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
   void declareTargetInitializer(Decl *TD) {
     A = TD->getAttr<OMPDeclareTargetDeclAttr>();
     DeclVector.push_back(cast<VarDecl>(TD));
-    llvm::DenseSet<Decl *> Visited;
+    llvm::SmallDenseSet<Decl *> Visited;
     while (!DeclVector.empty()) {
       VarDecl *TargetVarDecl = DeclVector.pop_back_val();
       if (!Visited.insert(TargetVarDecl).second)



More information about the cfe-commits mailing list