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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits