Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang-repl] Handle frontend options for clang-repl before calling executeAction #132670

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

anutosh491
Copy link
Contributor

  1. How usual clang works

It goes from Creating the Compiler Instance -> Addressing these llvmargs -> calling executeAction

  1. what clang-repl does is create the Compiler Instance -> calls executeAction (and doesn't handle some options in between)

So ExecuteAction is framed like this

bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
  assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
  assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
  assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
....

And clang-repl would need to handle these before getting to executeAction.

Otherwise

  1. processing the -Xclang -version flag would give us the following (as shown while running clang-repl in the browser)

image

  1. This would also help us process a try-catch block while running clang-repl in the browser which can't be done currently

image

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 24, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 24, 2025

@llvm/pr-subscribers-clang

Author: Anutosh Bhat (anutosh491)

Changes
  1. How usual clang works

It goes from Creating the Compiler Instance -> Addressing these llvmargs -> calling executeAction

  1. what clang-repl does is create the Compiler Instance -> calls executeAction (and doesn't handle some options in between)

So ExecuteAction is framed like this

bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
  assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
  assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
  assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
....

And clang-repl would need to handle these before getting to executeAction.

Otherwise

  1. processing the -Xclang -version flag would give us the following (as shown while running clang-repl in the browser)

image

  1. This would also help us process a try-catch block while running clang-repl in the browser which can't be done currently

image


Full diff: https://github.com/llvm/llvm-project/pull/132670.diff

1 Files Affected:

  • (modified) clang/lib/Interpreter/Interpreter.cpp (+37-1)
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index fa4c1439c9261..5f48117dbf3b8 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -141,6 +141,37 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
   return std::move(Clang);
 }
 
+static llvm::Error HandleFrontendOptions(const CompilerInstance &CI) {
+  const auto &FrontendOpts = CI.getFrontendOpts();
+
+  if (FrontendOpts.ShowHelp) {
+    driver::getDriverOptTable().printHelp(
+        llvm::outs(), "clang -cc1 [options] file...",
+        "LLVM 'Clang' Compiler: http://clang.llvm.org",
+        /*ShowHidden=*/false, /*ShowAllAliases=*/false,
+        llvm::opt::Visibility(driver::options::CC1Option));
+    return llvm::createStringError(llvm::errc::not_supported, "Help displayed");
+  }
+
+  if (FrontendOpts.ShowVersion) {
+    llvm::cl::PrintVersionMessage();
+    return llvm::createStringError(llvm::errc::not_supported, "Version displayed");
+  }
+
+  if (!FrontendOpts.LLVMArgs.empty()) {
+    unsigned NumArgs = FrontendOpts.LLVMArgs.size();
+    auto Args = std::make_unique<const char*[]>(NumArgs + 2);
+    Args[0] = "clang-repl (LLVM option parsing)";
+    for (unsigned i = 0; i != NumArgs; ++i)
+      Args[i + 1] = FrontendOpts.LLVMArgs[i].c_str();
+    Args[NumArgs + 1] = nullptr;
+    llvm::errs() << "Parsing LLVM backend options via cl::ParseCommandLineOptions...\n";
+    llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
+  }
+
+  return llvm::Error::success();
+}
+
 } // anonymous namespace
 
 namespace clang {
@@ -451,7 +482,12 @@ const char *const Runtimes = R"(
 
 llvm::Expected<std::unique_ptr<Interpreter>>
 Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
-  llvm::Error Err = llvm::Error::success();
+
+  llvm::Error Err = HandleFrontendOptions(*CI);
+  if (Err) {
+    return std::move(Err);
+  }
+
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)

@anutosh491
Copy link
Contributor Author

After handling these args we should see

(base) anutosh491@Anutoshs-MacBook-Air bin % ./clang-repl --Xcc -Xclang --Xcc -version                                      
LLVM (http://llvm.org/):
  LLVM version 21.0.0git
  Optimized build.
clang-repl: Version displayed

rather than the abort.

Copy link

github-actions bot commented Mar 24, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@anutosh491
Copy link
Contributor Author

I see clang handle 4 types of FrontendOpts before calling ExecuteAction

  1. help
  2. version
  3. Plugins through LoadRequestedPlugins
  4. llvmargs

We might be interesting in 1, 2 and 4 for clang-repl
Also clang-repl uses IncrementalAction unlike FrontendAction so simply calling ExecuteCompilerInvocation won't do the job. So not sure if we can maybe refactor out 1/2/4 and use it from clang itself.

@serge-sans-paille
Copy link
Collaborator

Hey @anutosh491 can you add some testing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants