Index: clang/lib/Format/TokenAnnotator.h =================================================================== --- clang/lib/Format/TokenAnnotator.h +++ clang/lib/Format/TokenAnnotator.h @@ -99,9 +99,21 @@ /// function declaration. Asserts MightBeFunctionDecl. bool mightBeFunctionDefinition() const { assert(MightBeFunctionDecl); - // FIXME: Line.Last points to other characters than tok::semi - // and tok::lbrace. - return !Last->isOneOf(tok::semi, tok::comment); + // Try to determine if the end of a stream of tokens is either the + // Definition or the Declaration for a function. It does this by looking for + // the ';' in foo(); and using that it ends with a ; to know this is the + // Definition, however the line could end with + // foo(); /* comment */ + // or + // foo(); // comment + // or + // foo() // comment + // In all cases the last token would be a comment (old way) but a definition + // like the last one means you must look at the last two tokens to + // ensure its not `; `. + return Last->isNot(tok::semi) && + (Last->Previous && + !Last->Previous->startsSequence(tok::semi, tok::comment)); } /// \c true if this line starts a namespace definition. Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -5745,6 +5745,72 @@ " return a;\n" "}\n", Style); + + Style = getGNUStyle(); + // Test for comments at the define of function definitions and declarations. + + verifyFormat("void\n" + "foo (int a, /*abc*/ int b // def\n" + ")\n" + "{\n" + "}\n", + Style); + + verifyFormat("void\n" + "foo (int a, /*abc*/ int b) // def\n" + "{\n" + "}\n", + Style); + + verifyFormat("void\n" + "foo (int a, // abc\n" + " int b) // def\n" + "{\n" + "}\n", + Style); + + verifyFormat("void\n" + "foo (int a, /*abc*/ int b)\n" + "{\n" + "}\n", + Style); + + verifyFormat("void\n" + "foo (int a, /* abc */ int b) /* def */\n" + "{\n" + "}\n", + Style); + + verifyFormat("void\n" + "foo (int a, /*abc*/ int /*def=*/b)\n" + "{\n" + "}\n", + Style); + + verifyFormat("void\n" + "foo (int a, /*abc*/ int /*def=*/b)\n" + "{\n" + "}\n", + Style); + + // Definitions that should not break after return type + verifyFormat("void foo (int a, // abc\n" + " int /*def=*/b);\n", + Style); + verifyFormat("void foo (int a, // abc\n" + " int /*def=*/b); /* def */\n", + Style); + verifyFormat("void foo (int a, // abc\n" + " int /*def=*/b); // def\n", + Style); + + verifyFormat("void foo (int a, // abc\n" + " int b); // def\n", + Style); + + verifyFormat("void foo (int a, int b); // def\n", Style); + + verifyFormat("void foo (int a, int b); /* def */\n", Style); } TEST_F(FormatTest, AlwaysBreakBeforeMultilineStrings) {