diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp index 4bc865b043fd2..8e4994f4c0d57 100644 --- a/clang/lib/Format/FormatToken.cpp +++ b/clang/lib/Format/FormatToken.cpp @@ -62,6 +62,7 @@ bool FormatToken::isSimpleTypeSpecifier() const { case tok::kw_char32_t: case tok::kw_typeof: case tok::kw_decltype: + case tok::kw__Atomic: return true; default: return false; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index a9aeef5e9e52f..8253bf18fc667 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -101,8 +101,8 @@ namespace format { TYPE(TrailingAnnotation) \ TYPE(TrailingReturnArrow) \ TYPE(TrailingUnaryOperator) \ + TYPE(TypeDeclarationParen) \ TYPE(TypenameMacro) \ - TYPE(TypenameMacroParen) \ TYPE(UnaryOperator) \ TYPE(UntouchableMacroFunc) \ TYPE(CSharpStringLiteral) \ @@ -526,6 +526,7 @@ struct FormatToken { case tok::kw_decltype: case tok::kw_noexcept: case tok::kw_static_assert: + case tok::kw__Atomic: case tok::kw___attribute: return true; default: diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 097843bdca84d..0239dbd63d94e 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -185,6 +185,8 @@ class AnnotatingParser { if (!CurrentToken) return false; FormatToken *Left = CurrentToken->Previous; + FormatToken *PrevNonComment = + Left ? Left->getPreviousNonComment() : nullptr; Left->ParentBracket = Contexts.back().ContextKind; ScopedContextCreator ContextCreator(*this, tok::l_paren, 1); @@ -216,9 +218,8 @@ class AnnotatingParser { // export type X = (...); Contexts.back().IsExpression = false; } else if (Left->Previous && - (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype, - tok::kw_while, tok::l_paren, - tok::comma) || + (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_while, + tok::l_paren, tok::comma) || Left->Previous->isIf() || Left->Previous->is(TT_BinaryOperator))) { // static_assert, if and while usually contain expressions. @@ -242,10 +243,15 @@ class AnnotatingParser { } else if (Contexts[Contexts.size() - 2].CaretFound) { // This is the parameter list of an ObjC block. Contexts.back().IsExpression = false; - } else if (Left->Previous && Left->Previous->is(tok::kw___attribute)) { + } else if (PrevNonComment && PrevNonComment->is(tok::kw___attribute)) { Left->setType(TT_AttributeParen); - } else if (Left->Previous && Left->Previous->is(TT_TypenameMacro)) { - Left->setType(TT_TypenameMacroParen); + } else if (PrevNonComment && + PrevNonComment->isOneOf(TT_TypenameMacro, tok::kw_decltype, + tok::kw_typeof, tok::kw__Atomic)) { + Left->setType(TT_TypeDeclarationParen); + // decltype() and typeof() usually contain expressions. + if (PrevNonComment->isOneOf(tok::kw_decltype, tok::kw_typeof)) + Contexts.back().IsExpression = true; } else if (Left->Previous && Left->Previous->is(TT_ForEachMacro)) { // The first argument to a foreach macro is a declaration. Contexts.back().IsForEachMacro = true; @@ -337,8 +343,8 @@ class AnnotatingParser { if (Left->is(TT_AttributeParen)) CurrentToken->setType(TT_AttributeParen); - if (Left->is(TT_TypenameMacroParen)) - CurrentToken->setType(TT_TypenameMacroParen); + if (Left->is(TT_TypeDeclarationParen)) + CurrentToken->setType(TT_TypeDeclarationParen); if (Left->Previous && Left->Previous->is(TT_JavaAnnotation)) CurrentToken->setType(TT_JavaAnnotation); if (Left->Previous && Left->Previous->is(TT_LeadingJavaAnnotation)) @@ -944,9 +950,9 @@ class AnnotatingParser { return false; if (Line.MustBeDeclaration && Contexts.size() == 1 && !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) && - (!Tok->Previous || - !Tok->Previous->isOneOf(tok::kw_decltype, tok::kw___attribute, - TT_LeadingJavaAnnotation))) + !Tok->is(TT_TypeDeclarationParen) && + (!Tok->Previous || !Tok->Previous->isOneOf(tok::kw___attribute, + TT_LeadingJavaAnnotation))) Line.MightBeFunctionDecl = true; break; case tok::l_square: @@ -1758,9 +1764,8 @@ class AnnotatingParser { PreviousNotConst->MatchingParen->Previous->isNot(tok::period) && PreviousNotConst->MatchingParen->Previous->isNot(tok::kw_template); - if (PreviousNotConst->is(tok::r_paren) && PreviousNotConst->MatchingParen && - PreviousNotConst->MatchingParen->Previous && - PreviousNotConst->MatchingParen->Previous->is(tok::kw_decltype)) + if (PreviousNotConst->is(tok::r_paren) && + PreviousNotConst->is(TT_TypeDeclarationParen)) return true; return (!IsPPKeyword && @@ -1861,7 +1866,7 @@ class AnnotatingParser { }; bool ParensAreType = !Tok.Previous || - Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypenameMacroParen) || + Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || Tok.Previous->isSimpleTypeSpecifier() || IsQualifiedPointerOrReference(Tok.Previous); bool ParensCouldEndDecl = @@ -1931,6 +1936,9 @@ class AnnotatingParser { if (PrevToken->is(tok::coloncolon)) return TT_PointerOrReference; + if (PrevToken->is(tok::r_paren) && PrevToken->is(TT_TypeDeclarationParen)) + return TT_PointerOrReference; + if (PrevToken->isOneOf(tok::l_paren, tok::l_square, tok::l_brace, tok::comma, tok::semi, tok::kw_return, tok::colon, tok::equal, tok::kw_delete, tok::kw_sizeof, @@ -1946,15 +1954,6 @@ class AnnotatingParser { if (NextToken->isOneOf(tok::comma, tok::semi)) return TT_PointerOrReference; - if (PrevToken->is(tok::r_paren) && PrevToken->MatchingParen) { - FormatToken *TokenBeforeMatchingParen = - PrevToken->MatchingParen->getPreviousNonComment(); - if (TokenBeforeMatchingParen && - TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype, - TT_TypenameMacro)) - return TT_PointerOrReference; - } - if (PrevToken->Tok.isLiteral() || PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true, tok::kw_false, tok::r_brace) || @@ -2848,9 +2847,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return true; FormatToken *TokenBeforeMatchingParen = Left.MatchingParen->getPreviousNonComment(); - if (!TokenBeforeMatchingParen || - !TokenBeforeMatchingParen->isOneOf(tok::kw_typeof, tok::kw_decltype, - TT_TypenameMacro)) + if (!TokenBeforeMatchingParen || !Left.is(TT_TypeDeclarationParen)) return true; } return (Left.Tok.isLiteral() || @@ -3948,7 +3945,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, if (Left.is(tok::equal) && Right.is(tok::l_brace) && !Style.Cpp11BracedListStyle) return false; - if (Left.is(tok::l_paren) && Left.is(TT_AttributeParen)) + if (Left.is(tok::l_paren) && + Left.isOneOf(TT_AttributeParen, TT_TypeDeclarationParen)) return false; if (Left.is(tok::l_paren) && Left.Previous && (Left.Previous->isOneOf(TT_BinaryOperator, TT_CastRParen))) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 978c22c6ee69a..a5943847882fb 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -168,6 +168,8 @@ TEST_F(FormatTest, NestedNameSpecifiers) { verifyFormat("vector<::Type> v;"); verifyFormat("::ns::SomeFunction(::ns::SomeOtherFunction())"); verifyFormat("static constexpr bool Bar = decltype(bar())::value;"); + verifyFormat("static constexpr bool Bar = typeof(bar())::value;"); + verifyFormat("static constexpr bool Bar = _Atomic(bar())::value;"); verifyFormat("bool a = 2 < ::SomeFunction();"); verifyFormat("ALWAYS_INLINE ::std::string getName();"); verifyFormat("some::string getName();"); @@ -7904,7 +7906,10 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("auto PointerBinding = [](const char *S) {};"); verifyFormat("typedef typeof(int(int, int)) *MyFunc;"); verifyFormat("[](const decltype(*a) &value) {}"); + verifyFormat("[](const typeof(*a) &value) {}"); + verifyFormat("[](const _Atomic(a *) &value) {}"); verifyFormat("decltype(a * b) F();"); + verifyFormat("typeof(a * b) F();"); verifyFormat("#define MACRO() [](A *a) { return 1; }"); verifyFormat("Constructor() : member([](A *a, B *b) {}) {}"); verifyIndependentOfContext("typedef void (*f)(int *a);"); @@ -7970,6 +7975,8 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("delete *x;", Left); verifyFormat("typedef typeof(int(int, int))* MyFuncPtr;", Left); verifyFormat("[](const decltype(*a)* ptr) {}", Left); + verifyFormat("[](const typeof(*a)* ptr) {}", Left); + verifyFormat("[](const _Atomic(a*)* ptr) {}", Left); verifyFormat("typedef typeof /*comment*/ (int(int, int))* MyFuncPtr;", Left); verifyFormat("auto x(A&&, B&&, C&&) -> D;", Left); verifyFormat("auto x = [](A&&, B&&, C&&) -> D {};", Left); @@ -8066,6 +8073,8 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("foo();"); verifyFormat("foo();"); verifyFormat("decltype(*::std::declval()) void F();"); + verifyFormat("typeof(*::std::declval()) void F();"); + verifyFormat("_Atomic(*::std::declval()) void F();"); verifyFormat( "template ::value &&\n" @@ -8089,6 +8098,9 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyIndependentOfContext("MACRO(int *i);"); verifyIndependentOfContext("MACRO(auto *a);"); verifyIndependentOfContext("MACRO(const A *a);"); + verifyIndependentOfContext("MACRO(_Atomic(A) *a);"); + verifyIndependentOfContext("MACRO(decltype(A) *a);"); + verifyIndependentOfContext("MACRO(typeof(A) *a);"); verifyIndependentOfContext("MACRO(A *const a);"); verifyIndependentOfContext("MACRO(A *restrict a);"); verifyIndependentOfContext("MACRO(A *__restrict__ a);"); @@ -8639,6 +8651,10 @@ TEST_F(FormatTest, BreaksLongDeclarations) { "LooooooooooooooooooooooooooooooooooongFunctionDefinition() {}"); verifyFormat("decltype(LoooooooooooooooooooooooooooooooooooooooongName)\n" "LooooooooooooooooooooooooooooooooooongFunctionDefinition() {}"); + verifyFormat("typeof(LoooooooooooooooooooooooooooooooooooooooooongName)\n" + "LooooooooooooooooooooooooooooooooooongFunctionDefinition() {}"); + verifyFormat("_Atomic(LooooooooooooooooooooooooooooooooooooooooongName)\n" + "LooooooooooooooooooooooooooooooooooongFunctionDefinition() {}"); verifyFormat("LoooooooooooooooooooooooooooooooooooooooongReturnType\n" "LooooooooooooooooooooooooooongFunctionDeclaration(T... t);"); verifyFormat("LoooooooooooooooooooooooooooooooooooooooongReturnType\n" @@ -8988,6 +9004,8 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { verifyFormat("int foo(int i) { return fo1{}(i); }"); verifyFormat("int foo(int i) { return fo1{}(i); }"); verifyFormat("auto i = decltype(x){};"); + verifyFormat("auto i = typeof(x){};"); + verifyFormat("auto i = _Atomic(x){};"); verifyFormat("std::vector v = {1, 0 /* comment */};"); verifyFormat("Node n{1, Node{1000}, //\n" " 2};"); @@ -11580,6 +11598,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("auto i = std::make_unique(5);", NoSpace); verifyFormat("size_t x = sizeof(x);", NoSpace); verifyFormat("auto f(int x) -> decltype(x);", NoSpace); + verifyFormat("auto f(int x) -> typeof(x);", NoSpace); + verifyFormat("auto f(int x) -> _Atomic(x);", NoSpace); verifyFormat("int f(T x) noexcept(x.create());", NoSpace); verifyFormat("alignas(128) char a[128];", NoSpace); verifyFormat("size_t x = alignof(MyType);", NoSpace); @@ -11628,6 +11648,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("auto i = std::make_unique (5);", Space); verifyFormat("size_t x = sizeof (x);", Space); verifyFormat("auto f (int x) -> decltype (x);", Space); + verifyFormat("auto f (int x) -> typeof (x);", Space); + verifyFormat("auto f (int x) -> _Atomic (x);", Space); verifyFormat("int f (T x) noexcept (x.create ());", Space); verifyFormat("alignas (128) char a[128];", Space); verifyFormat("size_t x = alignof (MyType);", Space); @@ -11680,6 +11702,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { verifyFormat("auto i = std::make_unique (5);", SomeSpace); verifyFormat("size_t x = sizeof (x);", SomeSpace); verifyFormat("auto f (int x) -> decltype (x);", SomeSpace); + verifyFormat("auto f (int x) -> typeof (x);", SomeSpace); + verifyFormat("auto f (int x) -> _Atomic (x);", SomeSpace); verifyFormat("int f (T x) noexcept (x.create());", SomeSpace); verifyFormat("alignas (128) char a[128];", SomeSpace); verifyFormat("size_t x = alignof (MyType);", SomeSpace); @@ -14934,6 +14958,8 @@ TEST_F(FormatTest, FormatsLambdas) { "});")); verifyFormat("void f() {\n" " SomeFunction([](decltype(x), A *a) {});\n" + " SomeFunction([](typeof(x), A *a) {});\n" + " SomeFunction([](_Atomic(x), A *a) {});\n" "}"); verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" " [](const aaaaaaaaaa &a) { return a; });"); @@ -16575,6 +16601,45 @@ TEST_F(FormatTest, TypenameMacros) { verifyFormat("vector x;", Macros); } +TEST_F(FormatTest, AtomicQualifier) { + // Check that we treate _Atomic as a type and not a function call + FormatStyle Google = getGoogleStyleWithColumns(0); + verifyFormat("struct foo {\n" + " int a1;\n" + " _Atomic(a) a2;\n" + " _Atomic(_Atomic(int) *const) a3;\n" + "};", + Google); + verifyFormat("_Atomic(uint64_t) a;"); + verifyFormat("_Atomic(uint64_t) *a;"); + verifyFormat("_Atomic(uint64_t const *) *a;"); + verifyFormat("_Atomic(uint64_t *const) *a;"); + verifyFormat("_Atomic(const uint64_t *) *a;"); + verifyFormat("_Atomic(uint64_t) a;"); + verifyFormat("_Atomic(_Atomic(uint64_t)) a;"); + verifyFormat("_Atomic(_Atomic(uint64_t)) a, b;"); + verifyFormat("for (_Atomic(uint64_t) *a = NULL; a;) {\n}"); + verifyFormat("_Atomic(uint64_t) f(_Atomic(uint64_t) *arg);"); + + verifyFormat("_Atomic(uint64_t) *s(InitValue);"); + verifyFormat("_Atomic(uint64_t) *s{InitValue};"); + FormatStyle Style = getLLVMStyle(); + Style.PointerAlignment = FormatStyle::PAS_Left; + verifyFormat("_Atomic(uint64_t)* s(InitValue);", Style); + verifyFormat("_Atomic(uint64_t)* s{InitValue};", Style); + verifyFormat("_Atomic(int)* a;", Style); + verifyFormat("_Atomic(int*)* a;", Style); + verifyFormat("vector<_Atomic(uint64_t)* attr> x;", Style); + + Style.SpacesInCStyleCastParentheses = true; + Style.SpacesInParentheses = false; + verifyFormat("x = ( _Atomic(uint64_t) )*a;", Style); + Style.SpacesInCStyleCastParentheses = false; + Style.SpacesInParentheses = true; + verifyFormat("x = (_Atomic( uint64_t ))*a;", Style); + verifyFormat("x = (_Atomic( uint64_t ))&a;", Style); +} + TEST_F(FormatTest, AmbersandInLamda) { // Test case reported in https://bugs.llvm.org/show_bug.cgi?id=41899 FormatStyle AlignStyle = getLLVMStyle();