Skip to content

Commit d4e3ae0

Browse files
committed
[clang-format]: Treat #pragma once as include guard for IndentPPDirectives
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``.
1 parent 70627af commit d4e3ae0

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,11 +1102,18 @@ void UnwrappedLineParser::parsePPIf(bool IfDef) {
11021102
conditionalCompilationStart(Unreachable);
11031103
FormatToken *IfCondition = FormatTok;
11041104
// If there's a #ifndef on the first line, and the only lines before it are
1105-
// comments, it could be an include guard.
1105+
// comments or #pragma once, it could be an include guard.
11061106
bool MaybeIncludeGuard = IfNDef;
11071107
if (IncludeGuard == IG_Inited && MaybeIncludeGuard) {
11081108
for (auto &Line : Lines) {
1109-
if (Line.Tokens.front().Tok->isNot(tok::comment)) {
1109+
bool LineIsComment = Line.Tokens.front().Tok->is(tok::comment);
1110+
auto TokenIterator = Line.Tokens.begin();
1111+
bool LineIsPragmaOnce = Line.Tokens.size() >= 3 &&
1112+
TokenIterator->Tok->is(tok::hash) &&
1113+
(++TokenIterator)->Tok->is(tok::pp_pragma) &&
1114+
(++TokenIterator)->Tok->TokenText == "once";
1115+
1116+
if (!LineIsComment && !LineIsPragmaOnce) {
11101117
MaybeIncludeGuard = false;
11111118
IncludeGuard = IG_Rejected;
11121119
break;

clang/unittests/Format/FormatTest.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6223,6 +6223,16 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
62236223
"int z;\n"
62246224
"#endif",
62256225
Style);
6226+
// Treat #pragma once as part of an include guard.
6227+
verifyFormat("#pragma once\n"
6228+
"#ifndef HEADER_H\n"
6229+
"#define HEADER_H\n"
6230+
"#ifdef NOT_GUARD\n"
6231+
"# define NOT_GUARD\n"
6232+
"#endif\n"
6233+
"code();\n"
6234+
"#endif",
6235+
Style);
62266236
// FIXME: This doesn't handle the case where there's code between the
62276237
// #ifndef and #define but all other conditions hold. This is because when
62286238
// the #define line is parsed, UnwrappedLineParser::Lines doesn't hold the
@@ -6239,7 +6249,7 @@ TEST_F(FormatTest, IndentPreprocessorDirectives) {
62396249
"#endif",
62406250
Style);
62416251
// FIXME: This doesn't handle cases where legitimate preprocessor lines may
6242-
// be outside an include guard. Examples are #pragma once and
6252+
// be outside an include guard. Examples include
62436253
// #pragma GCC diagnostic, or anything else that does not change the meaning
62446254
// of the file if it's included multiple times.
62456255
verifyFormat("#ifdef WIN32\n"

0 commit comments

Comments
 (0)