Skip to content

[clang-format] Handle .h files for LK_C and LK_ObjC #141714

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

Merged
merged 1 commit into from
May 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -5536,7 +5536,7 @@ struct FormatStyle {
parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle *Style,
bool AllowUnknownOptions,
llvm::SourceMgr::DiagHandlerTy DiagHandler,
void *DiagHandlerCtxt);
void *DiagHandlerCtxt, bool IsDotHFile);
};

/// Returns a format style complying with the LLVM coding standards:
Expand Down Expand Up @@ -5602,13 +5602,15 @@ std::error_code
parseConfiguration(llvm::MemoryBufferRef Config, FormatStyle *Style,
bool AllowUnknownOptions = false,
llvm::SourceMgr::DiagHandlerTy DiagHandler = nullptr,
void *DiagHandlerCtx = nullptr);
void *DiagHandlerCtx = nullptr, bool IsDotHFile = false);

/// Like above but accepts an unnamed buffer.
inline std::error_code parseConfiguration(StringRef Config, FormatStyle *Style,
bool AllowUnknownOptions = false) {
bool AllowUnknownOptions = false,
bool IsDotHFile = false) {
return parseConfiguration(llvm::MemoryBufferRef(Config, "YAML"), Style,
AllowUnknownOptions);
AllowUnknownOptions, /*DiagHandler=*/nullptr,
/*DiagHandlerCtx=*/nullptr, IsDotHFile);
}

/// Gets configuration in a YAML string.
Expand Down
18 changes: 13 additions & 5 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2108,7 +2108,7 @@ ParseError validateQualifierOrder(FormatStyle *Style) {
std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
FormatStyle *Style, bool AllowUnknownOptions,
llvm::SourceMgr::DiagHandlerTy DiagHandler,
void *DiagHandlerCtxt) {
void *DiagHandlerCtxt, bool IsDotHFile) {
assert(Style);
FormatStyle::LanguageKind Language = Style->Language;
assert(Language != FormatStyle::LK_None);
Expand Down Expand Up @@ -2155,6 +2155,10 @@ std::error_code parseConfiguration(llvm::MemoryBufferRef Config,
// For backward compatibility.
(Lang == FormatStyle::LK_Cpp && Language == FormatStyle::LK_C)) {
LanguageFound = true;
} else if (IsDotHFile && Language == FormatStyle::LK_Cpp &&
(Lang == FormatStyle::LK_C || Lang == FormatStyle::LK_ObjC)) {
Language = Lang;
LanguageFound = true;
}
}
if (!LanguageFound) {
Expand Down Expand Up @@ -4177,13 +4181,15 @@ const char *DefaultFallbackStyle = "LLVM";
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
loadAndParseConfigFile(StringRef ConfigFile, llvm::vfs::FileSystem *FS,
FormatStyle *Style, bool AllowUnknownOptions,
llvm::SourceMgr::DiagHandlerTy DiagHandler) {
llvm::SourceMgr::DiagHandlerTy DiagHandler,
bool IsDotHFile) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
FS->getBufferForFile(ConfigFile.str());
if (auto EC = Text.getError())
return EC;
if (auto EC = parseConfiguration(*Text.get(), Style, AllowUnknownOptions,
DiagHandler)) {
DiagHandler, /*DiagHandlerCtx=*/nullptr,
IsDotHFile)) {
return EC;
}
return Text;
Expand Down Expand Up @@ -4221,13 +4227,15 @@ Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
FS = llvm::vfs::getRealFileSystem().get();
assert(FS);

const bool IsDotHFile = FileName.ends_with(".h");

// User provided clang-format file using -style=file:path/to/format/file.
if (!Style.InheritsParentConfig &&
StyleName.starts_with_insensitive("file:")) {
auto ConfigFile = StyleName.substr(5);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
DiagHandler);
DiagHandler, IsDotHFile);
if (auto EC = Text.getError()) {
return make_string_error("Error reading " + ConfigFile + ": " +
EC.message());
Expand Down Expand Up @@ -4303,7 +4311,7 @@ Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,

llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
loadAndParseConfigFile(ConfigFile, FS, &Style, AllowUnknownOptions,
DiagHandler);
DiagHandler, IsDotHFile);
if (auto EC = Text.getError()) {
if (EC != ParseError::Unsuitable) {
return make_string_error("Error reading " + ConfigFile + ": " +
Expand Down
18 changes: 18 additions & 0 deletions clang/unittests/Format/ConfigParseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,24 @@ TEST(ConfigParseTest, AllowCppForC) {
ParseError::Success);
}

TEST(ConfigParseTest, HandleNonCppDotHFile) {
FormatStyle Style = {};
Style.Language = FormatStyle::LK_Cpp;
EXPECT_EQ(parseConfiguration("Language: C", &Style,
/*AllowUnknownOptions=*/false,
/*IsDotHFile=*/true),
ParseError::Success);
EXPECT_EQ(Style.Language, FormatStyle::LK_C);

Style = {};
Style.Language = FormatStyle::LK_Cpp;
EXPECT_EQ(parseConfiguration("Language: ObjC", &Style,
/*AllowUnknownOptions=*/false,
/*IsDotHFile=*/true),
ParseError::Success);
EXPECT_EQ(Style.Language, FormatStyle::LK_ObjC);
}

TEST(ConfigParseTest, UsesLanguageForBasedOnStyle) {
FormatStyle Style = {};
Style.Language = FormatStyle::LK_JavaScript;
Expand Down