1 //===- unittest/Format/TokenAnnotatorTest.cpp - Formatting unit tests -----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/Format/Format.h" 10 11 #include "FormatTestUtils.h" 12 #include "TestLexer.h" 13 #include "gtest/gtest.h" 14 15 namespace clang { 16 namespace format { 17 namespace { 18 19 class TokenAnnotatorTest : public ::testing::Test { 20 protected: 21 TokenList annotate(llvm::StringRef Code, 22 const FormatStyle &Style = getLLVMStyle()) { 23 return TestLexer(Allocator, Buffers, Style).annotate(Code); 24 } 25 llvm::SpecificBumpPtrAllocator<FormatToken> Allocator; 26 std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers; 27 }; 28 29 #define EXPECT_TOKEN_KIND(FormatTok, Kind) \ 30 EXPECT_EQ((FormatTok)->Tok.getKind(), Kind) << *(FormatTok) 31 #define EXPECT_TOKEN_TYPE(FormatTok, Type) \ 32 EXPECT_EQ((FormatTok)->getType(), Type) << *(FormatTok) 33 #define EXPECT_TOKEN(FormatTok, Kind, Type) \ 34 do { \ 35 EXPECT_TOKEN_KIND(FormatTok, Kind); \ 36 EXPECT_TOKEN_TYPE(FormatTok, Type); \ 37 } while (false); 38 39 TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmpInMacroDefinition) { 40 // This is a regression test for mis-parsing the & after decltype as a binary 41 // operator instead of a reference (when inside a macro definition). 42 auto Tokens = annotate("auto x = [](const decltype(x) &ptr) {};"); 43 EXPECT_EQ(Tokens.size(), 18u) << Tokens; 44 EXPECT_TOKEN(Tokens[7], tok::kw_decltype, TT_Unknown); 45 EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_TypeDeclarationParen); 46 EXPECT_TOKEN(Tokens[9], tok::identifier, TT_Unknown); 47 EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); 48 EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference); 49 // Same again with * instead of &: 50 Tokens = annotate("auto x = [](const decltype(x) *ptr) {};"); 51 EXPECT_EQ(Tokens.size(), 18u) << Tokens; 52 EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); 53 EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference); 54 55 // Also check that we parse correctly within a macro definition: 56 Tokens = annotate("#define lambda [](const decltype(x) &ptr) {}"); 57 EXPECT_EQ(Tokens.size(), 17u) << Tokens; 58 EXPECT_TOKEN(Tokens[7], tok::kw_decltype, TT_Unknown); 59 EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_TypeDeclarationParen); 60 EXPECT_TOKEN(Tokens[9], tok::identifier, TT_Unknown); 61 EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); 62 EXPECT_TOKEN(Tokens[11], tok::amp, TT_PointerOrReference); 63 // Same again with * instead of &: 64 Tokens = annotate("#define lambda [](const decltype(x) *ptr) {}"); 65 EXPECT_EQ(Tokens.size(), 17u) << Tokens; 66 EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_TypeDeclarationParen); 67 EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference); 68 } 69 70 } // namespace 71 } // namespace format 72 } // namespace clang 73