[clang] [clang-format]: Treat #pragma once as include guard for IndentPPDirectives (PR #135443)

via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 11 14:39:38 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: saltyJeff (saltyJeff)

<details>
<summary>Changes</summary>

Summary:
This patch fixes the behavior of IndentPPDirectives so that `#pragma once`'s are treated as part of include guards, and therefore the `#define` in the guard will not be indented.

Sample:
```
    #pragma once
    #ifndef HEADER_H
    #define HEADER_H
    code();
    #endif
```

Previous formatting behavior:
```
    #pragma once
    #ifndef HEADER_H
        #define HEADER_H
    code();
    #endif
```

Patched behavior:
```
    #pragma once
    #ifndef HEADER_H
    #define HEADER_H
    code();
    #endif
```

Details:
Previously, a `#ifndef` could only start an include guard if all the lines above it were comments. This patch changes this check to see if all the lines above the `#ifndef` are comments OR `#pragma once`.

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


2 Files Affected:

- (modified) clang/lib/Format/UnwrappedLineParser.cpp (+9-2) 
- (modified) clang/unittests/Format/FormatTest.cpp (+11-1) 


``````````diff
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 60f4f30623baa..4fd16139323ca 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1102,11 +1102,18 @@ void UnwrappedLineParser::parsePPIf(bool IfDef) {
   conditionalCompilationStart(Unreachable);
   FormatToken *IfCondition = FormatTok;
   // If there's a #ifndef on the first line, and the only lines before it are
-  // comments, it could be an include guard.
+  // comments or #pragma once, it could be an include guard.
   bool MaybeIncludeGuard = IfNDef;
   if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
     for (auto &Line : Lines) {
-      if (Line.Tokens.front().Tok->isNot(tok::comment)) {
+      bool LineIsComment = Line.Tokens.front().Tok->is(tok::comment);
+      auto TokenIterator = Line.Tokens.begin();
+      bool LineIsPragmaOnce = Line.Tokens.size() >= 3 &&
+                              TokenIterator->Tok->is(tok::hash) &&
+                              (++TokenIterator)->Tok->is(tok::pp_pragma) &&
+                              (++TokenIterator)->Tok->TokenText == "once";
+
+      if (!LineIsComment && !LineIsPragmaOnce) {
         MaybeIncludeGuard = false;
         IncludeGuard = IG_Rejected;
         break;
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index f0e67c604cc4b..2c4eb7d9d581e 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -6223,6 +6223,16 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
                "int z;\n"
                "#endif",
                Style);
+  // Treat #pragma once as part of an include guard.
+  verifyFormat("#pragma once\n"
+               "#ifndef HEADER_H\n"
+               "#define HEADER_H\n"
+               "#ifdef NOT_GUARD\n"
+               "#  define NOT_GUARD\n"
+               "#endif\n"
+               "code();\n"
+               "#endif",
+               Style);
   // FIXME: This doesn't handle the case where there's code between the
   // #ifndef and #define but all other conditions hold. This is because when
   // the #define line is parsed, UnwrappedLineParser::Lines doesn't hold the
@@ -6239,7 +6249,7 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
                "#endif",
                Style);
   // FIXME: This doesn't handle cases where legitimate preprocessor lines may
-  // be outside an include guard. Examples are #pragma once and
+  // be outside an include guard. Examples include
   // #pragma GCC diagnostic, or anything else that does not change the meaning
   // of the file if it's included multiple times.
   verifyFormat("#ifdef WIN32\n"

``````````

</details>


https://github.com/llvm/llvm-project/pull/135443


More information about the cfe-commits mailing list