Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
15 changes: 15 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4426,6 +4426,21 @@ the configuration (without a prefix: ``Auto``).
#endif
#endif

* ``PPDIS_Leave`` (in configuration: ``Leave``)
Leaves indentation of directives as-is.

.. note::

Ignores ``PPIndentWidth``.

.. code-block:: c++

#if FOO
#if BAR
#include <foo>
#endif
#endif



.. _IndentRequiresClause:
Expand Down
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ clang-format
- Add ``SpaceInEmptyBraces`` option and set it to ``Always`` for WebKit style.
- Add ``NumericLiteralCase`` option for enforcing character case in numeric
literals.
- Add ``Leave`` suboption to ``IndentPPDirectives``.

libclang
--------
Expand Down
14 changes: 13 additions & 1 deletion clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -2976,7 +2976,19 @@ struct FormatStyle {
/// #endif
/// #endif
/// \endcode
PPDIS_BeforeHash
PPDIS_BeforeHash,
/// Leaves indentation of directives as-is.
/// \note
/// Ignores ``PPIndentWidth``.
/// \endnote
/// \code
/// #if FOO
/// #if BAR
/// #include <foo>
/// #endif
/// #endif
/// \endcode
PPDIS_Leave
};

/// The preprocessor directive indenting style to use.
Expand Down
24 changes: 13 additions & 11 deletions clang/lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,19 +780,21 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,

// Indent preprocessor directives after the hash if required.
int PPColumnCorrection = 0;
if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash &&
Previous.is(tok::hash) && State.FirstIndent > 0 &&
&Previous == State.Line->First &&
if (&Previous == State.Line->First && Previous.is(tok::hash) &&
(State.Line->Type == LT_PreprocessorDirective ||
State.Line->Type == LT_ImportStatement)) {
Spaces += State.FirstIndent;

// For preprocessor indent with tabs, State.Column will be 1 because of the
// hash. This causes second-level indents onward to have an extra space
// after the tabs. We avoid this misalignment by subtracting 1 from the
// column value passed to replaceWhitespace().
if (Style.UseTab != FormatStyle::UT_Never)
PPColumnCorrection = -1;
if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash) {
Spaces += State.FirstIndent;

// For preprocessor indent with tabs, State.Column will be 1 because of
// the hash. This causes second-level indents onward to have an extra
// space after the tabs. We avoid this misalignment by subtracting 1 from
// the column value passed to replaceWhitespace().
if (Style.UseTab != FormatStyle::UT_Never)
PPColumnCorrection = -1;
} else if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave) {
Spaces += Current.OriginalColumn - Previous.OriginalColumn - 1;
}
}

