Skip to content

Conversation

anutosh491
Copy link
Member

  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
Member 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
Member 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?

@anutosh491
Copy link
Member Author

Hey @serge-sans-paille

Sorry for missing your last reply completely. Thanks for going through it in the first place :)

I've added a small test to get us started

https://github.com/llvm/llvm-project/pull/132670/files#diff-339061dce5c23e378165cd07b0511a10e5f921803cb8d7ac76a220cdb3eb54a8

We would get the following as a whole

(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

But I am just checking the presence of the string "Version displayed" cause the version number and the output through help is subject to change in the future.

@anutosh491
Copy link
Member Author

Hey @serge-sans-paille ,

Gentle ping. This should be ready from my side. Would be great if you could review it anytime soon.

@anutosh491
Copy link
Member Author

Running this test after building ClangReplInterpreterTests.js

[ RUN      ] InterpreterTest.EmscriptenExceptionHandling
clang version 22.0.0git ([email protected]:anutosh491/llvm-project.git e5bbaa9c8fb6e06dbcbd39404039cc5d31df4410)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: 
 "" -cc1 -triple wasm32-unknown-emscripten -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name "<<< inputs >>>" -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/ -v -fcoverage-compilation-dir=/ -resource-dir lib/clang/22 -internal-isystem lib/clang/22/include -internal-isystem /include/wasm32-emscripten -internal-isystem /include -std=c++20 -fdeprecated-macro -ferror-limit 19 -fmessage-length=80 -fvisibility=default -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fincremental-extensions -mllvm -enable-emscripten-cxx-exceptions -mllvm -enable-emscripten-sjlj -o "<<< inputs >>>.o" -x c++ "<<< inputs >>>"
clang -cc1 version 22.0.0git based upon LLVM 22.0.0git default target wasm32-unknown-emscripten
ignoring nonexistent directory "lib/clang/22/include"
ignoring nonexistent directory "/include/wasm32-emscripten"
ignoring nonexistent directory "/include"
#include "..." search starts here:
End of search list.
[       OK ] InterpreterTest.EmscriptenExceptionHandling (336 ms)
[----------] 1 test from InterpreterTest (336 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (348 ms total)
[  PASSED  ] 1 test.

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