diff --git a/llvm/include/llvm/Testing/Support/Annotations.h b/llvm/include/llvm/Testing/Support/Annotations.h --- a/llvm/include/llvm/Testing/Support/Annotations.h +++ b/llvm/include/llvm/Testing/Support/Annotations.h @@ -21,10 +21,11 @@ /// Annotations lets you mark points and ranges inside source code, for tests: /// /// Annotations Example(R"cpp( -/// int complete() { x.pri^ } // ^ indicates a point -/// void err() { [["hello" == 42]]; } // [[this is a range]] -/// $definition^class Foo{}; // points can be named: "definition" -/// $fail[[static_assert(false, "")]] // ranges can be named too: "fail" +/// int complete() { x.pri^ } // ^ indicates a point +/// void err() { [["hello" == 42]]; } // [[this is a range]] +/// $definition^class Foo{}; // points can be named: "definition" +/// ${very,complex::name}^class Foo{}; // names inside ${} can contain any characters +/// $fail[[static_assert(false, "")]] // ranges can be named too: "fail" /// )cpp"); /// /// StringRef Code = Example.code(); // annotations stripped. diff --git a/llvm/lib/Testing/Support/Annotations.cpp b/llvm/lib/Testing/Support/Annotations.cpp --- a/llvm/lib/Testing/Support/Annotations.cpp +++ b/llvm/lib/Testing/Support/Annotations.cpp @@ -53,9 +53,15 @@ continue; } if (Text.consume_front("$")) { - Name = - Text.take_while([](char C) { return llvm::isAlnum(C) || C == '_'; }); - Text = Text.drop_front(Name->size()); + if (Text.consume_front("{")) { + Name = Text.take_while([](char C) { return C != '}'; }); + Require(Text.size() > Name->size(), "unterminated $name"); + Text = Text.drop_front(Name->size() + 1); + } else { + Name = Text.take_while( + [](char C) { return llvm::isAlnum(C) || C == '_'; }); + Text = Text.drop_front(Name->size()); + } continue; } Code.push_back(Text.front()); diff --git a/llvm/unittests/Support/AnnotationsTest.cpp b/llvm/unittests/Support/AnnotationsTest.cpp --- a/llvm/unittests/Support/AnnotationsTest.cpp +++ b/llvm/unittests/Support/AnnotationsTest.cpp @@ -109,13 +109,18 @@ // A single named point or range. EXPECT_EQ(llvm::Annotations("a$foo^b").point("foo"), 1u); EXPECT_EQ(llvm::Annotations("a$foo[[b]]cdef").range("foo"), range(1, 2)); + EXPECT_EQ(llvm::Annotations("a${foo}[[b]]cdef").range("foo"), range(1, 2)); + EXPECT_EQ(llvm::Annotations("a${foo->bar}[[b]]cdef").range("foo->bar"), + range(1, 2)); // Empty names should also work. EXPECT_EQ(llvm::Annotations("a$^b").point(""), 1u); + EXPECT_EQ(llvm::Annotations("a${}^b").point(""), 1u); EXPECT_EQ(llvm::Annotations("a$[[b]]cdef").range(""), range(1, 2)); + EXPECT_EQ(llvm::Annotations("a${}[[b]]cdef").range(""), range(1, 2)); // Multiple named points. - llvm::Annotations Annotated("a$p1^bcd$p2^123$p1^345"); + llvm::Annotations Annotated("a${p1}^bcd$p2^123$p1^345"); EXPECT_THAT(Annotated.points(), IsEmpty()); EXPECT_THAT(Annotated.points("p1"), ElementsAre(1u, 7u)); EXPECT_EQ(Annotated.point("p2"), 4u); @@ -144,6 +149,7 @@ EXPECT_DEATH(llvm::Annotations("ff[[fdfd"), "unmatched \\[\\["); EXPECT_DEATH(llvm::Annotations("ff[[fdjsfjd]]xxx]]"), "unmatched \\]\\]"); EXPECT_DEATH(llvm::Annotations("ff$fdsfd"), "unterminated \\$name"); + EXPECT_DEATH(llvm::Annotations("ff${hkhhk"), "unterminated \\$name"); #endif } } // namespace