diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -294,11 +294,12 @@ SourceRange Initializer) { SourceLocation Start = GetStartLoc().Visit(T); SourceLocation End = T.getEndLoc(); - assert(End.isValid()); if (Name.isValid()) { if (Start.isInvalid()) Start = Name; - if (SM.isBeforeInTranslationUnit(End, Name)) + // End of TypeLoc could be invalid if the type is invalid, fallback to the + // NameLoc. + if (End.isInvalid() || SM.isBeforeInTranslationUnit(End, Name)) End = Name; } if (Initializer.isValid()) { diff --git a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp --- a/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp @@ -23,11 +23,9 @@ SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " ")); auto *Root = buildTree(Code, GetParam()); - if (Diags->getClient()->getNumErrors() != 0) { - return ::testing::AssertionFailure() - << "Source file has syntax errors, they were printed to the test " - "log"; - } + auto ErrorOK = errorOK(Code); + if (!ErrorOK) + return ErrorOK; auto Actual = StringRef(Root->dump(Arena->getSourceManager())).trim().str(); // EXPECT_EQ shows the diff between the two strings if they are different. EXPECT_EQ(Tree.trim().str(), Actual); @@ -45,11 +43,9 @@ auto AnnotatedCode = llvm::Annotations(CodeWithAnnotations); auto *Root = buildTree(AnnotatedCode.code(), GetParam()); - if (Diags->getClient()->getNumErrors() != 0) { - return ::testing::AssertionFailure() - << "Source file has syntax errors, they were printed to the test " - "log"; - } + auto ErrorOK = errorOK(AnnotatedCode.code()); + if (!ErrorOK) + return ErrorOK; auto AnnotatedRanges = AnnotatedCode.ranges(); if (AnnotatedRanges.size() != TreeDumps.size()) { @@ -77,6 +73,19 @@ return Failed ? ::testing::AssertionFailure() : ::testing::AssertionSuccess(); } + +private: + ::testing::AssertionResult errorOK(StringRef RawCode) { + if (!RawCode.contains("error-ok")) { + if (Diags->getClient()->getNumErrors() != 0) { + return ::testing::AssertionFailure() + << "Source file has syntax errors (suppress with /*error-ok*/), " + "they were printed to the " + "test log"; + } + } + return ::testing::AssertionSuccess(); + } }; INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, BuildSyntaxTreeTest, @@ -4773,6 +4782,7 @@ int func1([[int a]]); int func2([[int *ap]]); int func3([[int a, float b]]); + int func4([[undef a]]); // error-ok: no crash on invalid type )cpp", {R"txt( ParameterDeclarationList Parameters @@ -4804,6 +4814,14 @@ `-DeclaratorList Declarators `-SimpleDeclarator ListElement `-'b' +)txt", + R"txt( +ParameterDeclarationList Parameters +`-SimpleDeclaration ListElement + |-'undef' + `-DeclaratorList Declarators + `-SimpleDeclarator ListElement + `-'a' )txt"})); }