blob: 31f40b167081e3bdf77c27ee2a426c314d5a4ef4 [file] [log] [blame]
//===- unittest/Format/FormatTest.cpp - Formatting unit tests -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/Format/Format.h"
#include "../Tooling/ReplacementTest.h"
#include "FormatTestUtils.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
#define DEBUG_TYPE "format-test"
using clang::tooling::ReplacementTest;
using clang::tooling::toReplacements;
namespace clang {
namespace format {
namespace {
FormatStyle getGoogleStyle() { return getGoogleStyle(FormatStyle::LK_Cpp); }
class FormatTest : public ::testing::Test {
protected:
enum StatusCheck {
SC_ExpectComplete,
SC_ExpectIncomplete,
SC_DoNotCheck
};
std::string format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(),
StatusCheck CheckComplete = SC_ExpectComplete) {
LLVM_DEBUG(llvm::errs() << "---\n");
LLVM_DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
FormattingAttemptStatus Status;
tooling::Replacements Replaces =
reformat(Style, Code, Ranges, "<stdin>", &Status);
if (CheckComplete != SC_DoNotCheck) {
bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
<< Code << "\n\n";
}
ReplacementCount = Replaces.size();
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
FormatStyle getStyleWithColumns(FormatStyle Style, unsigned ColumnLimit) {
Style.ColumnLimit = ColumnLimit;
return Style;
}
FormatStyle getLLVMStyleWithColumns(unsigned ColumnLimit) {
return getStyleWithColumns(getLLVMStyle(), ColumnLimit);
}
FormatStyle getGoogleStyleWithColumns(unsigned ColumnLimit) {
return getStyleWithColumns(getGoogleStyle(), ColumnLimit);
}
void verifyFormat(llvm::StringRef Expected, llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
EXPECT_EQ(Expected.str(), format(Expected, Style))
<< "Expected code is not stable";
EXPECT_EQ(Expected.str(), format(Code, Style));
if (Style.Language == FormatStyle::LK_Cpp) {
// Objective-C++ is a superset of C++, so everything checked for C++
// needs to be checked for Objective-C++ as well.
FormatStyle ObjCStyle = Style;
ObjCStyle.Language = FormatStyle::LK_ObjC;
EXPECT_EQ(Expected.str(), format(test::messUp(Code), ObjCStyle));
}
}
void verifyFormat(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
verifyFormat(Code, test::messUp(Code), Style);
}
void verifyIncompleteFormat(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
EXPECT_EQ(Code.str(),
format(test::messUp(Code), Style, SC_ExpectIncomplete));
}
void verifyGoogleFormat(llvm::StringRef Code) {
verifyFormat(Code, getGoogleStyle());
}
void verifyIndependentOfContext(llvm::StringRef text) {
verifyFormat(text);
verifyFormat(llvm::Twine("void f() { " + text + " }").str());
}
/// \brief Verify that clang-format does not crash on the given input.
void verifyNoCrash(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle()) {
format(Code, Style, SC_DoNotCheck);
}
int ReplacementCount;
};
TEST_F(FormatTest, MessUp) {
EXPECT_EQ("1 2 3", test::messUp("1 2 3"));
EXPECT_EQ("1 2 3\n", test::messUp("1\n2\n3\n"));
EXPECT_EQ("a\n//b\nc", test::messUp("a\n//b\nc"));
EXPECT_EQ("a\n#b\nc", test::messUp("a\n#b\nc"));
EXPECT_EQ("a\n#b c d\ne", test::messUp("a\n#b\\\nc\\\nd\ne"));
}
TEST_F(FormatTest, DefaultLLVMStyleIsCpp) {
EXPECT_EQ(FormatStyle::LK_Cpp, getLLVMStyle().Language);
}
TEST_F(FormatTest, LLVMStyleOverride) {
EXPECT_EQ(FormatStyle::LK_Proto,
getLLVMStyle(FormatStyle::LK_Proto).Language);
}
//===----------------------------------------------------------------------===//
// Basic function tests.
//===----------------------------------------------------------------------===//
TEST_F(FormatTest, DoesNotChangeCorrectlyFormattedCode) {
EXPECT_EQ(";", format(";"));
}
TEST_F(FormatTest, FormatsGlobalStatementsAt0) {
EXPECT_EQ("int i;", format(" int i;"));
EXPECT_EQ("\nint i;", format(" \n\t \v \f int i;"));
EXPECT_EQ("int i;\nint j;", format(" int i; int j;"));
EXPECT_EQ("int i;\nint j;", format(" int i;\n int j;"));
}
TEST_F(FormatTest, FormatsUnwrappedLinesAtFirstFormat) {
EXPECT_EQ("int i;", format("int\ni;"));
}
TEST_F(FormatTest, FormatsNestedBlockStatements) {
EXPECT_EQ("{\n {\n {}\n }\n}", format("{{{}}}"));
}
TEST_F(FormatTest, FormatsNestedCall) {
verifyFormat("Method(f1, f2(f3));");
verifyFormat("Method(f1(f2, f3()));");
verifyFormat("Method(f1(f2, (f3())));");
}
TEST_F(FormatTest, NestedNameSpecifiers) {
verifyFormat("vector<::Type> v;");
verifyFormat("::ns::SomeFunction(::ns::SomeOtherFunction())");
verifyFormat("static constexpr bool Bar = decltype(bar())::value;");
verifyFormat("bool a = 2 < ::SomeFunction();");
verifyFormat("ALWAYS_INLINE ::std::string getName();");
verifyFormat("some::string getName();");
}
TEST_F(FormatTest, OnlyGeneratesNecessaryReplacements) {
EXPECT_EQ("if (a) {\n"
" f();\n"
"}",
format("if(a){f();}"));
EXPECT_EQ(4, ReplacementCount);
EXPECT_EQ("if (a) {\n"
" f();\n"
"}",
format("if (a) {\n"
" f();\n"
"}"));
EXPECT_EQ(0, ReplacementCount);
EXPECT_EQ("/*\r\n"
"\r\n"
"*/\r\n",
format("/*\r\n"
"\r\n"
"*/\r\n"));
EXPECT_EQ(0, ReplacementCount);
}
TEST_F(FormatTest, RemovesEmptyLines) {
EXPECT_EQ("class C {\n"
" int i;\n"
"};",
format("class C {\n"
" int i;\n"
"\n"
"};"));
// Don't remove empty lines at the start of namespaces or extern "C" blocks.
EXPECT_EQ("namespace N {\n"
"\n"
"int i;\n"
"}",
format("namespace N {\n"
"\n"
"int i;\n"
"}",
getGoogleStyle()));
EXPECT_EQ("/* something */ namespace N {\n"
"\n"
"int i;\n"
"}",
format("/* something */ namespace N {\n"
"\n"
"int i;\n"
"}",
getGoogleStyle()));
EXPECT_EQ("inline namespace N {\n"
"\n"
"int i;\n"
"}",
format("inline namespace N {\n"
"\n"
"int i;\n"
"}",
getGoogleStyle()));
EXPECT_EQ("/* something */ inline namespace N {\n"
"\n"
"int i;\n"
"}",
format("/* something */ inline namespace N {\n"
"\n"
"int i;\n"
"}",
getGoogleStyle()));
EXPECT_EQ("export namespace N {\n"
"\n"
"int i;\n"
"}",
format("export namespace N {\n"
"\n"
"int i;\n"
"}",
getGoogleStyle()));
EXPECT_EQ("extern /**/ \"C\" /**/ {\n"
"\n"
"int i;\n"
"}",
format("extern /**/ \"C\" /**/ {\n"
"\n"
"int i;\n"
"}",
getGoogleStyle()));
// ...but do keep inlining and removing empty lines for non-block extern "C"
// functions.
verifyFormat("extern \"C\" int f() { return 42; }", getGoogleStyle());
EXPECT_EQ("extern \"C\" int f() {\n"
" int i = 42;\n"
" return i;\n"
"}",
format("extern \"C\" int f() {\n"
"\n"
" int i = 42;\n"
" return i;\n"
"}",
getGoogleStyle()));
// Remove empty lines at the beginning and end of blocks.
EXPECT_EQ("void f() {\n"
"\n"
" if (a) {\n"
"\n"
" f();\n"
" }\n"
"}",
format("void f() {\n"
"\n"
" if (a) {\n"
"\n"
" f();\n"
"\n"
" }\n"
"\n"
"}",
getLLVMStyle()));
EXPECT_EQ("void f() {\n"
" if (a) {\n"
" f();\n"
" }\n"
"}",
format("void f() {\n"
"\n"
" if (a) {\n"
"\n"
" f();\n"
"\n"
" }\n"
"\n"
"}",
getGoogleStyle()));
// Don't remove empty lines in more complex control statements.
EXPECT_EQ("void f() {\n"
" if (a) {\n"
" f();\n"
"\n"
" } else if (b) {\n"
" f();\n"
" }\n"
"}",
format("void f() {\n"
" if (a) {\n"
" f();\n"
"\n"
" } else if (b) {\n"
" f();\n"
"\n"
" }\n"
"\n"
"}"));
// Don't remove empty lines before namespace endings.
FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle();
LLVMWithNoNamespaceFix.FixNamespaceComments = false;
EXPECT_EQ("namespace {\n"
"int i;\n"
"\n"
"}",
format("namespace {\n"
"int i;\n"
"\n"
"}", LLVMWithNoNamespaceFix));
EXPECT_EQ("namespace {\n"
"int i;\n"
"}",
format("namespace {\n"
"int i;\n"
"}", LLVMWithNoNamespaceFix));
EXPECT_EQ("namespace {\n"
"int i;\n"
"\n"
"};",
format("namespace {\n"
"int i;\n"
"\n"
"};", LLVMWithNoNamespaceFix));
EXPECT_EQ("namespace {\n"
"int i;\n"
"};",
format("namespace {\n"
"int i;\n"
"};", LLVMWithNoNamespaceFix));
EXPECT_EQ("namespace {\n"
"int i;\n"
"\n"
"}",
format("namespace {\n"
"int i;\n"
"\n"
"}"));
EXPECT_EQ("namespace {\n"
"int i;\n"
"\n"
"} // namespace",
format("namespace {\n"
"int i;\n"
"\n"
"} // namespace"));
FormatStyle Style = getLLVMStyle();
Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
Style.MaxEmptyLinesToKeep = 2;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterClass = true;
Style.BraceWrapping.AfterFunction = true;
Style.KeepEmptyLinesAtTheStartOfBlocks = false;
EXPECT_EQ("class Foo\n"
"{\n"
" Foo() {}\n"
"\n"
" void funk() {}\n"
"};",
format("class Foo\n"
"{\n"
" Foo()\n"
" {\n"
" }\n"
"\n"
" void funk() {}\n"
"};",
Style));
}
TEST_F(FormatTest, RecognizesBinaryOperatorKeywords) {
verifyFormat("x = (a) and (b);");
verifyFormat("x = (a) or (b);");
verifyFormat("x = (a) bitand (b);");
verifyFormat("x = (a) bitor (b);");
verifyFormat("x = (a) not_eq (b);");
verifyFormat("x = (a) and_eq (b);");
verifyFormat("x = (a) or_eq (b);");
verifyFormat("x = (a) xor (b);");
}
TEST_F(FormatTest, RecognizesUnaryOperatorKeywords) {
verifyFormat("x = compl(a);");
verifyFormat("x = not(a);");
verifyFormat("x = bitand(a);");
// Unary operator must not be merged with the next identifier
verifyFormat("x = compl a;");
verifyFormat("x = not a;");
verifyFormat("x = bitand a;");
}
//===----------------------------------------------------------------------===//
// Tests for control statements.
//===----------------------------------------------------------------------===//
TEST_F(FormatTest, FormatIfWithoutCompoundStatement) {
verifyFormat("if (true)\n f();\ng();");
verifyFormat("if (a)\n if (b)\n if (c)\n g();\nh();");
verifyFormat("if (a)\n if (b) {\n f();\n }\ng();");
verifyFormat("if constexpr (true)\n"
" f();\ng();");
verifyFormat("if constexpr (a)\n"
" if constexpr (b)\n"
" if constexpr (c)\n"
" g();\n"
"h();");
verifyFormat("if constexpr (a)\n"
" if constexpr (b) {\n"
" f();\n"
" }\n"
"g();");
FormatStyle AllowsMergedIf = getLLVMStyle();
AllowsMergedIf.AlignEscapedNewlines = FormatStyle::ENAS_Left;
AllowsMergedIf.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
verifyFormat("if (a)\n"
" // comment\n"
" f();",
AllowsMergedIf);
verifyFormat("{\n"
" if (a)\n"
" label:\n"
" f();\n"
"}",
AllowsMergedIf);
verifyFormat("#define A \\\n"
" if (a) \\\n"
" label: \\\n"
" f()",
AllowsMergedIf);
verifyFormat("if (a)\n"
" ;",
AllowsMergedIf);
verifyFormat("if (a)\n"
" if (b) return;",
AllowsMergedIf);
verifyFormat("if (a) // Can't merge this\n"
" f();\n",
AllowsMergedIf);
verifyFormat("if (a) /* still don't merge */\n"
" f();",
AllowsMergedIf);
verifyFormat("if (a) { // Never merge this\n"
" f();\n"
"}",
AllowsMergedIf);
verifyFormat("if (a) { /* Never merge this */\n"
" f();\n"
"}",
AllowsMergedIf);
AllowsMergedIf.ColumnLimit = 14;
verifyFormat("if (a) return;", AllowsMergedIf);
verifyFormat("if (aaaaaaaaa)\n"
" return;",
AllowsMergedIf);
AllowsMergedIf.ColumnLimit = 13;
verifyFormat("if (a)\n return;", AllowsMergedIf);
}
TEST_F(FormatTest, FormatIfWithoutCompoundStatementButElseWith) {
FormatStyle AllowsMergedIf = getLLVMStyle();
AllowsMergedIf.AlignEscapedNewlines = FormatStyle::ENAS_Left;
AllowsMergedIf.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
verifyFormat("if (a)\n"
" f();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("if (a)\n"
" f();\n"
"else\n"
" g();\n",
AllowsMergedIf);
AllowsMergedIf.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_Always;
verifyFormat("if (a) f();\n"
"else {\n"
" g();\n"
"}",
AllowsMergedIf);
verifyFormat("if (a) f();\n"
"else {\n"
" if (a) f();\n"
" else {\n"
" g();\n"
" }\n"
" g();\n"
"}",
AllowsMergedIf);
}
TEST_F(FormatTest, FormatLoopsWithoutCompoundStatement) {
FormatStyle AllowsMergedLoops = getLLVMStyle();
AllowsMergedLoops.AllowShortLoopsOnASingleLine = true;
verifyFormat("while (true) continue;", AllowsMergedLoops);
verifyFormat("for (;;) continue;", AllowsMergedLoops);
verifyFormat("for (int &v : vec) v *= 2;", AllowsMergedLoops);
verifyFormat("while (true)\n"
" ;",
AllowsMergedLoops);
verifyFormat("for (;;)\n"
" ;",
AllowsMergedLoops);
verifyFormat("for (;;)\n"
" for (;;) continue;",
AllowsMergedLoops);
verifyFormat("for (;;) // Can't merge this\n"
" continue;",
AllowsMergedLoops);
verifyFormat("for (;;) /* still don't merge */\n"
" continue;",
AllowsMergedLoops);
}
TEST_F(FormatTest, FormatShortBracedStatements) {
FormatStyle AllowSimpleBracedStatements = getLLVMStyle();
AllowSimpleBracedStatements.ColumnLimit = 40;
AllowSimpleBracedStatements.AllowShortBlocksOnASingleLine = true;
AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = true;
AllowSimpleBracedStatements.BreakBeforeBraces = FormatStyle::BS_Custom;
AllowSimpleBracedStatements.BraceWrapping.AfterFunction = true;
AllowSimpleBracedStatements.BraceWrapping.SplitEmptyRecord = false;
verifyFormat("if (true) {}", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements);
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
verifyFormat("for (;;) {}", AllowSimpleBracedStatements);
verifyFormat("if (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("while (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("for (;;) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if (true) {\n"
" ffffffffffffffffffffffffffffffffffffffffffffffffffffff();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true) { //\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true) {\n"
" f();\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true) {\n"
" f();\n"
"} else {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("struct A2 {\n"
" int X;\n"
"};",
AllowSimpleBracedStatements);
verifyFormat("typedef struct A2 {\n"
" int X;\n"
"} A2_t;",
AllowSimpleBracedStatements);
verifyFormat("template <int> struct A2 {\n"
" struct B {};\n"
"};",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_Never;
verifyFormat("if (true) {}", AllowSimpleBracedStatements);
verifyFormat("if (true) {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true) {\n"
" f();\n"
"} else {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = false;
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
verifyFormat("while (true) {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("for (;;) {}", AllowSimpleBracedStatements);
verifyFormat("for (;;) {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_WithoutElse;
AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = true;
AllowSimpleBracedStatements.BraceWrapping.AfterControlStatement = true;
verifyFormat("if (true) {}", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements);
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
verifyFormat("for (;;) {}", AllowSimpleBracedStatements);
verifyFormat("if (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if constexpr (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("while (true) { f(); }", AllowSimpleBracedStatements);
verifyFormat("for (;;) { f(); }", AllowSimpleBracedStatements);
verifyFormat("if (true)\n"
"{\n"
" ffffffffffffffffffffffffffffffffffffffffffffffffffffff();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true)\n"
"{ //\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true)\n"
"{\n"
" f();\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true)\n"
"{\n"
" f();\n"
"} else\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine =
FormatStyle::SIS_Never;
verifyFormat("if (true) {}", AllowSimpleBracedStatements);
verifyFormat("if (true)\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("if (true)\n"
"{\n"
" f();\n"
"} else\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = false;
verifyFormat("while (true) {}", AllowSimpleBracedStatements);
verifyFormat("while (true)\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
verifyFormat("for (;;) {}", AllowSimpleBracedStatements);
verifyFormat("for (;;)\n"
"{\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
}
TEST_F(FormatTest, ShortBlocksInMacrosDontMergeWithCodeAfterMacro) {
FormatStyle Style = getLLVMStyleWithColumns(60);
Style.AllowShortBlocksOnASingleLine = true;
Style.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_WithoutElse;
Style.BreakBeforeBraces = FormatStyle::BS_Allman;
EXPECT_EQ("#define A \\\n"
" if (HANDLEwernufrnuLwrmviferuvnierv) \\\n"
" { RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; }\n"
"X;",
format("#define A \\\n"
" if (HANDLEwernufrnuLwrmviferuvnierv) { \\\n"
" RET_ERR1_ANUIREUINERUIFNIOAerwfwrvnuier; \\\n"
" }\n"
"X;",
Style));
}
TEST_F(FormatTest, ParseIfElse) {
verifyFormat("if (true)\n"
" if (true)\n"
" if (true)\n"
" f();\n"
" else\n"
" g();\n"
" else\n"
" h();\n"
"else\n"
" i();");
verifyFormat("if (true)\n"
" if (true)\n"
" if (true) {\n"
" if (true)\n"
" f();\n"
" } else {\n"
" g();\n"
" }\n"
" else\n"
" h();\n"
"else {\n"
" i();\n"
"}");
verifyFormat("if (true)\n"
" if constexpr (true)\n"
" if (true) {\n"
" if constexpr (true)\n"
" f();\n"
" } else {\n"
" g();\n"
" }\n"
" else\n"
" h();\n"
"else {\n"
" i();\n"
"}");
verifyFormat("void f() {\n"
" if (a) {\n"
" } else {\n"
" }\n"
"}");
}
TEST_F(FormatTest, ElseIf) {
verifyFormat("if (a) {\n} else if (b) {\n}");
verifyFormat("if (a)\n"
" f();\n"
"else if (b)\n"
" g();\n"
"else\n"
" h();");
verifyFormat("if constexpr (a)\n"
" f();\n"
"else if constexpr (b)\n"
" g();\n"
"else\n"
" h();");
verifyFormat("if (a) {\n"
" f();\n"
"}\n"
"// or else ..\n"
"else {\n"
" g()\n"
"}");
verifyFormat("if (a) {\n"
"} else if (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaa)) {\n"
"}");
verifyFormat("if (a) {\n"
"} else if (\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
"}",
getLLVMStyleWithColumns(62));
verifyFormat("if (a) {\n"
"} else if constexpr (\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n"
"}",
getLLVMStyleWithColumns(62));
}
TEST_F(FormatTest, FormatsForLoop) {
verifyFormat(
"for (int VeryVeryLongLoopVariable = 0; VeryVeryLongLoopVariable < 10;\n"
" ++VeryVeryLongLoopVariable)\n"
" ;");
verifyFormat("for (;;)\n"
" f();");
verifyFormat("for (;;) {\n}");
verifyFormat("for (;;) {\n"
" f();\n"
"}");
verifyFormat("for (int i = 0; (i < 10); ++i) {\n}");
verifyFormat(
"for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(),\n"
" E = UnwrappedLines.end();\n"
" I != E; ++I) {\n}");
verifyFormat(
"for (MachineFun::iterator IIII = PrevIt, EEEE = F.end(); IIII != EEEE;\n"
" ++IIIII) {\n}");
verifyFormat("for (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaa =\n"
" aaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaa;\n"
" aaaaaaaaaaa != aaaaaaaaaaaaaaaaaaa; ++aaaaaaaaaaa) {\n}");
verifyFormat("for (llvm::ArrayRef<NamedDecl *>::iterator\n"
" I = FD->getDeclsInPrototypeScope().begin(),\n"
" E = FD->getDeclsInPrototypeScope().end();\n"
" I != E; ++I) {\n}");
verifyFormat("for (SmallVectorImpl<TemplateIdAnnotationn *>::iterator\n"
" I = Container.begin(),\n"
" E = Container.end();\n"
" I != E; ++I) {\n}",
getLLVMStyleWithColumns(76));
verifyFormat(
"for (aaaaaaaaaaaaaaaaa aaaaaaaaaaa = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa !=\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n"
" ++aaaaaaaaaaa) {\n}");
verifyFormat("for (int i = 0; i < aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
" bbbbbbbbbbbbbbbbbbbb < ccccccccccccccc;\n"
" ++i) {\n}");
verifyFormat("for (int aaaaaaaaaaa = 1; aaaaaaaaaaa <= bbbbbbbbbbbbbbb;\n"
" aaaaaaaaaaa++, bbbbbbbbbbbbbbbbb++) {\n"
"}");
verifyFormat("for (some_namespace::SomeIterator iter( // force break\n"
" aaaaaaaaaa);\n"
" iter; ++iter) {\n"
"}");
verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaa != bbbbbbbbbbbbbbbbbbbbbbb;\n"
" ++aaaaaaaaaaaaaaaaaaaaaaaaaaa) {");
// These should not be formatted as Objective-C for-in loops.
verifyFormat("for (Foo *x = 0; x != in; x++) {\n}");
verifyFormat("Foo *x;\nfor (x = 0; x != in; x++) {\n}");
verifyFormat("Foo *x;\nfor (x in y) {\n}");
verifyFormat("for (const Foo<Bar> &baz = in.value(); !baz.at_end(); ++baz) {\n}");
FormatStyle NoBinPacking = getLLVMStyle();
NoBinPacking.BinPackParameters = false;
verifyFormat("for (int aaaaaaaaaaa = 1;\n"
" aaaaaaaaaaa <= aaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaa);\n"
" aaaaaaaaaaa++, bbbbbbbbbbbbbbbbb++) {\n"
"}",
NoBinPacking);
verifyFormat(
"for (std::vector<UnwrappedLine>::iterator I = UnwrappedLines.begin(),\n"
" E = UnwrappedLines.end();\n"
" I != E;\n"
" ++I) {\n}",
NoBinPacking);
FormatStyle AlignLeft = getLLVMStyle();
AlignLeft.PointerAlignment = FormatStyle::PAS_Left;
verifyFormat("for (A* a = start; a < end; ++a, ++value) {\n}", AlignLeft);
}
TEST_F(FormatTest, RangeBasedForLoops) {
verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa :\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}");
verifyFormat("for (auto aaaaaaaaaaaaaaaaaaaaa :\n"
" aaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaa, aaaaaaaaaaaaa)) {\n}");
verifyFormat("for (const aaaaaaaaaaaaaaaaaaaaa &aaaaaaaaa :\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {\n}");
verifyFormat("for (aaaaaaaaa aaaaaaaaaaaaaaaaaaaaa :\n"
" aaaaaaaaaaaa.aaaaaaaaaaaa().aaaaaaaaa().a()) {\n}");
}
TEST_F(FormatTest, ForEachLoops) {
verifyFormat("void f() {\n"
" foreach (Item *item, itemlist) {}\n"
" Q_FOREACH (Item *item, itemlist) {}\n"
" BOOST_FOREACH (Item *item, itemlist) {}\n"
" UNKNOWN_FORACH(Item * item, itemlist) {}\n"
"}");
// As function-like macros.
verifyFormat("#define foreach(x, y)\n"
"#define Q_FOREACH(x, y)\n"
"#define BOOST_FOREACH(x, y)\n"
"#define UNKNOWN_FOREACH(x, y)\n");
// Not as function-like macros.
verifyFormat("#define foreach (x, y)\n"
"#define Q_FOREACH (x, y)\n"
"#define BOOST_FOREACH (x, y)\n"
"#define UNKNOWN_FOREACH (x, y)\n");
}
TEST_F(FormatTest, FormatsWhileLoop) {
verifyFormat("while (true) {\n}");
verifyFormat("while (true)\n"
" f();");
verifyFormat("while () {\n}");
verifyFormat("while () {\n"
" f();\n"
"}");
}
TEST_F(FormatTest, FormatsDoWhile) {
verifyFormat("do {\n"
" do_something();\n"
"} while (something());");
verifyFormat("do\n"
" do_something();\n"
"while (something());");
}
TEST_F(FormatTest, FormatsSwitchStatement) {
verifyFormat("switch (x) {\n"
"case 1:\n"
" f();\n"
" break;\n"
"case kFoo:\n"
"case ns::kBar:\n"
"case kBaz:\n"
" break;\n"
"default:\n"
" g();\n"
" break;\n"
"}");
verifyFormat("switch (x) {\n"
"case 1: {\n"
" f();\n"
" break;\n"
"}\n"
"case 2: {\n"
" break;\n"
"}\n"
"}");
verifyFormat("switch (x) {\n"
"case 1: {\n"
" f();\n"
" {\n"
" g();\n"
" h();\n"
" }\n"
" break;\n"
"}\n"
"}");
verifyFormat("switch (x) {\n"
"case 1: {\n"
" f();\n"
" if (foo) {\n"
" g();\n"
" h();\n"
" }\n"
" break;\n"
"}\n"
"}");
verifyFormat("switch (x) {\n"
"case 1: {\n"
" f();\n"
" g();\n"
"} break;\n"
"}");
verifyFormat("switch (test)\n"
" ;");
verifyFormat("switch (x) {\n"
"default: {\n"
" // Do nothing.\n"
"}\n"
"}");
verifyFormat("switch (x) {\n"
"// comment\n"
"// if 1, do f()\n"
"case 1:\n"
" f();\n"
"}");
verifyFormat("switch (x) {\n"
"case 1:\n"
" // Do amazing stuff\n"
" {\n"
" f();\n"
" g();\n"
" }\n"
" break;\n"
"}");
verifyFormat("#define A \\\n"
" switch (x) { \\\n"
" case a: \\\n"
" foo = b; \\\n"
" }",
getLLVMStyleWithColumns(20));
verifyFormat("#define OPERATION_CASE(name) \\\n"
" case OP_name: \\\n"
" return operations::Operation##name\n",
getLLVMStyleWithColumns(40));
verifyFormat("switch (x) {\n"
"case 1:;\n"
"default:;\n"
" int i;\n"
"}");
verifyGoogleFormat("switch (x) {\n"
" case 1:\n"
" f();\n"
" break;\n"
" case kFoo:\n"
" case ns::kBar:\n"
" case kBaz:\n"
" break;\n"
" default:\n"
" g();\n"
" break;\n"
"}");
verifyGoogleFormat("switch (x) {\n"
" case 1: {\n"
" f();\n"
" break;\n"
" }\n"
"}");
verifyGoogleFormat("switch (test)\n"
" ;");
verifyGoogleFormat("#define OPERATION_CASE(name) \\\n"
" case OP_name: \\\n"
" return operations::Operation##name\n");
verifyGoogleFormat("Operation codeToOperation(OperationCode OpCode) {\n"
" // Get the correction operation class.\n"
" switch (OpCode) {\n"
" CASE(Add);\n"
" CASE(Subtract);\n"
" default:\n"
" return operations::Unknown;\n"
" }\n"
"#undef OPERATION_CASE\n"
"}");
verifyFormat("DEBUG({\n"
" switch (x) {\n"
" case A:\n"
" f();\n"
" break;\n"
" // fallthrough\n"
" case B:\n"
" g();\n"
" break;\n"
" }\n"
"});");
EXPECT_EQ("DEBUG({\n"
" switch (x) {\n"
" case A:\n"
" f();\n"
" break;\n"
" // On B:\n"
" case B:\n"
" g();\n"
" break;\n"
" }\n"
"});",
format("DEBUG({\n"
" switch (x) {\n"
" case A:\n"
" f();\n"
" break;\n"
" // On B:\n"
" case B:\n"
" g();\n"
" break;\n"
" }\n"
"});",
getLLVMStyle()));
EXPECT_EQ("switch (n) {\n"
"case 0: {\n"
" return false;\n"
"}\n"
"default: {\n"
" return true;\n"
"}\n"
"}",
format("switch (n)\n"
"{\n"
"case 0: {\n"
" return false;\n"
"}\n"
"default: {\n"
" return true;\n"
"}\n"
"}",
getLLVMStyle()));
verifyFormat("switch (a) {\n"
"case (b):\n"
" return;\n"
"}");
verifyFormat("switch (a) {\n"
"case some_namespace::\n"
" some_constant:\n"
" return;\n"
"}",
getLLVMStyleWithColumns(34));
FormatStyle Style = getLLVMStyle();
Style.IndentCaseLabels = true;
Style.AllowShortBlocksOnASingleLine = false;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterCaseLabel = true;
Style.BraceWrapping.AfterControlStatement = true;
EXPECT_EQ("switch (n)\n"
"{\n"
" case 0:\n"
" {\n"
" return false;\n"
" }\n"
" default:\n"
" {\n"
" return true;\n"
" }\n"
"}",
format("switch (n) {\n"
" case 0: {\n"
" return false;\n"
" }\n"
" default: {\n"
" return true;\n"
" }\n"
"}",
Style));
Style.BraceWrapping.AfterCaseLabel = false;
EXPECT_EQ("switch (n)\n"
"{\n"
" case 0: {\n"
" return false;\n"
" }\n"
" default: {\n"
" return true;\n"
" }\n"
"}",
format("switch (n) {\n"
" case 0:\n"
" {\n"
" return false;\n"
" }\n"
" default:\n"
" {\n"
" return true;\n"
" }\n"
"}",
Style));
}
TEST_F(FormatTest, CaseRanges) {
verifyFormat("switch (x) {\n"
"case 'A' ... 'Z':\n"
"case 1 ... 5:\n"
"case a ... b:\n"
" break;\n"
"}");
}
TEST_F(FormatTest, ShortCaseLabels) {
FormatStyle Style = getLLVMStyle();
Style.AllowShortCaseLabelsOnASingleLine = true;
verifyFormat("switch (a) {\n"
"case 1: x = 1; break;\n"
"case 2: return;\n"
"case 3:\n"
"case 4:\n"
"case 5: return;\n"
"case 6: // comment\n"
" return;\n"
"case 7:\n"
" // comment\n"
" return;\n"
"case 8:\n"
" x = 8; // comment\n"
" break;\n"
"default: y = 1; break;\n"
"}",
Style);
verifyFormat("switch (a) {\n"
"case 0: return; // comment\n"
"case 1: break; // comment\n"
"case 2: return;\n"
"// comment\n"
"case 3: return;\n"
"// comment 1\n"
"// comment 2\n"
"// comment 3\n"
"case 4: break; /* comment */\n"
"case 5:\n"
" // comment\n"
" break;\n"
"case 6: /* comment */ x = 1; break;\n"
"case 7: x = /* comment */ 1; break;\n"
"case 8:\n"
" x = 1; /* comment */\n"
" break;\n"
"case 9:\n"
" break; // comment line 1\n"
" // comment line 2\n"
"}",
Style);
EXPECT_EQ("switch (a) {\n"
"case 1:\n"
" x = 8;\n"
" // fall through\n"
"case 2: x = 8;\n"
"// comment\n"
"case 3:\n"
" return; /* comment line 1\n"
" * comment line 2 */\n"
"case 4: i = 8;\n"
"// something else\n"
"#if FOO\n"
"case 5: break;\n"
"#endif\n"
"}",
format("switch (a) {\n"
"case 1: x = 8;\n"
" // fall through\n"
"case 2:\n"
" x = 8;\n"
"// comment\n"
"case 3:\n"
" return; /* comment line 1\n"
" * comment line 2 */\n"
"case 4:\n"
" i = 8;\n"
"// something else\n"
"#if FOO\n"
"case 5: break;\n"
"#endif\n"
"}",
Style));
EXPECT_EQ("switch (a) {\n" "case 0:\n"
" return; // long long long long long long long long long long long long comment\n"
" // line\n" "}",
format("switch (a) {\n"
"case 0: return; // long long long long long long long long long long long long comment line\n"
"}",
Style));
EXPECT_EQ("switch (a) {\n"
"case 0:\n"
" return; /* long long long long long long long long long long long long comment\n"
" line */\n"
"}",
format("switch (a) {\n"
"case 0: return; /* long long long long long long long long long long long long comment line */\n"
"}",
Style));
verifyFormat("switch (a) {\n"
"#if FOO\n"
"case 0: return 0;\n"
"#endif\n"
"}",
Style);
verifyFormat("switch (a) {\n"
"case 1: {\n"
"}\n"
"case 2: {\n"
" return;\n"
"}\n"
"case 3: {\n"
" x = 1;\n"
" return;\n"
"}\n"
"case 4:\n"
" if (x)\n"
" return;\n"
"}",
Style);
Style.ColumnLimit = 21;
verifyFormat("switch (a) {\n"
"case 1: x = 1; break;\n"
"case 2: return;\n"
"case 3:\n"
"case 4:\n"
"case 5: return;\n"
"default:\n"
" y = 1;\n"
" break;\n"
"}",
Style);
Style.ColumnLimit = 80;
Style.AllowShortCaseLabelsOnASingleLine = false;
Style.IndentCaseLabels = true;
EXPECT_EQ("switch (n) {\n"
" default /*comments*/:\n"
" return true;\n"
" case 0:\n"
" return false;\n"
"}",
format("switch (n) {\n"
"default/*comments*/:\n"
" return true;\n"
"case 0:\n"
" return false;\n"
"}",
Style));
Style.AllowShortCaseLabelsOnASingleLine = true;
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterCaseLabel = true;
Style.BraceWrapping.AfterControlStatement = true;
EXPECT_EQ("switch (n)\n"
"{\n"
" case 0:\n"
" {\n"
" return false;\n"
" }\n"
" default:\n"
" {\n"
" return true;\n"
" }\n"
"}",
format("switch (n) {\n"
" case 0: {\n"
" return false;\n"
" }\n"
" default:\n"
" {\n"
" return true;\n"
" }\n"
"}",
Style));
}
TEST_F(FormatTest, FormatsLabels) {
verifyFormat("void f() {\n"
" some_code();\n"
"test_label:\n"
" some_other_code();\n"
" {\n"
" some_more_code();\n"
" another_label:\n"
" some_more_code();\n"
" }\n"
"}");
verifyFormat("{\n"
" some_code();\n"
"test_label:\n"
" some_other_code();\n"
"}");
verifyFormat("{\n"
" some_code();\n"
"test_label:;\n"
" int i = 0;\n"
"}");
}
//===----------------------------------------------------------------------===//
// Tests for classes, namespaces, etc.
//===----------------------------------------------------------------------===//
TEST_F(FormatTest, DoesNotBreakSemiAfterClassDecl) {
verifyFormat("class A {};");
}
TEST_F(FormatTest, UnderstandsAccessSpecifiers) {
verifyFormat("class A {\n"
"public:\n"
"public: // comment\n"
"protected:\n"
"private:\n"
" void f() {}\n"
"};");
verifyFormat("export class A {\n"
"public:\n"
"public: // comment\n"
"protected:\n"
"private:\n"
" void f() {}\n"
"};");
verifyGoogleFormat("class A {\n"
" public:\n"
" protected:\n"
" private:\n"
" void f() {}\n"
"};");
verifyGoogleFormat("export class A {\n"
" public:\n"
" protected:\n"
" private:\n"
" void f() {}\n"
"};");
verifyFormat("class A {\n"
"public slots:\n"
" void f1() {}\n"
"public Q_SLOTS:\n"
" void f2() {}\n"
"protected slots:\n"
" void f3() {}\n"
"protected Q_SLOTS:\n"
" void f4() {}\n"
"private slots:\n"
" void f5() {}\n"
"private Q_SLOTS:\n"
" void f6() {}\n"
"signals:\n"
" void g1();\n"
"Q_SIGNALS:\n"
" void g2();\n"
"};");
// Don't interpret 'signals' the wrong way.
verifyFormat("signals.set();");
verifyFormat("for (Signals signals : f()) {\n}");
verifyFormat("{\n"
" signals.set(); // This needs indentation.\n"
"}");
verifyFormat("void f() {\n"
"label:\n"
" signals.baz();\n"
"}");
}
TEST_F(FormatTest, SeparatesLogicalBlocks) {
EXPECT_EQ("class A {\n"
"public:\n"
" void f();\n"
"\n"
"private:\n"
" void g() {}\n"
" // test\n"
"protected:\n"
" int h;\n"
"};",
format("class A {\n"
"public:\n"
"void f();\n"
"private:\n"
"void g() {}\n"
"// test\n"
"protected:\n"
"int h;\n"
"};"));
EXPECT_EQ("class A {\n"
"protected:\n"
"public:\n"
" void f();\n"
"};",
format("class A {\n"
"protected:\n"
"\n"
"public:\n"
"\n"
" void f();\n"
"};"));
// Even ensure proper spacing inside macros.
EXPECT_EQ("#define B \\\n"
" class A { \\\n"
" protected: \\\n"
" public: \\\n"
" void f(); \\\n"
" };",
format("#define B \\\n"
" class A { \\\n"
" protected: \\\n"
" \\\n"
" public: \\\n"
" \\\n"
" void f(); \\\n"
" };",
getGoogleStyle()));
// But don't remove empty lines after macros ending in access specifiers.
EXPECT_EQ("#define A private:\n"
"\n"
"int i;",
format("#define A private:\n"
"\n"
"int i;"));
}
TEST_F(FormatTest, FormatsClasses) {
verifyFormat("class A : public B {};");
verifyFormat("class A : public ::B {};");
verifyFormat(
"class AAAAAAAAAAAAAAAAAAAA : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n"
" public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};");
verifyFormat("class AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
" : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n"
" public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};");
verifyFormat(
"class A : public B, public C, public D, public E, public F {};");
verifyFormat("class AAAAAAAAAAAA : public B,\n"
" public C,\n"
" public D,\n"
" public E,\n"
" public F,\n"
" public G {};");
verifyFormat("class\n"
" ReallyReallyLongClassName {\n"
" int i;\n"
"};",
getLLVMStyleWithColumns(32));
verifyFormat("struct aaaaaaaaaaaaa : public aaaaaaaaaaaaaaaaaaa< // break\n"
" aaaaaaaaaaaaaaaa> {};");
verifyFormat("struct aaaaaaaaaaaaaaaaaaaa\n"
" : public aaaaaaaaaaaaaaaaaaa<aaaaaaaaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaaaaaaaa> {};");
verifyFormat("template <class R, class C>\n"
"struct Aaaaaaaaaaaaaaaaa<R (C::*)(int) const>\n"
" : Aaaaaaaaaaaaaaaaa<R (C::*)(int)> {};");
verifyFormat("class ::A::B {};");
}
TEST_F(FormatTest, BreakInheritanceStyle) {
FormatStyle StyleWithInheritanceBreakBeforeComma = getLLVMStyle();
StyleWithInheritanceBreakBeforeComma.BreakInheritanceList =
FormatStyle::BILS_BeforeComma;
verifyFormat("class MyClass : public X {};",
StyleWithInheritanceBreakBeforeComma);
verifyFormat("class MyClass\n"
" : public X\n"
" , public Y {};",
StyleWithInheritanceBreakBeforeComma);
verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA\n"
" : public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"
" , public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};",
StyleWithInheritanceBreakBeforeComma);
verifyFormat("struct aaaaaaaaaaaaa\n"
" : public aaaaaaaaaaaaaaaaaaa< // break\n"
" aaaaaaaaaaaaaaaa> {};",
StyleWithInheritanceBreakBeforeComma);
FormatStyle StyleWithInheritanceBreakAfterColon = getLLVMStyle();
StyleWithInheritanceBreakAfterColon.BreakInheritanceList =
FormatStyle::BILS_AfterColon;
verifyFormat("class MyClass : public X {};",
StyleWithInheritanceBreakAfterColon);
verifyFormat("class MyClass : public X, public Y {};",
StyleWithInheritanceBreakAfterColon);
verifyFormat("class AAAAAAAAAAAAAAAAAAAAAA :\n"
" public BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB,\n"
" public CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC {};",
StyleWithInheritanceBreakAfterColon);
verifyFormat("struct aaaaaaaaaaaaa :\n"
" public aaaaaaaaaaaaaaaaaaa< // break\n"
" aaaaaaaaaaaaaaaa> {};",
StyleWithInheritanceBreakAfterColon);
}
TEST_F(FormatTest, FormatsVariableDeclarationsAfterStructOrClass) {
verifyFormat("class A {\n} a, b;");
verifyFormat("struct A {\n} a, b;");
verifyFormat("union A {\n} a;");
}
TEST_F(FormatTest, FormatsEnum) {
verifyFormat("enum {\n"
" Zero,\n"
" One = 1,\n"
" Two = One + 1,\n"
" Three = (One + Two),\n"
" Four = (Zero && (One ^ Two)) | (One << Two),\n"
" Five = (One, Two, Three, Four, 5)\n"
"};");
verifyGoogleFormat("enum {\n"
" Zero,\n"
" One = 1,\n"
" Two = One + 1,\n"
" Three = (One + Two),\n"
" Four = (Zero && (One ^ Two)) | (One << Two),\n"
" Five = (One, Two, Three, Four, 5)\n"
"};");
verifyFormat("enum Enum {};");
verifyFormat("enum {};");
verifyFormat("enum X E {} d;");
verifyFormat("enum __attribute__((...)) E {} d;");
verifyFormat("enum __declspec__((...)) E {} d;");
verifyFormat("enum {\n"
" Bar = Foo<int, int>::value\n"
"};",
getLLVMStyleWithColumns(30));
verifyFormat("enum ShortEnum { A, B, C };");
verifyGoogleFormat("enum ShortEnum { A, B, C };");
EXPECT_EQ("enum KeepEmptyLines {\n"
" ONE,\n"
"\n"
" TWO,\n"
"\n"
" THREE\n"
"}",
format("enum KeepEmptyLines {\n"
" ONE,\n"
"\n"
" TWO,\n"
"\n"
"\n"
" THREE\n"
"}"));
verifyFormat("enum E { // comment\n"
" ONE,\n"
" TWO\n"
"};\n"
"int i;");
// Not enums.
verifyFormat("enum X f() {\n"
" a();\n"
" return 42;\n"
"}");
verifyFormat("enum X Type::f() {\n"
" a();\n"
" return 42;\n"
"}");
verifyFormat("enum ::X f() {\n"
" a();\n"
" return 42;\n"
"}");
verifyFormat("enum ns::X f() {\n"
" a();\n"
" return 42;\n"
"}");
}
TEST_F(FormatTest, FormatsEnumsWithErrors) {
verifyFormat("enum Type {\n"
" One = 0; // These semicolons should be commas.\n"
" Two = 1;\n"
"};");
verifyFormat("namespace n {\n"
"enum Type {\n"
" One,\n"
" Two, // missing };\n"
" int i;\n"
"}\n"
"void g() {}");
}
TEST_F(FormatTest, FormatsEnumStruct) {
verifyFormat("enum struct {\n"
" Zero,\n"
" One = 1,\n"
" Two = One + 1,\n"
" Three = (One + Two),\n"
" Four = (Zero && (One ^ Two)) | (One << Two),\n"
" Five = (One, Two, Three, Four, 5)\n"
"};");
verifyFormat("enum struct Enum {};");
verifyFormat("enum struct {};");
verifyFormat("enum struct X E {} d;");
verifyFormat("enum struct __attribute__((...)) E {} d;");
verifyFormat("enum struct __declspec__((...)) E {} d;");
verifyFormat("enum struct X f() {\n a();\n return 42;\n}");
}
TEST_F(FormatTest, FormatsEnumClass) {
verifyFormat("enum class {\n"
" Zero,\n"
" One = 1,\n"
" Two = One + 1,\n"
" Three = (One + Two),\n"
" Four = (Zero && (One ^ Two)) | (One << Two),\n"
" Five = (One, Two, Three, Four, 5)\n"
"};");
verifyFormat("enum class Enum {};");
verifyFormat("enum class {};");
verifyFormat("enum class X E {} d;");
verifyFormat("enum class __attribute__((...)) E {} d;");
verifyFormat("enum class __declspec__((...)) E {} d;");
verifyFormat("enum class X f() {\n a();\n return 42;\n}");
}
TEST_F(FormatTest, FormatsEnumTypes) {
verifyFormat("enum X : int {\n"
" A, // Force multiple lines.\n"
" B\n"
"};");
verifyFormat("enum X : int { A, B };");
verifyFormat("enum X : std::uint32_t { A, B };");
}
TEST_F(FormatTest, FormatsTypedefEnum) {
FormatStyle Style = getLLVMStyle();
Style.ColumnLimit = 40;
verifyFormat("typedef enum {} EmptyEnum;");
verifyFormat("typedef enum { A, B, C } ShortEnum;");
verifyFormat("typedef enum {\n"
" ZERO = 0,\n"
" ONE = 1,\n"
" TWO = 2,\n"
" THREE = 3\n"
"} LongEnum;",
Style);
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterEnum = true;
verifyFormat("typedef enum {} EmptyEnum;");
verifyFormat("typedef enum { A, B, C } ShortEnum;");
verifyFormat("typedef enum\n"
"{\n"
" ZERO = 0,\n"
" ONE = 1,\n"
" TWO = 2,\n"
" THREE = 3\n"
"} LongEnum;",
Style);
}
TEST_F(FormatTest, FormatsNSEnums) {
verifyGoogleFormat("typedef NS_ENUM(NSInteger, SomeName) { AAA, BBB }");
verifyGoogleFormat("typedef NS_ENUM(NSInteger, MyType) {\n"
" // Information about someDecentlyLongValue.\n"
" someDecentlyLongValue,\n"
" // Information about anotherDecentlyLongValue.\n"
" anotherDecentlyLongValue,\n"
" // Information about aThirdDecentlyLongValue.\n"
" aThirdDecentlyLongValue\n"
"};");
verifyGoogleFormat("typedef NS_OPTIONS(NSInteger, MyType) {\n"
" a = 1,\n"
" b = 2,\n"
" c = 3,\n"
"};");
verifyGoogleFormat("typedef CF_ENUM(NSInteger, MyType) {\n"
" a = 1,\n"
" b = 2,\n"
" c = 3,\n"
"};");
verifyGoogleFormat("typedef CF_OPTIONS(NSInteger, MyType) {\n"
" a = 1,\n"
" b = 2,\n"
" c = 3,\n"
"};");
}
TEST_F(FormatTest, FormatsBitfields) {
verifyFormat("struct Bitfields {\n"
" unsigned sClass : 8;\n"
" unsigned ValueKind : 2;\n"
"};");
verifyFormat("struct A {\n"
" int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa : 1,\n"
" bbbbbbbbbbbbbbbbbbbbbbbbb;\n"
"};");
verifyFormat("struct MyStruct {\n"
" uchar data;\n"
" uchar : 8;\n"
" uchar : 8;\n"
" uchar other;\n"
"};");
}
TEST_F(FormatTest, FormatsNamespaces) {
FormatStyle LLVMWithNoNamespaceFix = getLLVMStyle();
LLVMWithNoNamespaceFix.FixNamespaceComments = false;
verifyFormat("namespace some_namespace {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
verifyFormat("/* something */ namespace some_namespace {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
verifyFormat("namespace {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
verifyFormat("/* something */ namespace {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
verifyFormat("inline namespace X {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
verifyFormat("/* something */ inline namespace X {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
verifyFormat("export namespace X {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
verifyFormat("using namespace some_namespace;\n"
"class A {};\n"
"void f() { f(); }",
LLVMWithNoNamespaceFix);
// This code is more common than we thought; if we
// layout this correctly the semicolon will go into
// its own line, which is undesirable.
verifyFormat("namespace {};",
LLVMWithNoNamespaceFix);
verifyFormat("namespace {\n"
"class A {};\n"
"};",
LLVMWithNoNamespaceFix);
verifyFormat("namespace {\n"
"int SomeVariable = 0; // comment\n"
"} // namespace",
LLVMWithNoNamespaceFix);
EXPECT_EQ("#ifndef HEADER_GUARD\n"
"#define HEADER_GUARD\n"
"namespace my_namespace {\n"
"int i;\n"
"} // my_namespace\n"
"#endif // HEADER_GUARD",
format("#ifndef HEADER_GUARD\n"
" #define HEADER_GUARD\n"
" namespace my_namespace {\n"
"int i;\n"
"} // my_namespace\n"
"#endif // HEADER_GUARD",
LLVMWithNoNamespaceFix));
EXPECT_EQ("namespace A::B {\n"
"class C {};\n"
"}",
format("namespace A::B {\n"
"class C {};\n"
"}",
LLVMWithNoNamespaceFix));
FormatStyle Style = getLLVMStyle();
Style.NamespaceIndentation = FormatStyle::NI_All;
EXPECT_EQ("namespace out {\n"
" int i;\n"
" namespace in {\n"
" int i;\n"
" } // namespace in\n"
"} // namespace out",
format("namespace out {\n"
"int i;\n"
"namespace in {\n"
"int i;\n"
"} // namespace in\n"
"} // namespace out",
Style));
Style.NamespaceIndentation = FormatStyle::NI_Inner;
EXPECT_EQ("namespace out {\n"
"int i;\n"
"namespace in {\n"
" int i;\n"
"} // namespace in\n"
"} // namespace out",
format("namespace out {\n"
"int i;\n"
"namespace in {\n"
"int i;\n"
"} // namespace in\n"
"} // namespace out",
Style));
}
TEST_F(FormatTest, FormatsCompactNamespaces) {
FormatStyle Style = getLLVMStyle();
Style.CompactNamespaces = true;
verifyFormat("namespace A { namespace B {\n"
"}} // namespace A::B",
Style);
EXPECT_EQ("namespace out { namespace in {\n"
"}} // namespace out::in",
format("namespace out {\n"
"namespace in {\n"
"} // namespace in\n"
"} // namespace out",
Style));
// Only namespaces which have both consecutive opening and end get compacted
EXPECT_EQ("namespace out {\n"
"namespace in1 {\n"
"} // namespace in1\n"
"namespace in2 {\n"
"} // namespace in2\n"
"} // namespace out",
format("namespace out {\n"
"namespace in1 {\n"
"} // namespace in1\n"
"namespace in2 {\n"
"} // namespace in2\n"
"} // namespace out",
Style));
EXPECT_EQ("namespace out {\n"
"int i;\n"
"namespace in {\n"
"int j;\n"
"} // namespace in\n"
"int k;\n"
"} // namespace out",
format("namespace out { int i;\n"
"namespace in { int j; } // namespace in\n"
"int k; } // namespace out",
Style));
EXPECT_EQ("namespace A { namespace B { namespace C {\n"
"}}} // namespace A::B::C\n",
format("namespace A { namespace B {\n"
"namespace C {\n"
"}} // namespace B::C\n"
"} // namespace A\n",
Style));
Style.ColumnLimit = 40;
EXPECT_EQ("namespace aaaaaaaaaa {\n"
"namespace bbbbbbbbbb {\n"
"}} // namespace aaaaaaaaaa::bbbbbbbbbb",
format("namespace aaaaaaaaaa {\n"
"namespace bbbbbbbbbb {\n"
"} // namespace bbbbbbbbbb\n"
"} // namespace aaaaaaaaaa",
Style));
EXPECT_EQ("namespace aaaaaa { namespace bbbbbb {\n"
"namespace cccccc {\n"
"}}} // namespace aaaaaa::bbbbbb::cccccc",
format("namespace aaaaaa {\n"
"namespace bbbbbb {\n"
"namespace cccccc {\n"
"} // namespace cccccc\n"
"} // namespace bbbbbb\n"
"} // namespace aaaaaa",
Style));
Style.ColumnLimit = 80;
// Extra semicolon after 'inner' closing brace prevents merging
EXPECT_EQ("namespace out { namespace in {\n"
"}; } // namespace out::in",
format("namespace out {\n"
"namespace in {\n"
"}; // namespace in\n"
"} // namespace out",
Style));
// Extra semicolon after 'outer' closing brace is conserved
EXPECT_EQ("namespace out { namespace in {\n"
"}}; // namespace out::in",
format("namespace out {\n"
"namespace in {\n"
"} // namespace in\n"
"}; // namespace out",
Style));
Style.NamespaceIndentation = FormatStyle::NI_All;
EXPECT_EQ("namespace out { namespace in {\n"
" int i;\n"
"}} // namespace out::in",
format("namespace out {\n"
"namespace in {\n"
"int i;\n"
"} // namespace in\n"
"} // namespace out",
Style));
EXPECT_EQ("namespace out { namespace mid {\n"
" namespace in {\n"
" int j;\n"
" } // namespace in\n"
" int k;\n"
"}} // namespace out::mid",
format("namespace out { namespace mid {\n"
"namespace in { int j; } // namespace in\n"
"int k; }} // namespace out::mid",
Style));
Style.NamespaceIndentation = FormatStyle::NI_Inner;
EXPECT_EQ("namespace out { namespace in {\n"
" int i;\n"
"}} // namespace out::in",
format("namespace out {\n"
"namespace in {\n"
"int i;\n"
"} // namespace in\n"
"} // namespace out",
Style));
EXPECT_EQ("namespace out { namespace mid { namespace in {\n"
" int i;\n"
"}}} // namespace out::mid::in",
format("namespace out {\n"
"namespace mid {\n"
"namespace in {\n"
"int i;\n"
"} // namespace in\n"
"} // namespace mid\n"
"} // namespace out",
Style));
}
TEST_F(FormatTest, FormatsExternC) {
verifyFormat("extern \"C\" {\nint a;");
verifyFormat("extern \"C\" {}");
verifyFormat("extern \"C\" {\n"
"int foo();\n"
"}");
verifyFormat("extern \"C\" int foo() {}");
verifyFormat("extern \"C\" int foo();");
verifyFormat("extern \"C\" int foo() {\n"
" int i = 42;\n"
" return i;\n"
"}");
FormatStyle Style = getLLVMStyle();
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterFunction = true;
verifyFormat("extern \"C\" int foo() {}", Style);
verifyFormat("extern \"C\" int foo();", Style);
verifyFormat("extern \"C\" int foo()\n"
"{\n"
" int i = 42;\n"
" return i;\n"
"}",
Style);
Style.BraceWrapping.AfterExternBlock = true;
Style.BraceWrapping.SplitEmptyRecord = false;
verifyFormat("extern \"C\"\n"
"{}",
Style);
verifyFormat("extern \"C\"\n"
"{\n"
" int foo();\n"
"}",
Style);
}
TEST_F(FormatTest, FormatsInlineASM) {
verifyFormat("asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));");
verifyFormat("asm(\"nop\" ::: \"memory\");");
verifyFormat(
"asm(\"movq\\t%%rbx, %%rsi\\n\\t\"\n"
" \"cpuid\\n\\t\"\n"
" \"xchgq\\t%%rbx, %%rsi\\n\\t\"\n"
" : \"=a\"(*rEAX), \"=S\"(*rEBX), \"=c\"(*rECX), \"=d\"(*rEDX)\n"
" : \"a\"(value));");
EXPECT_EQ(
"void NS_InvokeByIndex(void *that, unsigned int methodIndex) {\n"
" __asm {\n"
" mov edx,[that] // vtable in edx\n"
" mov eax,methodIndex\n"
" call [edx][eax*4] // stdcall\n"
" }\n"
"}",
format("void NS_InvokeByIndex(void *that, unsigned int methodIndex) {\n"
" __asm {\n"
" mov edx,[that] // vtable in edx\n"
" mov eax,methodIndex\n"
" call [edx][eax*4] // stdcall\n"
" }\n"
"}"));
EXPECT_EQ("_asm {\n"
" xor eax, eax;\n"
" cpuid;\n"
"}",
format("_asm {\n"
" xor eax, eax;\n"
" cpuid;\n"
"}"));
verifyFormat("void function() {\n"
" // comment\n"
" asm(\"\");\n"
"}");
EXPECT_EQ("__asm {\n"
"}\n"
"int i;",
format("__asm {\n"
"}\n"
"int i;"));
}
TEST_F(FormatTest, FormatTryCatch) {
verifyFormat("try {\n"
" throw a * b;\n"
"} catch (int a) {\n"
" // Do nothing.\n"
"} catch (...) {\n"
" exit(42);\n"
"}");
// Function-level try statements.
verifyFormat("int f() try { return 4; } catch (...) {\n"
" return 5;\n"
"}");
verifyFormat("class A {\n"
" int a;\n"
" A() try : a(0) {\n"
" } catch (...) {\n"
" throw;\n"
" }\n"
"};\n");
// Incomplete try-catch blocks.
verifyIncompleteFormat("try {} catch (");
}
TEST_F(FormatTest, FormatSEHTryCatch) {
verifyFormat("__try {\n"
" int a = b * c;\n"
"} __except (EXCEPTION_EXECUTE_HANDLER) {\n"
" // Do nothing.\n"
"}");
verifyFormat("__try {\n"
" int a = b * c;\n"
"} __finally {\n"
" // Do nothing.\n"
"}");
verifyFormat("DEBUG({\n"
" __try {\n"
" } __finally {\n"
" }\n"
"});\n");
}
TEST_F(FormatTest, IncompleteTryCatchBlocks) {
verifyFormat("try {\n"
" f();\n"
"} catch {\n"
" g();\n"
"}");
verifyFormat("try {\n"
" f();\n"
"} catch (A a) MACRO(x) {\n"
" g();\n"
"} catch (B b) MACRO(x) {\n"
" g();\n"
"}");
}
TEST_F(FormatTest, FormatTryCatchBraceStyles) {
FormatStyle Style = getLLVMStyle();
for (auto BraceStyle : {FormatStyle::BS_Attach, FormatStyle::BS_Mozilla,
FormatStyle::BS_WebKit}) {
Style.BreakBeforeBraces = BraceStyle;
verifyFormat("try {\n"
" // something\n"
"} catch (...) {\n"
" // something\n"
"}",
Style);
}
Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
verifyFormat("try {\n"
" // something\n"
"}\n"
"catch (...) {\n"
" // something\n"
"}",
Style);
verifyFormat("__try {\n"
" // something\n"
"}\n"
"__finally {\n"
" // something\n"
"}",
Style);
verifyFormat("@try {\n"
" // something\n"
"}\n"
"@finally {\n"
" // something\n"
"}",
Style);
Style.BreakBeforeBraces = FormatStyle::BS_Allman;
verifyFormat("try\n"
"{\n"
" // something\n"
"}\n"
"catch (...)\n"
"{\n"
" // something\n"
"}",
Style);
Style.BreakBeforeBraces = FormatStyle::BS_GNU;
verifyFormat("try\n"
" {\n"
" // something\n"
" }\n"
"catch (...)\n"
" {\n"
" // something\n"
" }",
Style);
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.BeforeCatch = true;
verifyFormat("try {\n"
" // something\n"
"}\n"
"catch (...) {\n"
" // something\n"
"}",
Style);
}
TEST_F(FormatTest, StaticInitializers) {
verifyFormat("static SomeClass SC = {1, 'a'};");
verifyFormat("static SomeClass WithALoooooooooooooooooooongName = {\n"
" 100000000, "
"\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};");
// Here, everything other than the "}" would fit on a line.
verifyFormat("static int LooooooooooooooooooooooooongVariable[1] = {\n"
" 10000000000000000000000000};");
EXPECT_EQ("S s = {a,\n"
"\n"
" b};",
format("S s = {\n"
" a,\n"
"\n"
" b\n"
"};"));
// FIXME: This would fit into the column limit if we'd fit "{ {" on the first
// line. However, the formatting looks a bit off and this probably doesn't
// happen often in practice.
verifyFormat("static int Variable[1] = {\n"
" {1000000000000000000000000000000000000}};",
getLLVMStyleWithColumns(40));
}
TEST_F(FormatTest, DesignatedInitializers) {
verifyFormat("const struct A a = {.a = 1, .b = 2};");
verifyFormat("const struct A a = {.aaaaaaaaaa = 1,\n"
" .bbbbbbbbbb = 2,\n"
" .cccccccccc = 3,\n"
" .dddddddddd = 4,\n"
" .eeeeeeeeee = 5};");
verifyFormat("const struct Aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa = {\n"
" .aaaaaaaaaaaaaaaaaaaaaaaaaaa = 1,\n"
" .bbbbbbbbbbbbbbbbbbbbbbbbbbb = 2,\n"
" .ccccccccccccccccccccccccccc = 3,\n"
" .ddddddddddddddddddddddddddd = 4,\n"
" .eeeeeeeeeeeeeeeeeeeeeeeeeee = 5};");
verifyGoogleFormat("const struct A a = {.a = 1, .b = 2};");
verifyFormat("const struct A a = {[0] = 1, [1] = 2};");
verifyFormat("const struct A a = {[1] = aaaaaaaaaa,\n"
" [2] = bbbbbbbbbb,\n"
" [3] = cccccccccc,\n"
" [4] = dddddddddd,\n"
" [5] = eeeeeeeeee};");
verifyFormat("const struct Aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa = {\n"
" [1] = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
" [2] = bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
" [3] = cccccccccccccccccccccccccccccccccccccc,\n"
" [4] = dddddddddddddddddddddddddddddddddddddd,\n"
" [5] = eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee};");
}
TEST_F(FormatTest, NestedStaticInitializers) {
verifyFormat("static A x = {{{}}};\n");
verifyFormat("static A x = {{{init1, init2, init3, init4},\n"
" {init1, init2, init3, init4}}};",
getLLVMStyleWithColumns(50));
verifyFormat("somes Status::global_reps[3] = {\n"
" {kGlobalRef, OK_CODE, NULL, NULL, NULL},\n"
" {kGlobalRef, CANCELLED_CODE, NULL, NULL, NULL},\n"
" {kGlobalRef, UNKNOWN_CODE, NULL, NULL, NULL}};",
getLLVMStyleWithColumns(60));
verifyGoogleFormat("SomeType Status::global_reps[3] = {\n"
" {kGlobalRef, OK_CODE, NULL, NULL, NULL},\n"
" {kGlobalRef, CANCELLED_CODE, NULL, NULL, NULL},\n"
" {kGlobalRef, UNKNOWN_CODE, NULL, NULL, NULL}};");
verifyFormat("CGRect cg_rect = {{rect.fLeft, rect.fTop},\n"
" {rect.fRight - rect.fLeft, rect.fBottom - "
"rect.fTop}};");
verifyFormat(
"SomeArrayOfSomeType a = {\n"
" {{1, 2, 3},\n"
" {1, 2, 3},\n"
" {111111111111111111111111111111, 222222222222222222222222222222,\n"
" 333333333333333333333333333333},\n"
" {1, 2, 3},\n"
" {1, 2, 3}}};");
verifyFormat(
"SomeArrayOfSomeType a = {\n"
" {{1, 2, 3}},\n"
" {{1, 2, 3}},\n"
" {{111111111111111111111111111111, 222222222222222222222222222222,\n"
" 333333333333333333333333333333}},\n"
" {{1, 2, 3}},\n"
" {{1, 2, 3}}};");
verifyFormat("struct {\n"
" unsigned bit;\n"
" const char *const name;\n"
"} kBitsToOs[] = {{kOsMac, \"Mac\"},\n"
" {kOsWin, \"Windows\"},\n"
" {kOsLinux, \"Linux\"},\n"
" {kOsCrOS, \"Chrome OS\"}};");
verifyFormat("struct {\n"
" unsigned bit;\n"
" const char *const name;\n"
"} kBitsToOs[] = {\n"
" {kOsMac, \"Mac\"},\n"
" {kOsWin, \"Windows\"},\n"
" {kOsLinux, \"Linux\"},\n"
" {kOsCrOS, \"Chrome OS\"},\n"
"};");
}
TEST_F(FormatTest, FormatsSmallMacroDefinitionsInSingleLine) {
verifyFormat("#define ALooooooooooooooooooooooooooooooooooooooongMacro("
" \\\n"
" aLoooooooooooooooooooooooongFuuuuuuuuuuuuuunctiooooooooo)");
}
TEST_F(FormatTest, DoesNotBreakPureVirtualFunctionDefinition) {
verifyFormat("virtual void write(ELFWriter *writerrr,\n"
" OwningPtr<FileOutputBuffer> &buffer) = 0;");
// Do break defaulted and deleted functions.
verifyFormat("virtual void ~Deeeeeeeestructor() =\n"
" default;",
getLLVMStyleWithColumns(40));
verifyFormat("virtual void ~Deeeeeeeestructor() =\n"
" delete;",
getLLVMStyleWithColumns(40));
}
TEST_F(FormatTest, BreaksStringLiteralsOnlyInDefine) {
verifyFormat("# 1111 \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/aaaaaaaa.cpp\" 2 3",
getLLVMStyleWithColumns(40));
verifyFormat("#line 11111 \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/aaaaaaaa.cpp\"",
getLLVMStyleWithColumns(40));
EXPECT_EQ("#define Q \\\n"
" \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/\" \\\n"
" \"aaaaaaaa.cpp\"",
format("#define Q \"/aaaaaaaaa/aaaaaaaaaaaaaaaaaaa/aaaaaaaa.cpp\"",
getLLVMStyleWithColumns(40)));
}
TEST_F(FormatTest, UnderstandsLinePPDirective) {
EXPECT_EQ("# 123 \"A string literal\"",
format(" # 123 \"A string literal\""));
}
TEST_F(FormatTest, LayoutUnknownPPDirective) {
EXPECT_EQ("#;", format("#;"));
verifyFormat("#\n;\n;\n;");
}
TEST_F(FormatTest, UnescapedEndOfLineEndsPPDirective) {
EXPECT_EQ("#line 42 \"test\"\n",
format("# \\\n line \\\n 42 \\\n \"test\"\n"));
EXPECT_EQ("#define A B\n", format("# \\\n define \\\n A \\\n B\n",
getLLVMStyleWithColumns(12)));
}
TEST_F(FormatTest, EndOfFileEndsPPDirective) {
EXPECT_EQ("#line 42 \"test\"",
format("# \\\n line \\\n 42 \\\n \"test\""));
EXPECT_EQ("#define A B", format("# \\\n define \\\n A \\\n B"));
}
TEST_F(FormatTest, DoesntRemoveUnknownTokens) {
verifyFormat("#define A \\x20");
verifyFormat("#define A \\ x20");
EXPECT_EQ("#define A \\ x20", format("#define A \\ x20"));
verifyFormat("#define A ''");
verifyFormat("#define A ''qqq");
verifyFormat("#define A `qqq");
verifyFormat("f(\"aaaa, bbbb, \"\\\"ccccc\\\"\");");
EXPECT_EQ("const char *c = STRINGIFY(\n"
"\\na : b);",
format("const char * c = STRINGIFY(\n"
"\\na : b);"));
verifyFormat("a\r\\");
verifyFormat("a\v\\");
verifyFormat("a\f\\");
}
TEST_F(FormatTest, IndentsPPDirectiveInReducedSpace) {
verifyFormat("#define A(BB)", getLLVMStyleWithColumns(13));
verifyFormat("#define A( \\\n BB)", getLLVMStyleWithColumns(12));
verifyFormat("#define A( \\\n A, B)", getLLVMStyleWithColumns(12));
// FIXME: We never break before the macro name.
verifyFormat("#define AA( \\\n B)", getLLVMStyleWithColumns(12));
verifyFormat("#define A A\n#define A A");
verifyFormat("#define A(X) A\n#define A A");
verifyFormat("#define Something Other", getLLVMStyleWithColumns(23));
verifyFormat("#define Something \\\n Other", getLLVMStyleWithColumns(22));
}
TEST_F(FormatTest, HandlePreprocessorDirectiveContext) {
EXPECT_EQ("// somecomment\n"
"#include \"a.h\"\n"
"#define A( \\\n"
" A, B)\n"
"#include \"b.h\"\n"
"// somecomment\n",
format(" // somecomment\n"
" #include \"a.h\"\n"
"#define A(A,\\\n"
" B)\n"
" #include \"b.h\"\n"
" // somecomment\n",
getLLVMStyleWithColumns(13)));
}
TEST_F(FormatTest, LayoutSingleHash) { EXPECT_EQ("#\na;", format("#\na;")); }
TEST_F(FormatTest, LayoutCodeInMacroDefinitions) {
EXPECT_EQ("#define A \\\n"
" c; \\\n"
" e;\n"
"f;",
format("#define A c; e;\n"
"f;",
getLLVMStyleWithColumns(14)));
}
TEST_F(FormatTest, LayoutRemainingTokens) { EXPECT_EQ("{}", format("{}")); }
TEST_F(FormatTest, MacroDefinitionInsideStatement) {
EXPECT_EQ("int x,\n"
"#define A\n"
" y;",
format("int x,\n#define A\ny;"));
}
TEST_F(FormatTest, HashInMacroDefinition) {
EXPECT_EQ("#define A(c) L#c", format("#define A(c) L#c", getLLVMStyle()));
verifyFormat("#define A \\\n b #c;", getLLVMStyleWithColumns(11));
verifyFormat("#define A \\\n"
" { \\\n"
" f(#c); \\\n"
" }",
getLLVMStyleWithColumns(11));
verifyFormat("#define A(X) \\\n"
" void function##X()",
getLLVMStyleWithColumns(22));
verifyFormat("#define A(a, b, c) \\\n"
" void a##b##c()",
getLLVMStyleWithColumns(22));
verifyFormat("#define A void # ## #", getLLVMStyleWithColumns(22));
}
TEST_F(FormatTest, RespectWhitespaceInMacroDefinitions) {
EXPECT_EQ("#define A (x)", format("#define A (x)"));
EXPECT_EQ("#define A(x)", format("#define A(x)"));
FormatStyle Style = getLLVMStyle();
Style.SpaceBeforeParens = FormatStyle::SBPO_Never;
verifyFormat("#define true ((foo)1)", Style);
Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
verifyFormat("#define false((foo)0)", Style);
}
TEST_F(FormatTest, EmptyLinesInMacroDefinitions) {
EXPECT_EQ("#define A b;", format("#define A \\\n"
" \\\n"
" b;",
getLLVMStyleWithColumns(25)));
EXPECT_EQ("#define A \\\n"
" \\\n"
" a; \\\n"
" b;",
format("#define A \\\n"
" \\\n"
" a; \\\n"
" b;",
getLLVMStyleWithColumns(11)));
EXPECT_EQ("#define A \\\n"
" a; \\\n"
" \\\n"
" b;",
format("#define A \\\n"
" a; \\\n"
" \\\n"
" b;",
getLLVMStyleWithColumns(11)));
}
TEST_F(FormatTest, MacroDefinitionsWithIncompleteCode) {
verifyIncompleteFormat("#define A :");
verifyFormat("#define SOMECASES \\\n"
" case 1: \\\n"
" case 2\n",
getLLVMStyleWithColumns(20));
verifyFormat("#define MACRO(a) \\\n"
" if (a) \\\n"
" f(); \\\n"
" else \\\n"
" g()",
getLLVMStyleWithColumns(18));
verifyFormat("#define A template <typename T>");
verifyIncompleteFormat("#define STR(x) #x\n"
"f(STR(this_is_a_string_literal{));");
verifyFormat("#pragma omp threadprivate( \\\n"
" y)), // expected-warning",
getLLVMStyleWithColumns(28));
verifyFormat("#d, = };");
verifyFormat("#if \"a");
verifyIncompleteFormat("({\n"
"#define b \\\n"
" } \\\n"
" a\n"
"a",
getLLVMStyleWithColumns(15));
verifyFormat("#define A \\\n"
" { \\\n"
" {\n"
"#define B \\\n"
" } \\\n"
" }",
getLLVMStyleWithColumns(15));
verifyNoCrash("#if a\na(\n#else\n#endif\n{a");
verifyNoCrash("a={0,1\n#if a\n#else\n;\n#endif\n}");
verifyNoCrash("#if a\na(\n#else\n#endif\n) a {a,b,c,d,f,g};");
verifyNoCrash("#ifdef A\n a(\n #else\n #endif\n) = []() { \n)}");
}
TEST_F(FormatTest, MacrosWithoutTrailingSemicolon) {
verifyFormat("SOME_TYPE_NAME abc;"); // Gated on the newline.
EXPECT_EQ("class A : public QObject {\n"
" Q_OBJECT\n"
"\n"
" A() {}\n"
"};",
format("class A : public QObject {\n"
" Q_OBJECT\n"
"\n"
" A() {\n}\n"
"} ;"));
EXPECT_EQ("MACRO\n"
"/*static*/ int i;",
format("MACRO\n"
" /*static*/ int i;"));
EXPECT_EQ("SOME_MACRO\n"
"namespace {\n"
"void f();\n"
"} // namespace",
format("SOME_MACRO\n"
" namespace {\n"
"void f( );\n"
"} // namespace"));
// Only if the identifier contains at least 5 characters.
EXPECT_EQ("HTTP f();", format("HTTP\nf();"));
EXPECT_EQ("MACRO\nf();", format("MACRO\nf();"));
// Only if everything is upper case.
EXPECT_EQ("class A : public QObject {\n"
" Q_Object A() {}\n"
"};",
format("class A : public QObject {\n"
" Q_Object\n"
" A() {\n}\n"
"} ;"));
// Only if the next line can actually start an unwrapped line.
EXPECT_EQ("SOME_WEIRD_LOG_MACRO << SomeThing;",
format("SOME_WEIRD_LOG_MACRO\n"
"<< SomeThing;"));
verifyFormat("VISIT_GL_CALL(GenBuffers, void, (GLsizei n, GLuint* buffers), "
"(n, buffers))\n",
getChromiumStyle(FormatStyle::LK_Cpp));
// See PR41483
EXPECT_EQ("/**/ FOO(a)\n"
"FOO(b)",
format("/**/ FOO(a)\n"
"FOO(b)"));
}
TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) {
EXPECT_EQ("INITIALIZE_PASS_BEGIN(ScopDetection, \"polly-detect\")\n"
"INITIALIZE_AG_DEPENDENCY(AliasAnalysis)\n"
"INITIALIZE_PASS_DEPENDENCY(DominatorTree)\n"
"class X {};\n"
"INITIALIZE_PASS_END(ScopDetection, \"polly-detect\")\n"
"int *createScopDetectionPass() { return 0; }",
format(" INITIALIZE_PASS_BEGIN(ScopDetection, \"polly-detect\")\n"
" INITIALIZE_AG_DEPENDENCY(AliasAnalysis)\n"
" INITIALIZE_PASS_DEPENDENCY(DominatorTree)\n"
" class X {};\n"
" INITIALIZE_PASS_END(ScopDetection, \"polly-detect\")\n"
" int *createScopDetectionPass() { return 0; }"));
// FIXME: We could probably treat IPC_BEGIN_MESSAGE_MAP/IPC_END_MESSAGE_MAP as
// braces, so that inner block is indented one level more.
EXPECT_EQ("int q() {\n"
" IPC_BEGIN_MESSAGE_MAP(WebKitTestController, message)\n"
" IPC_MESSAGE_HANDLER(xxx, qqq)\n"
" IPC_END_MESSAGE_MAP()\n"
"}",
format("int q() {\n"
" IPC_BEGIN_MESSAGE_MAP(WebKitTestController, message)\n"
" IPC_MESSAGE_HANDLER(xxx, qqq)\n"
" IPC_END_MESSAGE_MAP()\n"
"}"));
// Same inside macros.
EXPECT_EQ("#define LIST(L) \\\n"
" L(A) \\\n"
" L(B) \\\n"
" L(C)",
format("#define LIST(L) \\\n"
" L(A) \\\n"
" L(B) \\\n"
" L(C)",
getGoogleStyle()));
// These must not be recognized as macros.
EXPECT_EQ("int q() {\n"
" f(x);\n"
" f(x) {}\n"
" f(x)->g();\n"
" f(x)->*g();\n"
" f(x).g();\n"
" f(x) = x;\n"
" f(x) += x;\n"
" f(x) -= x;\n"
" f(x) *= x;\n"
" f(x) /= x;\n"
" f(x) %= x;\n"
" f(x) &= x;\n"
" f(x) |= x;\n"
" f(x) ^= x;\n"
" f(x) >>= x;\n"
" f(x) <<= x;\n"
" f(x)[y].z();\n"
" LOG(INFO) << x;\n"
" ifstream(x) >> x;\n"
"}\n",
format("int q() {\n"
" f(x)\n;\n"
" f(x)\n {}\n"
" f(x)\n->g();\n"
" f(x)\n->*g();\n"
" f(x)\n.g();\n"
" f(x)\n = x;\n"
" f(x)\n += x;\n"
" f(x)\n -= x;\n"
" f(x)\n *= x;\n"
" f(x)\n /= x;\n"
" f(x)\n %= x;\n"
" f(x)\n &= x;\n"
" f(x)\n |= x;\n"
" f(x)\n ^= x;\n"
" f(x)\n >>= x;\n"
" f(x)\n <<= x;\n"
" f(x)\n[y].z();\n"
" LOG(INFO)\n << x;\n"
" ifstream(x)\n >> x;\n"
"}\n"));
EXPECT_EQ("int q() {\n"
" F(x)\n"
" if (1) {\n"
" }\n"
" F(x)\n"
" while (1) {\n"
" }\n"
" F(x)\n"
" G(x);\n"
" F(x)\n"
" try {\n"
" Q();\n"
" } catch (...) {\n"
" }\n"
"}\n",
format("int q() {\n"
"F(x)\n"
"if (1) {}\n"
"F(x)\n"
"while (1) {}\n"
"F(x)\n"
"G(x);\n"
"F(x)\n"
"try { Q(); } catch (...) {}\n"
"}\n"));
EXPECT_EQ("class A {\n"
" A() : t(0) {}\n"
" A(int i) noexcept() : {}\n"
" A(X x)\n" // FIXME: function-level try blocks are broken.
" try : t(0) {\n"
" } catch (...) {\n"
" }\n"
"};",
format("class A {\n"
" A()\n : t(0) {}\n"
" A(int i)\n noexcept() : {}\n"
" A(X x)\n"
" try : t(0) {} catch (...) {}\n"
"};"));
FormatStyle Style = getLLVMStyle();
Style.BreakBeforeBraces = FormatStyle::BS_Custom;
Style.BraceWrapping.AfterControlStatement = true;
Style.BraceWrapping.AfterFunction = true;
EXPECT_EQ("void f()\n"
"try\n"
"{\n"
"}",
format("void f() try {\n"
"}", Style));
EXPECT_EQ("class SomeClass {\n"
"public:\n"
" SomeClass() EXCLUSIVE_LOCK_FUNCTION(mu_);\n"
"};",
format("class SomeClass {\n"
"public:\n"
" SomeClass()\n"
" EXCLUSIVE_LOCK_FUNCTION(mu_);\n"
"};"));
EXPECT_EQ("class SomeClass {\n"
"public:\n"
" SomeClass()\n"
" EXCLUSIVE_LOCK_FUNCTION(mu_);\n"
"};",
format("class SomeClass {\n"
"public:\n"
" SomeClass()\n"
" EXCLUSIVE_LOCK_FUNCTION(mu_);\n"
"};",
getLLVMStyleWithColumns(40)));
verifyFormat("MACRO(>)");
// Some macros contain an implicit semicolon.
Style = getLLVMStyle();
Style.StatementMacros.push_back("FOO");
verifyFormat("FOO(a) int b = 0;");
verifyFormat("FOO(a)\n"
"int b = 0;",
Style);
verifyFormat("FOO(a);\n"
"int b = 0;",
Style);
verifyFormat("FOO(argc, argv, \"4.0.2\")\n"
"int b = 0;",
Style);
verifyFormat("FOO()\n"
"int b = 0;",
Style);
verifyFormat("FOO\n"
"int b = 0;",
Style);
verifyFormat("void f() {\n"
" FOO(a)\n"
" return a;\n"
"}",
Style);
verifyFormat("FOO(a)\n"
"FOO(b)",
Style);
verifyFormat("int a = 0;\n"
"FOO(b)\n"
"int c = 0;",
Style);
verifyFormat("int a = 0;\n"
"int x = FOO(a)\n"
"int b = 0;",
Style);
verifyFormat("void foo(int a) { FOO(a) }\n"
"uint32_t bar() {}",
Style);
}
TEST_F(FormatTest, LayoutMacroDefinitionsStatementsSpanningBlocks) {
verifyFormat("#define A \\\n"
" f({ \\\n"
" g(); \\\n"
" });",
getLLVMStyleWithColumns(11));
}
TEST_F(FormatTest, IndentPreprocessorDirectives) {
FormatStyle Style = getLLVMStyle();
Style.IndentPPDirectives = FormatStyle::PPDIS_None;
Style.ColumnLimit = 40;
verifyFormat("#ifdef _WIN32\n"
"#define A 0\n"
"#ifdef VAR2\n"
"#define B 1\n"
"#include <someheader.h>\n"
"#define MACRO \\\n"
" some_very_long_func_aaaaaaaaaa();\n"
"#endif\n"
"#else\n"
"#define A 1\n"
"#endif",
Style);
Style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash;
verifyFormat("#ifdef _WIN32\n"
"# define A 0\n"
"# ifdef VAR2\n"
"# define B 1\n"
"# include <someheader.h>\n"
"# define MACRO \\\n"
" some_very_long_func_aaaaaaaaaa();\n"
"# endif\n"
"#else\n"
"# define A 1\n"
"#endif",
Style);
verifyFormat("#if A\n"
"# define MACRO \\\n"
" void a(int x) { \\\n"
" b(); \\\n"
" c(); \\\n"
" d(); \\\n"
" e(); \\\n"
" f(); \\\n"
" }\n"
"#endif",
Style);
// Comments before include guard.
verifyFormat("// file comment\n"
"// file comment\n"
"#ifndef HEADER_H\n"
"#define HEADER_H\n"
"code();\n"
"#endif",
Style);
// Test with include guards.
verifyFormat("#ifndef HEADER_H\n"
"#define HEADER_H\n"
"code();\n"
"#endif",
Style);
// Include guards must have a #define with the same variable immediately
// after #ifndef.
verifyFormat("#ifndef NOT_GUARD\n"
"# define FOO\n"
"code();\n"
"#endif",
Style);
// Include guards must cover the entire file.
verifyFormat("code();\n"
"code();\n"
"#ifndef NOT_GUARD\n"
"# define NOT_GUARD\n"
"code();\n"
"#endif",
Style);
verifyFormat("#ifndef NOT_GUARD\n"
"# define NOT_GUARD\n"
"code();\n"
"#endif\n"
"code();",
Style);
// Test with trailing blank lines.
verifyFormat("#ifndef HEADER_H\n"
"#define HEADER_H\n"
"code();\n"
"#endif\n",
Style);
// Include guards don't have #else.
verifyFormat("#ifndef NOT_GUARD\n"
"# define NOT_GUARD\n"
"code();\n"
"#else\n"
"#endif",
Style);
verifyFormat("#ifndef NOT_GUARD\n"
"# define NOT_GUARD\n"
"code();\n"
"#elif FOO\n"
"#endif",
Style);
// Non-identifier #define after potential include guard.
verifyFormat("#ifndef FOO\n"
"# define 1\n"
"#endif\n",
Style);
// #if closes past last non-preprocessor line.
verifyFormat("#ifndef FOO\n"
"#define FOO\n"
"#if 1\n"
"int i;\n"
"# define A 0\n"
"#endif\n"
"#endif\n",
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
// previous code line yet, so we can't detect it.
EXPECT_EQ("#ifndef NOT_GUARD\n"
"code();\n"
"#define NOT_GUARD\n"
"code();\n"
"#endif",
format("#ifndef NOT_GUARD\n"
"code();\n"
"# define NOT_GUARD\n"
"code();\n"
"#endif",
Style));
// FIXME: This doesn't handle cases where legitimate preprocessor lines may
// be outside an include guard. Examples are #pragma once and
// #pragma GCC diagnostic, or anything else that does not change the meaning
// of the file if it's included multiple times.
EXPECT_EQ("#ifdef WIN32\n"
"# pragma once\n"
"#endif\n"
"#ifndef HEADER_H\n"
"# define HEADER_H\n"
"code();\n"
"#endif",
format("#ifdef WIN32\n"
"# pragma once\n"
"#endif\n"
"#ifndef HEADER_H\n"
"#define HEADER_H\n"
"code();\n"
"#endif",
Style));
// FIXME: This does not detect when there is a single non-preprocessor line
// in front of an include-guard-like structure where other conditions hold
// because ScopedLineState hides the line.
EXPECT_EQ("code();\n"
"#ifndef HEADER_H\n"
"#define HEADER_H\n"
"code();\n"
"#endif",
format("code();\n"
"#ifndef HEADER_H\n"
"# define HEADER_H\n"
"code();\n"
"#endif",
Style));
// Keep comments aligned with #, otherwise indent comments normally. These
// tests cannot use verifyFormat because messUp manipulates leading
// whitespace.
{
const char *Expected = ""
"void f() {\n"
"#if 1\n"
"// Preprocessor aligned.\n"
"# define A 0\n"
" // Code. Separated by blank line.\n"
"\n"
"# define B 0\n"
" // Code. Not aligned with #\n"
"# define C 0\n"
"#endif";
const char *ToFormat = ""
"void f() {\n"
"#if 1\n"
"// Preprocessor aligned.\n"
"# define A 0\n"
"// Code. Separated by blank line.\n"
"\n"
"# define B 0\n"
" // Code. Not aligned with #\n"
"# define C 0\n"
"#endif";
EXPECT_EQ(Expected, format(ToFormat, Style));
EXPECT_EQ(Expected, format(Expected, Style));
}
// Keep block quotes aligned.
{
const char *Expected = ""
"void f() {\n"
"#if 1\n"
"/* Preprocessor aligned. */\n"
"# define A 0\n"
" /* Code. Separated by blank line. */\n"
"\n"
"# define B 0\n"
" /* Code. Not aligned with # */\n"
"# define C 0\n"
"#endif";
const char *ToFormat = ""
"void f() {\n"
"#if 1\n"
"/* Preprocessor aligned. */\n"
"# define A 0\n"
"/* Code. Separated by blank line. */\n"
"\n"
"# define B 0\n"
" /* Code. Not aligned with # */\n"
"# define C 0\n"
"#endif";
EXPECT_EQ(Expected, format(ToFormat, Style));
EXPECT_EQ(Expected, format(Expected, Style));
}
// Keep comments aligned with un-indented directives.
{
const char *Expected = ""
"void f() {\n"
"// Preprocessor aligned.\n"
"#define A 0\n"
" // Code. Separated by blank line.\n"
"\n"
"#define B 0\n"
" // Code. Not aligned with #\n"
"#define C 0\n";
const char *ToFormat = ""
"void f() {\n"
"// Preprocessor aligned.\n"
"#define A 0\n"
"// Code. Separated by blank line.\n"
"\n"
"#define B 0\n"
" // Code. Not aligned with #\n"
"#define C 0\n";
EXPECT_EQ(Expected, format(ToFormat, Style));
EXPECT_EQ(Expected, format(Expected, Style));
}
// Test AfterHash with tabs.
{
FormatStyle Tabbed = Style;
Tabbed.UseTab = FormatStyle::UT_Always;
Tabbed.IndentWidth = 8;
Tabbed.TabWidth = 8;
verifyFormat("#ifdef _WIN32\n"
"#\tdefine A 0\n"
"#\tifdef VAR2\n"