Author: Haojian Wu Date: 2022-01-10T09:34:18+01:00 New Revision: 4a4b8e4f99e2a82286b0595d561a51e7ad1945d2
URL: https://github.com/llvm/llvm-project/commit/4a4b8e4f99e2a82286b0595d561a51e7ad1945d2 DIFF: https://github.com/llvm/llvm-project/commit/4a4b8e4f99e2a82286b0595d561a51e7ad1945d2.diff LOG: [AST] Add more source information for DecltypeTypeLoc. Adds the paren source location, and removes the hack in clangd. Differential Revision: https://reviews.llvm.org/D116793 Added: Modified: clang-tools-extra/clangd/Selection.cpp clang-tools-extra/clangd/unittests/SelectionTests.cpp clang/include/clang/AST/TypeLoc.h clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Sema/SemaCXXScopeSpec.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaType.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/unittests/AST/SourceLocationTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp index 7dc8a868ea00e..7c6b8b3134fe1 100644 --- a/clang-tools-extra/clangd/Selection.cpp +++ b/clang-tools-extra/clangd/Selection.cpp @@ -60,21 +60,6 @@ void recordMetrics(const SelectionTree &S, const LangOptions &Lang) { // Return the range covering a node and all its children. SourceRange getSourceRange(const DynTypedNode &N) { - // DeclTypeTypeLoc::getSourceRange() is incomplete, which would lead to - // failing to descend into the child expression. - // decltype(2+2); - // ~~~~~~~~~~~~~ <-- correct range - // ~~~~~~~~ <-- range reported by getSourceRange() - // ~~~~~~~~~~~~ <-- range with this hack(i.e, missing closing paren) - // FIXME: Alter DecltypeTypeLoc to contain parentheses locations and get - // rid of this patch. - if (const auto *TL = N.get<TypeLoc>()) { - if (auto DT = TL->getAs<DecltypeTypeLoc>()) { - SourceRange S = DT.getSourceRange(); - S.setEnd(DT.getUnderlyingExpr()->getEndLoc()); - return S; - } - } // MemberExprs to implicitly access anonymous fields should not claim any // tokens for themselves. Given: // struct A { struct { int b; }; }; diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index 9da111f684c31..7e19f07a2215e 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -390,7 +390,7 @@ TEST(SelectionTest, CommonAncestor) { decltype([[^a]] + a) b; )cpp", "DeclRefExpr"}, - {"[[decltype]]^(1) b;", "DecltypeTypeLoc"}, // Not the VarDecl. + {"[[decltype^(1)]] b;", "DecltypeTypeLoc"}, // Not the VarDecl. // Objective-C nullability attributes. { diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 7a036836e8c48..9a43d34a9ec38 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -1994,12 +1994,35 @@ class TypeOfTypeLoc void initializeLocal(ASTContext &Context, SourceLocation Loc); }; -// FIXME: location of the 'decltype' and parens. -class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - DecltypeTypeLoc, - DecltypeType> { +// decltype(expression) abc; +// ~~~~~~~~ DecltypeLoc +// ~ RParenLoc +// FIXME: add LParenLoc, it is tricky to support due to the limitation of +// annotated-decltype token. +struct DecltypeTypeLocInfo { + SourceLocation DecltypeLoc; + SourceLocation RParenLoc; +}; +class DecltypeTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, DecltypeTypeLoc, DecltypeType, + DecltypeTypeLocInfo> { public: Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); } + + SourceLocation getDecltypeLoc() const { return getLocalData()->DecltypeLoc; } + void setDecltypeLoc(SourceLocation Loc) { getLocalData()->DecltypeLoc = Loc; } + + SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } + void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } + + SourceRange getLocalSourceRange() const { + return SourceRange(getDecltypeLoc(), getRParenLoc()); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setDecltypeLoc(Loc); + setRParenLoc(Loc); + } }; struct UnaryTransformTypeLocInfo { diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 8ab1231e1bc10..c08a586604b1f 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1007,6 +1007,9 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { if (Tok.is(tok::annot_decltype)) { Result = getExprAnnotation(Tok); EndLoc = Tok.getAnnotationEndLoc(); + // Unfortunately, we don't know the LParen source location as the annotated + // token doesn't have it. + DS.setTypeofParensRange(SourceRange(SourceLocation(), EndLoc)); ConsumeAnnotationToken(); if (Result.isInvalid()) { DS.SetTypeSpecError(); @@ -1071,6 +1074,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // Match the ')' T.consumeClose(); + DS.setTypeofParensRange(T.getRange()); if (T.getCloseLocation().isInvalid()) { DS.SetTypeSpecError(); // FIXME: this should return the location of the last token diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 8cecf6c6ab4f6..4781d71080c98 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -881,7 +881,8 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, TypeLocBuilder TLB; DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); - DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); + DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); + DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd()); SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), ColonColonLoc); return false; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 454b2647cf347..4c6a96acdb91c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7767,7 +7767,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, TypeLocBuilder TLB; DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T); - DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc()); + DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); + DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd()); TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T); PseudoDestructorTypeStorage Destructed(DestructedTypeInfo); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 57825fe3d79b2..f0bbbcf59c751 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5973,6 +5973,11 @@ namespace { Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); TL.setUnderlyingTInfo(TInfo); } + void VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { + assert(DS.getTypeSpecType() == DeclSpec::TST_decltype); + TL.setDecltypeLoc(DS.getTypeSpecTypeLoc()); + TL.setRParenLoc(DS.getTypeofParensRange().getEnd()); + } void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { // FIXME: This holds only because we only have one unary transform. assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 298a3f7a83d83..c105a0c26ab4a 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6228,15 +6228,15 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB, QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || E.get() != T->getUnderlyingExpr()) { - Result = getDerived().RebuildDecltypeType(E.get(), TL.getNameLoc()); + Result = getDerived().RebuildDecltypeType(E.get(), TL.getDecltypeLoc()); if (Result.isNull()) return QualType(); } else E.get(); DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result); - NewTL.setNameLoc(TL.getNameLoc()); - + NewTL.setDecltypeLoc(TL.getDecltypeLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); return Result; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 724ea53463ca3..b8ec5b2722a95 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6628,7 +6628,8 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { } void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - TL.setNameLoc(readSourceLocation()); + TL.setDecltypeLoc(readSourceLocation()); + TL.setRParenLoc(readSourceLocation()); } void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 65a780e675100..40772bb7dd7f5 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -427,7 +427,8 @@ void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { } void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - Record.AddSourceLocation(TL.getNameLoc()); + Record.AddSourceLocation(TL.getDecltypeLoc()); + Record.AddSourceLocation(TL.getRParenLoc()); } void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { diff --git a/clang/unittests/AST/SourceLocationTest.cpp b/clang/unittests/AST/SourceLocationTest.cpp index c1565c8f4c30d..832d3751362f6 100644 --- a/clang/unittests/AST/SourceLocationTest.cpp +++ b/clang/unittests/AST/SourceLocationTest.cpp @@ -215,6 +215,33 @@ TEST(TypeLoc, LongRange) { EXPECT_TRUE(Verifier.match("long a;", typeLoc())); } +TEST(TypeLoc, DecltypeTypeLocRange) { + llvm::Annotations Code(R"( + $full1[[decltype(1)]] a; + struct A {struct B{};} var; + $full2[[decltype(var)]]::B c; + )"); + auto AST = tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{}); + ASTContext &Ctx = AST->getASTContext(); + const auto &SM = Ctx.getSourceManager(); + + auto MatchedLocs = clang::ast_matchers::match( + typeLoc(loc(decltypeType())).bind("target"), Ctx); + ASSERT_EQ(MatchedLocs.size(), 2u); + auto verify = [&](SourceRange ActualRange, + const llvm::Annotations::Range &Expected) { + auto ActualCharRange = + Lexer::getAsCharRange(ActualRange, SM, Ctx.getLangOpts()); + EXPECT_EQ(SM.getFileOffset(ActualCharRange.getBegin()), Expected.Begin); + EXPECT_EQ(SM.getFileOffset(ActualCharRange.getEnd()), Expected.End); + }; + const auto *Target1 = MatchedLocs[0].getNodeAs<DecltypeTypeLoc>("target"); + verify(Target1->getSourceRange(), Code.range("full1")); + + const auto *Target2 = MatchedLocs[1].getNodeAs<DecltypeTypeLoc>("target"); + verify(Target2->getSourceRange(), Code.range("full2")); +} + TEST(TypeLoc, LongDoubleRange) { RangeVerifier<TypeLoc> Verifier; Verifier.expectRange(1, 1, 1, 6); @@ -559,7 +586,7 @@ TEST(FriendDecl, FriendDecltypeLocation) { TEST(FriendDecl, FriendDecltypeRange) { RangeVerifier<FriendDecl> Verifier; - Verifier.expectRange(4, 1, 4, 8); + Verifier.expectRange(4, 1, 4, 22); EXPECT_TRUE(Verifier.match("struct A;\n" "A foo();\n" "struct A {\n" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits