https://github.com/bcardosolopes created 
https://github.com/llvm/llvm-project/pull/214904

`-fno-clangir` was a no-op whenever `-fclangir` also appeared on the command 
line, in either order: the CIR pipeline ran regardless. Options.td already 
declares clangir as a BoolFOption with a NegFlag, so last-wins semantics were 
intended and the generated marshalling implements them correctly.

>From 5d776418dd01b380e854a8e78eff62ce9d828f89 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <[email protected]>
Date: Fri, 7 Aug 2026 17:44:25 -0700
Subject: [PATCH] [CIR] Honor -fno-clangir

-fno-clangir was a no-op whenever -fclangir also appeared on the command
line, in either order: the CIR pipeline ran regardless. Options.td already
declares clangir as a BoolFOption with a NegFlag, so last-wins semantics
were intended and the generated marshalling implements them correctly.
Two consumers bypassed it:

 - The driver tested Args.hasArg(OPT_fclangir), a presence check that never
   looks at the negation, and forwarded -fclangir to -cc1 unconditionally.

 - ParseFrontendArgs then set Opts.UseClangIRPipeline = true under the same
   presence check, clobbering the value the marshalling had already computed
   from both flags a few lines earlier.

Use hasFlag() in the driver, and drop the redundant frontend override.
-emit-cir still forces the pipeline on, since it is an action that requires
it.

Beyond the stated flag semantics, this matters for A/B testing: appending
-fno-clangir to a -fclangir build to produce a "CIR off" arm silently
produced a second CIR build instead.
---
 clang/lib/Driver/ToolChains/Clang.cpp     |  2 +-
 clang/lib/Frontend/CompilerInvocation.cpp |  5 ++++-
 clang/test/CIR/Driver/clangir.c           | 23 +++++++++++++++++++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 85fe99dbf8b69..ec1ad05497751 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5332,7 +5332,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     }
   }
 
-  if (Args.hasArg(options::OPT_fclangir))
+  if (Args.hasFlag(options::OPT_fclangir, options::OPT_fno_clangir, false))
     CmdArgs.push_back("-fclangir");
 
   if (IsOpenMPDevice) {
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 6562cb3a9b135..4f319f11e7cb6 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3172,7 +3172,10 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, 
ArgList &Args,
   if (Opts.ProgramAction != frontend::GenerateModule && Opts.IsSystemModule)
     Diags.Report(diag::err_drv_argument_only_allowed_with) << "-fsystem-module"
                                                            << "-emit-module";
-  if (Args.hasArg(OPT_fclangir) || Args.hasArg(OPT_emit_cir))
+  // -fclangir/-fno-clangir are marshalled into Opts.UseClangIRPipeline above,
+  // which already gives them last-wins semantics; don't clobber that here.
+  // -emit-cir is an action that implies the pipeline regardless.
+  if (Args.hasArg(OPT_emit_cir))
     Opts.UseClangIRPipeline = true;
 
 #if CLANG_ENABLE_CIR
diff --git a/clang/test/CIR/Driver/clangir.c b/clang/test/CIR/Driver/clangir.c
index afbe6c6d2388f..d8419d8812f62 100644
--- a/clang/test/CIR/Driver/clangir.c
+++ b/clang/test/CIR/Driver/clangir.c
@@ -15,4 +15,27 @@
 // LLVMIR: "-cc1"
 // LLVMIR-SAME: "-fclangir"
 
+// -fclangir and -fno-clangir are last-wins, in either order.
+
+// RUN: %clang -### -fclangir -fno-clangir -S %s 2>&1 | FileCheck %s 
--check-prefix=NEG
+// RUN: %clang -### -fno-clangir -S %s 2>&1 | FileCheck %s --check-prefix=NEG
+// NEG: "-cc1"
+// NEG-NOT: "-fclangir"
+
+// RUN: %clang -### -fno-clangir -fclangir -S %s 2>&1 | FileCheck %s 
--check-prefix=POS
+// POS: "-cc1"
+// POS-SAME: "-fclangir"
+
+// The frontend must honor the negation too, not just the driver. -fopenacc
+// warns only when the CIR pipeline is off, which makes UseClangIRPipeline
+// observable at -cc1.
+
+// RUN: %clang_cc1 -fopenacc -fclangir -fno-clangir -emit-llvm-only %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-OFF
+// CC1-OFF: use -fclangir to enable runtime effect
+
+// RUN: %clang_cc1 -fopenacc -fno-clangir -fclangir -emit-llvm-only %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-ON --allow-empty
+// CC1-ON-NOT: use -fclangir to enable runtime effect
+
 void foo() {}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to