[clang] 2444c4a - [clang-repl] add %help, documentation, and tests for %commands (#150348)

via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 5 06:50:51 PDT 2025


Author: Aaron Danen
Date: 2025-08-05T14:50:48+01:00
New Revision: 2444c4a69861c643c6628b736affe5861cc79080

URL: https://github.com/llvm/llvm-project/commit/2444c4a69861c643c6628b736affe5861cc79080
DIFF: https://github.com/llvm/llvm-project/commit/2444c4a69861c643c6628b736affe5861cc79080.diff

LOG: [clang-repl] add %help, documentation, and tests for %commands (#150348)

1. Added %commands to documentation
2. Added %help command to clang repl
3. Expanded parsing to throw unique errors in the case of users entering
an invalid %command or using %lib without an argument
4. Added tests to check the behvaior of %help, %lib, and bad %commands

Added: 
    clang/test/Interpreter/bad_percent_command.cpp
    clang/test/Interpreter/dynamic-library-bad-args.cpp
    clang/test/Interpreter/help.cpp

Modified: 
    clang/docs/ClangRepl.rst
    clang/tools/clang-repl/ClangRepl.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ClangRepl.rst b/clang/docs/ClangRepl.rst
index 5399036c123fb..e7e86304f2561 100644
--- a/clang/docs/ClangRepl.rst
+++ b/clang/docs/ClangRepl.rst
@@ -159,8 +159,29 @@ Lamdas:
    clang-repl> welcome();
    Welcome to REPL
 
-Using Dynamic Library:
-======================
+Comments:
+=========
+
+.. code-block:: text
+
+   clang-repl> // Comments in Clang-Repl
+   clang-repl> /* Comments in Clang-Repl */
+
+Built in Commands:
+==================
+clang-repl has some special commands that are of the form ``%<something>``. To list all these commands, use the ``%help`` command:
+
+Help:
+-----
+The ``%help`` command lists all built in clang-repl commands.
+
+.. code-block:: text
+
+   clang-repl> %help
+
+Using Dynamic Libraries:
+------------------------
+The ``%lib`` command links a dynamic library.
 
 .. code-block:: text
 
@@ -189,21 +210,30 @@ Using Dynamic Library:
    clang++-17  -c -o print.o print.cpp
    clang-17 -shared print.o -o print.so
 
-Comments:
-=========
+Undo:
+-----
+The ``%undo`` command undoes the previous input.
 
 .. code-block:: text
 
-   clang-repl> // Comments in Clang-Repl
-   clang-repl> /* Comments in Clang-Repl */
+   clang-repl> int a = 1; a
+   (int) 1
+   clang-repl> %undo
+   clang-repl> a
+   In file included from <<< inputs >>>:1:
+   input_line_2:1:1: error: use of undeclared identifier 'a'
+   1 | a
+   * | ^
+   error: Parsing failed.
 
-
-Closure or Termination:
-=======================
+Quit:
+-----
+The ``%quit`` command terminates clang-repl.
 
 .. code-block:: text
 
-   clang-repl>%quit
+   clang-repl> %quit
+
 
 
 Just like Clang, Clang-Repl can be integrated in existing applications as a library

diff  --git a/clang/test/Interpreter/bad_percent_command.cpp b/clang/test/Interpreter/bad_percent_command.cpp
new file mode 100644
index 0000000000000..207570cac1873
--- /dev/null
+++ b/clang/test/Interpreter/bad_percent_command.cpp
@@ -0,0 +1,4 @@
+// RUN: cat %s | clang-repl 2>&1 | FileCheck %s
+%foobar
+// CHECK: Invalid % command "%foobar", use "%help" to list commands
+%quit

diff  --git a/clang/test/Interpreter/dynamic-library-bad-args.cpp b/clang/test/Interpreter/dynamic-library-bad-args.cpp
new file mode 100644
index 0000000000000..f48a2657beacc
--- /dev/null
+++ b/clang/test/Interpreter/dynamic-library-bad-args.cpp
@@ -0,0 +1,4 @@
+// RUN: cat %s | clang-repl 2>&1 | FileCheck %s
+%lib
+// CHECK: %lib expects 1 argument: the path to a dynamic library
+%quit

diff  --git a/clang/test/Interpreter/help.cpp b/clang/test/Interpreter/help.cpp
new file mode 100644
index 0000000000000..70f114f4644e3
--- /dev/null
+++ b/clang/test/Interpreter/help.cpp
@@ -0,0 +1,7 @@
+// RUN: cat %s | clang-repl | FileCheck %s
+%help
+// CHECK: %help   list clang-repl %commands
+// CHECK-NEXT: %undo   undo the previous input
+// CHECK-NEXT: %lib  <path>  link a dynamic library
+// CHECK-NEXT: %quit   exit clang-repl
+%quit

diff  --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp
index 54b27782d3db3..b666959c33b73 100644
--- a/clang/tools/clang-repl/ClangRepl.cpp
+++ b/clang/tools/clang-repl/ClangRepl.cpp
@@ -28,6 +28,7 @@
 #include "llvm/Support/ManagedStatic.h" // llvm_shutdown
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Host.h"
 #include <optional>
 
@@ -364,15 +365,34 @@ int main(int argc, const char **argv) {
       }
 
       Input += L;
+      // If we add more % commands, there should be better architecture than
+      // this.
       if (Input == R"(%quit)") {
         break;
       }
       if (Input == R"(%undo)") {
         if (auto Err = Interp->Undo())
           llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
+      } else if (Input == R"(%help)") {
+        llvm::outs() << "%help\t\tlist clang-repl %commands\n"
+                     << "%undo\t\tundo the previous input\n"
+                     << "%lib\t<path>\tlink a dynamic library\n"
+                     << "%quit\t\texit clang-repl\n";
+      } else if (Input == R"(%lib)") {
+        auto Err = llvm::make_error<llvm::StringError>(
+            "%lib expects 1 argument: the path to a dynamic library\n",
+            std::error_code());
+        llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
       } else if (Input.rfind("%lib ", 0) == 0) {
         if (auto Err = Interp->LoadDynamicLibrary(Input.data() + 5))
           llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
+      } else if (Input[0] == '%') {
+        auto Err = llvm::make_error<llvm::StringError>(
+            llvm::formatv(
+                "Invalid % command \"{0}\", use \"%help\" to list commands\n",
+                Input),
+            std::error_code());
+        llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
       } else if (auto Err = Interp->ParseAndExecute(Input)) {
         llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
       }


        


More information about the cfe-commits mailing list