Skip to content

Commit bc40b76

Browse files
committed
[clang-format] Correctly parse C99 digraphs: "<:", ":>", "<%", "%>", "%:", "%:%:".
Fixes #31592. This commits enables lexing of digraphs in C++11 and onwards. Enabling them in C++03 is error-prone, as it would unconditionally treat sequences like "<:" as digraphs, even if they are followed by a single colon, e.g. "<::" would be treated as "[:" instead of "<" followed by "::". Lexing in C++11 doesn't have this problem as it looks ahead the following token. The relevant excerpt from Lexer::LexTokenInternal: ``` // C++0x [lex.pptoken]p3: // Otherwise, if the next three characters are <:: and the subsequent // character is neither : nor >, the < is treated as a preprocessor // token by itself and not as the first character of the alternative // token <:. ``` Also, note that both clang and gcc turn on digraphs by default (-fdigraphs), so clang-format should match this behaviour. Reviewed By: MyDeveloperDay, HazardyKnusperkeks, owenpan Differential Revision: https://reviews.llvm.org/D118706
1 parent 8a12cae commit bc40b76

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed

clang/lib/Format/Format.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3242,6 +3242,10 @@ LangOptions getFormattingLangOpts(const FormatStyle &Style) {
32423242
LangOpts.CPlusPlus17 = LexingStd >= FormatStyle::LS_Cpp17;
32433243
LangOpts.CPlusPlus20 = LexingStd >= FormatStyle::LS_Cpp20;
32443244
LangOpts.Char8 = LexingStd >= FormatStyle::LS_Cpp20;
3245+
// Turning on digraphs in standards before C++0x is error-prone, because e.g.
3246+
// the sequence "<::" will be unconditionally treated as "[:".
3247+
// Cf. Lexer::LexTokenInternal.
3248+
LangOpts.Digraphs = LexingStd >= FormatStyle::LS_Cpp11;
32453249

32463250
LangOpts.LineComment = 1;
32473251
bool AlternativeOperators = Style.isCpp();

clang/unittests/Format/FormatTest.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24219,6 +24219,16 @@ TEST_F(FormatTest, AlignAfterOpenBracketBlockIndentForStatement) {
2421924219
Style);
2422024220
}
2422124221

24222+
TEST_F(FormatTest, UnderstandsDigraphs) {
24223+
verifyFormat("int arr<:5:> = {};");
24224+
verifyFormat("int arr[5] = <%%>;");
24225+
verifyFormat("int arr<:::qualified_variable:> = {};");
24226+
verifyFormat("int arr[::qualified_variable] = <%%>;");
24227+
verifyFormat("%:include <header>");
24228+
verifyFormat("%:define A x##y");
24229+
verifyFormat("#define A x%:%:y");
24230+
}
24231+
2422224232
} // namespace
2422324233
} // namespace format
2422424234
} // namespace clang

0 commit comments

Comments
 (0)