if (!DryRun) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
IO.enumCase(Value, "BeforeHash", FormatStyle::PPDIS_BeforeHash);
IO.enumCase(Value, "Leave", FormatStyle::PPDIS_Leave);
}
};

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3627,7 +3627,7 @@ void TokenAnnotator::setCommentLineLevels(
// Align comments for preprocessor lines with the # in column 0 if
// preprocessor lines are not indented. Otherwise, align with the next
// line.
Line->Level = Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
Line->Level = Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
PPDirectiveOrImportStmt
? 0
: NextNonCommentLine->Level;
Expand Down
16 changes: 11 additions & 5 deletions clang/lib/Format/UnwrappedLineFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,16 @@ class LevelIndentTracker {
// having the right size in adjustToUnmodifiedline.
if (Line.Level >= IndentForLevel.size())
IndentForLevel.resize(Line.Level + 1, -1);
if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
(Line.InPPDirective ||
(Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
Line.Type == LT_CommentAbovePPDirective))) {
if (Style.IndentPPDirectives == FormatStyle::PPDIS_Leave &&
(Line.InPPDirective || Line.Type == LT_CommentAbovePPDirective)) {
Indent = Line.InMacroBody
? (Line.Level - Line.PPLevel) * Style.IndentWidth +
AdditionalIndent
: Line.First->OriginalColumn;
} else if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
(Line.InPPDirective ||
(Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
Line.Type == LT_CommentAbovePPDirective))) {
unsigned PPIndentWidth =
(Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
Indent = Line.InMacroBody
Expand Down Expand Up @@ -1656,7 +1662,7 @@ void UnwrappedLineFormatter::formatFirstToken(
// Preprocessor directives get indented before the hash only if specified. In
// Javascript import statements are indented like normal statements.
if (!Style.isJavaScript() &&
Style.IndentPPDirectives != FormatStyle::PPDIS_BeforeHash &&
Style.IndentPPDirectives < FormatStyle::PPDIS_BeforeHash &&
(Line.Type == LT_PreprocessorDirective ||
Line.Type == LT_ImportStatement)) {
Indent = 0;
Expand Down
9 changes: 6 additions & 3 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,17 @@ UnwrappedLineParser::UnwrappedLineParser(
LangOpts(getFormattingLangOpts(Style)), Keywords(Keywords),
CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None ||
Style.IndentPPDirectives == FormatStyle::PPDIS_Leave
? IG_Rejected
: IG_Inited),
IncludeGuardToken(nullptr), FirstStartColumn(FirstStartColumn),
Macros(Style.Macros, SourceMgr, Style, Allocator, IdentTable) {}

void UnwrappedLineParser::reset() {
PPBranchLevel = -1;
IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None
IncludeGuard = Style.IndentPPDirectives == FormatStyle::PPDIS_None ||
Style.IndentPPDirectives == FormatStyle::PPDIS_Leave
? IG_Rejected
: IG_Inited;
IncludeGuardToken = nullptr;
Expand Down Expand Up @@ -1140,7 +1142,8 @@ void UnwrappedLineParser::parsePPEndIf() {
// If the #endif of a potential include guard is the last thing in the file,
// then we found an include guard.
if (IncludeGuard == IG_Defined && PPBranchLevel == -1 && Tokens->isEOF() &&
Style.IndentPPDirectives != FormatStyle::PPDIS_None) {
Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
Style.IndentPPDirectives != FormatStyle::PPDIS_Leave) {
IncludeGuard = IG_Found;
}
}
Expand Down
71 changes: 71 additions & 0 deletions clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5564,6 +5564,63 @@ TEST_F(FormatTest, IndentsPPDirectiveWithPPIndentWidth) {
" }",
style);

style.IndentPPDirectives = FormatStyle::PPDIS_Leave;
style.IndentWidth = 4;
verifyNoChange("#ifndef foo\n"
"#define foo\n"
"if (emacs) {\n"
"#ifdef is\n"
"#define lit \\\n"
" if (af) { \\\n"
" return duh(); \\\n"
" }\n"
"#endif\n"
"}\n"
"#endif",
style);
verifyNoChange("#ifndef foo\n"
" #define foo\n"
"if (emacs) {\n"
" #ifdef is\n"
"#define lit \\\n"
" if (af) { \\\n"
" return duh(); \\\n"
" }\n"
" #endif\n"
"}\n"
"#endif",
style);
verifyNoChange(" #ifndef foo\n"
"# define foo\n"
"if (emacs) {\n"
"#ifdef is\n"
" # define lit \\\n"
" if (af) { \\\n"
" return duh(); \\\n"
" }\n"
"#endif\n"
"}\n"
" #endif",
style);
verifyNoChange("#ifdef foo\n"
"#else\n"
"/* This is a comment */\n"
"#ifdef BAR\n"
"#endif\n"
"#endif",
style);

style.IndentWidth = 1;
style.PPIndentWidth = 4;
verifyNoChange("# if 1\n"
" #define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }\n"
"# endif",
style);

style.IndentWidth = 4;
style.PPIndentWidth = 1;
style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash;
Expand Down Expand Up @@ -25597,6 +25654,20 @@ TEST_F(FormatTest, SkipMacroDefinitionBody) {
"a",
Style);

Style.IndentPPDirectives = FormatStyle::PPDIS_Leave;
verifyNoChange("#if A\n"
"#define A a\n"
"#endif",
Style);
verifyNoChange("#if A\n"
" #define A a\n"
"#endif",
Style);
verifyNoChange("#if A\n"
"# define A a\n"
"#endif",
Style);

// Adjust indendations but don't change the definition.
Style.IndentPPDirectives = FormatStyle::PPDIS_None;
verifyNoChange("#if A\n"
Expand Down