jaredgrubb updated this revision to Diff 502390.
jaredgrubb added a comment.
Create unit-tests for the patch (and remove the proposed non-unit test "test").
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D145262/new/
https://reviews.llvm.org/D145262
Files:
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTestObjC.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp
Index: clang/unittests/Format/TokenAnnotatorTest.cpp
===================================================================
--- clang/unittests/Format/TokenAnnotatorTest.cpp
+++ clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -1292,6 +1292,34 @@
EXPECT_TOKEN(Tokens[9], tok::colon, TT_GenericSelectionColon);
}
+TEST_F(TokenAnnotatorTest, UnderstandsAttributeMacros) {
+ // '__attribute__' has special handling.
+ auto Tokens = annotate("__attribute__(X) void Foo(void);");
+ ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+ EXPECT_TOKEN(Tokens[0], tok::kw___attribute, TT_Unknown);
+ EXPECT_TOKEN(Tokens[1], tok::l_paren, TT_AttributeParen);
+ EXPECT_TOKEN(Tokens[3], tok::r_paren, TT_AttributeParen);
+
+ // Generic macro has no special handling in this location.
+ Tokens = annotate("A(X) void Foo(void);");
+ ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+ EXPECT_TOKEN(Tokens[0], tok::identifier, TT_Unknown);
+ EXPECT_TOKEN(Tokens[1], tok::l_paren, TT_Unknown);
+ // 'TT_FunctionAnnotationRParen' doesn't seem right; fix?
+ EXPECT_TOKEN(Tokens[3], tok::r_paren, TT_FunctionAnnotationRParen);
+
+ // Add a custom AttributeMacro. Test that it has the same behavior.
+ FormatStyle Style = getLLVMStyle();
+ Style.AttributeMacros.push_back("A");
+
+ // An "AttributeMacro" gets annotated like '__attribute__'.
+ Tokens = annotate("A(X) void Foo(void);", Style);
+ ASSERT_EQ(Tokens.size(), 11u) << Tokens;
+ EXPECT_TOKEN(Tokens[0], tok::identifier, TT_AttributeMacro);
+ EXPECT_TOKEN(Tokens[1], tok::l_paren, TT_AttributeParen);
+ EXPECT_TOKEN(Tokens[3], tok::r_paren, TT_AttributeParen);
+}
+
TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) {
auto Annotate = [this](llvm::StringRef Code) {
return annotate(Code, getLLVMStyle(FormatStyle::LK_Verilog));
Index: clang/unittests/Format/FormatTestObjC.cpp
===================================================================
--- clang/unittests/Format/FormatTestObjC.cpp
+++ clang/unittests/Format/FormatTestObjC.cpp
@@ -1489,6 +1489,9 @@
}
TEST_F(FormatTestObjC, Attributes) {
+ Style.AttributeMacros.push_back("ATTRIBUTE_MACRO");
+
+ // Check '__attribute__' macro directly.
verifyFormat("__attribute__((objc_subclassing_restricted))\n"
"@interface Foo\n"
"@end");
@@ -1498,6 +1501,41 @@
verifyFormat("__attribute__((objc_subclassing_restricted))\n"
"@implementation Foo\n"
"@end");
+
+ // Check AttributeMacro gets treated the same, with or without parentheses.
+ verifyFormat("ATTRIBUTE_MACRO\n"
+ "@interface Foo\n"
+ "@end");
+ verifyFormat("ATTRIBUTE_MACRO(X)\n"
+ "@interface Foo\n"
+ "@end");
+
+ // Indenter also needs to understand multiple attribute macros.
+ verifyFormat("ATTRIBUTE_MACRO(X) ATTRIBUTE_MACRO\n"
+ "@interface Foo\n"
+ "@end");
+ verifyFormat("ATTRIBUTE_MACRO ATTRIBUTE_MACRO(X)\n"
+ "@interface Foo\n"
+ "@end");
+
+ Style.ColumnLimit = 30;
+ verifyFormat("ATTRIBUTE_MACRO(X)\n"
+ "ATTRIBUTE_MACRO\n"
+ "@interface Foo\n"
+ "@end");
+ // Note: the following -should- break across multiple lines, but doesn't.
+ // This is added to acknowledge the behavior, but it should be improved.
+ verifyFormat("ATTRIBUTE_MACRO ATTRIBUTE_MACRO(X)\n"
+ "@interface Foo\n"
+ "@end");
+
+ Style.ColumnLimit = 0;
+ verifyFormat("ATTRIBUTE_MACRO(X) ATTRIBUTE_MACRO\n"
+ "@interface Foo\n"
+ "@end");
+ verifyFormat("ATTRIBUTE_MACRO ATTRIBUTE_MACRO(X)\n"
+ "@interface Foo\n"
+ "@end");
}
} // end namespace
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -369,7 +369,7 @@
// Infer the role of the l_paren based on the previous token if we haven't
// detected one yet.
if (PrevNonComment && OpeningParen.is(TT_Unknown)) {
- if (PrevNonComment->is(tok::kw___attribute)) {
+ if (PrevNonComment->isOneOf(tok::kw___attribute, TT_AttributeMacro)) {
OpeningParen.setType(TT_AttributeParen);
} else if (PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype,
tok::kw_typeof,
@@ -4889,8 +4889,10 @@
}
// Ensure wrapping after __attribute__((XX)) and @interface etc.
- if (Left.is(TT_AttributeParen) && Right.is(TT_ObjCDecl))
+ if (Left.isOneOf(TT_AttributeMacro, TT_AttributeParen) &&
+ Right.is(TT_ObjCDecl)) {
return true;
+ }
if (Left.is(TT_LambdaLBrace)) {
if (IsFunctionArgument(Left) &&
Index: clang/lib/Format/ContinuationIndenter.cpp
===================================================================
--- clang/lib/Format/ContinuationIndenter.cpp
+++ clang/lib/Format/ContinuationIndenter.cpp
@@ -1228,8 +1228,9 @@
(PreviousNonComment->ClosesTemplateDeclaration ||
PreviousNonComment->ClosesRequiresClause ||
PreviousNonComment->isOneOf(
- TT_AttributeParen, TT_AttributeSquare, TT_FunctionAnnotationRParen,
- TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
+ TT_AttributeParen, TT_AttributeMacro, TT_AttributeSquare,
+ TT_FunctionAnnotationRParen, TT_JavaAnnotation,
+ TT_LeadingJavaAnnotation))) ||
(!Style.IndentWrappedFunctionNames &&
NextNonComment->isOneOf(tok::kw_operator, TT_FunctionDeclarationName))) {
return std::max(CurrentState.LastSpace, CurrentState.Indent);
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits