Skip to content

Instantly share code, notes, and snippets.

@kamack38
Last active October 25, 2025 13:47
Show Gist options
  • Select an option

  • Save kamack38/0cea4932fe7d4a318e6558fb53a05fd5 to your computer and use it in GitHub Desktop.

Select an option

Save kamack38/0cea4932fe7d4a318e6558fb53a05fd5 to your computer and use it in GitHub Desktop.
Bring `--fallback-style` to parity with `--style`
From 2fb4c48d4b6f8c52e16d0a0cbfa38cf747fddc12 Mon Sep 17 00:00:00 2001
From: kamack38 <[email protected]>
Date: Sat, 4 Oct 2025 21:09:50 +0200
Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20new=20option?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
clang/docs/ClangFormat.rst | 17 +++++---
clang/include/clang/Format/Format.h | 5 +++
clang/lib/Format/Format.cpp | 51 +++++++++++++++++++++++-
clang/tools/clang-format/ClangFormat.cpp | 6 +--
4 files changed, 67 insertions(+), 12 deletions(-)
diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e50..b1aba5231 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -62,11 +62,18 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code.
--dump-config - Dump configuration options to stdout and exit.
Can be used with -style option.
--fail-on-incomplete-format - If set, fail with exit code 1 on incomplete format.
- --fallback-style=<string> - The name of the predefined style used as a
- fallback in case clang-format is invoked with
- -style=file, but can not find the .clang-format
- file to use. Defaults to 'LLVM'.
- Use -fallback-style=none to skip formatting.
+ --fallback-style=<string> - Set coding style used as a fallback in case
+ clang-format is invoked with --style=file, but
+ can not find the .clang-format file to use.
+ <string> can be:
+ 1. A preset: LLVM, GNU, Google, Chromium, Microsoft,
+ Mozilla, WebKit.
+ --fallback-style=LLVM is the default.
+ 2. 'file:<format_file_path>' to explicitly specify
+ the configuration file.
+ 3. "{key: value, ...}" to set specific parameters, e.g.:
+ --fallback-style="{BasedOnStyle: llvm, IndentWidth: 8}"
+ 4. --fallback-style=none to skip formatting.
--ferror-limit=<uint> - Set the maximum number of clang-format errors to emit
before stopping (0 = no limit).
Used only with --dry-run or -n
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 3df5b9265..c24902a4c 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -5871,6 +5871,11 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style = getLLVMStyle());
/// of ``getStyle()``.
extern const char *StyleOptionHelpDescription;
+/// Description to be used for help text for a ``llvm::cl`` option for
+/// specifying fallback format style. The description is closely related to the
+/// operation of ``getStyle()``.
+extern const char *FallbackStyleOptionHelpDescription;
+
/// The suggested format style to use by default. This allows tools using
/// ``getStyle`` to have a consistent default style.
/// Different builds can modify the value to the preferred styles.
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 686e54128..1921307b2 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -4181,6 +4181,20 @@ const char *StyleOptionHelpDescription =
"4. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
" --style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
+const char *FallbackStyleOptionHelpDescription =
+ "Set coding style used as a fallback in case\n"
+ "clang-format is invoked with --style=file, but\n"
+ "can not find the .clang-format file to use.\n"
+ "<string> can be:\n"
+ "1. A preset: LLVM, GNU, Google, Chromium, Microsoft,\n"
+ " Mozilla, WebKit.\n"
+ " --fallback-style=LLVM is the default.\n"
+ "2. 'file:<format_file_path>' to explicitly specify\n"
+ " the configuration file.\n"
+ "3. \"{key: value, ...}\" to set specific parameters, e.g.:\n"
+ " --fallback-style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"\n"
+ "4. --fallback-style=none to skip formatting.";
+
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
if (FileName.ends_with(".c"))
return FormatStyle::LK_C;
@@ -4279,6 +4293,7 @@ FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
// Update StyleOptionHelpDescription above when changing this.
const char *DefaultFormatStyle = "file";
+// Update FallbackStyleOptionHelpDescription above when changing this.
const char *DefaultFallbackStyle = "LLVM";
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
@@ -4305,8 +4320,6 @@ Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
llvm::SourceMgr::DiagHandlerTy DiagHandler) {
FormatStyle Style = getLLVMStyle(guessLanguage(FileName, Code));
FormatStyle FallbackStyle = getNoStyle();
- if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
- return make_string_error("Invalid fallback style: " + FallbackStyleName);
SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 1> ChildFormatTextToApply;
@@ -4464,6 +4477,40 @@ Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
applyChildFormatTexts(&FallbackStyle);
}
+ if (FallbackStyleName.starts_with("{")) {
+ // Parse YAML/JSON fallback style from the command line.
+ // We don't care about inheriting parent style because when fallback style
+ // is used it doesn't exist
+ StringRef Source = "<command-line>";
+ if (std::error_code ec = parseConfiguration(
+ llvm::MemoryBufferRef(FallbackStyleName, Source), &FallbackStyle,
+ AllowUnknownOptions, DiagHandler)) {
+ return make_string_error("Error parsing -fallback-style: " +
+ ec.message());
+ }
+
+ return FallbackStyle;
+ }
+
+ if (FallbackStyleName.starts_with_insensitive("file:")) {
+ auto ConfigFile = FallbackStyleName.substr(5);
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
+ loadAndParseConfigFile(ConfigFile, FS, &FallbackStyle,
+ AllowUnknownOptions, DiagHandler, IsDotHFile);
+ if (auto EC = Text.getError()) {
+ return make_string_error("Error reading " + ConfigFile + ": " +
+ EC.message());
+ }
+
+ LLVM_DEBUG(llvm::dbgs()
+ << "Using configuration file " << ConfigFile << "\n");
+
+ return FallbackStyle;
+ }
+
+ if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
+ return make_string_error("Invalid fallback style: " + FallbackStyleName);
+
return FallbackStyle;
}
diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp
index 5f6502f7f..8ffded8af 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -68,11 +68,7 @@ static cl::opt<std::string>
cl::cat(ClangFormatCategory));
static cl::opt<std::string>
FallbackStyle("fallback-style",
- cl::desc("The name of the predefined style used as a\n"
- "fallback in case clang-format is invoked with\n"
- "-style=file, but can not find the .clang-format\n"
- "file to use. Defaults to 'LLVM'.\n"
- "Use -fallback-style=none to skip formatting."),
+ cl::desc(clang::format::FallbackStyleOptionHelpDescription),
cl::init(clang::format::DefaultFallbackStyle),
cl::cat(ClangFormatCategory));
--
2.51.0
@kamack38
Copy link
Author

kamack38 commented Oct 4, 2025

For llvm 20.1.8 remove the argument IsDotHFile.

@kamack38
Copy link
Author

kamack38 commented Oct 4, 2025

This fails the 9.1.1 test in ConfigParseTest.cpp due to incorrect inherit parent config handling. Otherwise, it works with clang-format and clangd also correctly forwards given fallback style and formats the file as expected.

@kamack38
Copy link
Author

kamack38 commented Oct 4, 2025

When building the Cachyos PKGBUILD use

makepkg -si --skippgpcheck --nocheck 

@kamack38
Copy link
Author

kamack38 commented Oct 4, 2025

Build took around 2h on my Ryzen 7 5800H.

@kamack38
Copy link
Author

If you want to package the package when errors exist, run makepkg -si --skippgpcheck --repackage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment