Skip to content

Commit 4a4b8e4

Browse files
committed
[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
1 parent 5c2e7c9 commit 4a4b8e4

File tree

11 files changed

+76
-28
lines changed

11 files changed

+76
-28
lines changed

clang-tools-extra/clangd/Selection.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,6 @@ void recordMetrics(const SelectionTree &S, const LangOptions &Lang) {
6060

6161
// Return the range covering a node and all its children.
6262
SourceRange getSourceRange(const DynTypedNode &N) {
63-
// DeclTypeTypeLoc::getSourceRange() is incomplete, which would lead to
64-
// failing to descend into the child expression.
65-
// decltype(2+2);
66-
// ~~~~~~~~~~~~~ <-- correct range
67-
// ~~~~~~~~ <-- range reported by getSourceRange()
68-
// ~~~~~~~~~~~~ <-- range with this hack(i.e, missing closing paren)
69-
// FIXME: Alter DecltypeTypeLoc to contain parentheses locations and get
70-
// rid of this patch.
71-
if (const auto *TL = N.get<TypeLoc>()) {
72-
if (auto DT = TL->getAs<DecltypeTypeLoc>()) {
73-
SourceRange S = DT.getSourceRange();
74-
S.setEnd(DT.getUnderlyingExpr()->getEndLoc());
75-
return S;
76-
}
77-
}
7863
// MemberExprs to implicitly access anonymous fields should not claim any
7964
// tokens for themselves. Given:
8065
// struct A { struct { int b; }; };

clang-tools-extra/clangd/unittests/SelectionTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ TEST(SelectionTest, CommonAncestor) {
390390
decltype([[^a]] + a) b;
391391
)cpp",
392392
"DeclRefExpr"},
393-
{"[[decltype]]^(1) b;", "DecltypeTypeLoc"}, // Not the VarDecl.
393+
{"[[decltype^(1)]] b;", "DecltypeTypeLoc"}, // Not the VarDecl.
394394

395395
// Objective-C nullability attributes.
396396
{

clang/include/clang/AST/TypeLoc.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,12 +1994,35 @@ class TypeOfTypeLoc
19941994
void initializeLocal(ASTContext &Context, SourceLocation Loc);
19951995
};
19961996

1997-
// FIXME: location of the 'decltype' and parens.
1998-
class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
1999-
DecltypeTypeLoc,
2000-
DecltypeType> {
1997+
// decltype(expression) abc;
1998+
// ~~~~~~~~ DecltypeLoc
1999+
// ~ RParenLoc
2000+
// FIXME: add LParenLoc, it is tricky to support due to the limitation of
2001+
// annotated-decltype token.
2002+
struct DecltypeTypeLocInfo {
2003+
SourceLocation DecltypeLoc;
2004+
SourceLocation RParenLoc;
2005+
};
2006+
class DecltypeTypeLoc
2007+
: public ConcreteTypeLoc<UnqualTypeLoc, DecltypeTypeLoc, DecltypeType,
2008+
DecltypeTypeLocInfo> {
20012009
public:
20022010
Expr *getUnderlyingExpr() const { return getTypePtr()->getUnderlyingExpr(); }
2011+
2012+
SourceLocation getDecltypeLoc() const { return getLocalData()->DecltypeLoc; }
2013+
void setDecltypeLoc(SourceLocation Loc) { getLocalData()->DecltypeLoc = Loc; }
2014+
2015+
SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; }
2016+
void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; }
2017+
2018+
SourceRange getLocalSourceRange() const {
2019+
return SourceRange(getDecltypeLoc(), getRParenLoc());
2020+
}
2021+
2022+
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
2023+
setDecltypeLoc(Loc);
2024+
setRParenLoc(Loc);
2025+
}
20032026
};
20042027

20052028
struct UnaryTransformTypeLocInfo {

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,9 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
10071007
if (Tok.is(tok::annot_decltype)) {
10081008
Result = getExprAnnotation(Tok);
10091009
EndLoc = Tok.getAnnotationEndLoc();
1010+
// Unfortunately, we don't know the LParen source location as the annotated
1011+
// token doesn't have it.
1012+
DS.setTypeofParensRange(SourceRange(SourceLocation(), EndLoc));
10101013
ConsumeAnnotationToken();
10111014
if (Result.isInvalid()) {
10121015
DS.SetTypeSpecError();
@@ -1071,6 +1074,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
10711074

10721075
// Match the ')'
10731076
T.consumeClose();
1077+
DS.setTypeofParensRange(T.getRange());
10741078
if (T.getCloseLocation().isInvalid()) {
10751079
DS.SetTypeSpecError();
10761080
// FIXME: this should return the location of the last token

clang/lib/Sema/SemaCXXScopeSpec.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,8 @@ bool Sema::ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
881881

882882
TypeLocBuilder TLB;
883883
DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
884-
DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc());
884+
DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc());
885+
DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd());
885886
SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T),
886887
ColonColonLoc);
887888
return false;

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7767,7 +7767,8 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
77677767

77687768
TypeLocBuilder TLB;
77697769
DecltypeTypeLoc DecltypeTL = TLB.push<DecltypeTypeLoc>(T);
7770-
DecltypeTL.setNameLoc(DS.getTypeSpecTypeLoc());
7770+
DecltypeTL.setDecltypeLoc(DS.getTypeSpecTypeLoc());
7771+
DecltypeTL.setRParenLoc(DS.getTypeofParensRange().getEnd());
77717772
TypeSourceInfo *DestructedTypeInfo = TLB.getTypeSourceInfo(Context, T);
77727773
PseudoDestructorTypeStorage Destructed(DestructedTypeInfo);
77737774

clang/lib/Sema/SemaType.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5973,6 +5973,11 @@ namespace {
59735973
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
59745974
TL.setUnderlyingTInfo(TInfo);
59755975
}
5976+
void VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
5977+
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
5978+
TL.setDecltypeLoc(DS.getTypeSpecTypeLoc());
5979+
TL.setRParenLoc(DS.getTypeofParensRange().getEnd());
5980+
}
59765981
void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
59775982
// FIXME: This holds only because we only have one unary transform.
59785983
assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);

clang/lib/Sema/TreeTransform.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6228,15 +6228,15 @@ QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB,
62286228
QualType Result = TL.getType();
62296229
if (getDerived().AlwaysRebuild() ||
62306230
E.get() != T->getUnderlyingExpr()) {
6231-
Result = getDerived().RebuildDecltypeType(E.get(), TL.getNameLoc());
6231+
Result = getDerived().RebuildDecltypeType(E.get(), TL.getDecltypeLoc());
62326232
if (Result.isNull())
62336233
return QualType();
62346234
}
62356235
else E.get();
62366236

62376237
DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result);
6238-
NewTL.setNameLoc(TL.getNameLoc());
6239-
6238+
NewTL.setDecltypeLoc(TL.getDecltypeLoc());
6239+
NewTL.setRParenLoc(TL.getRParenLoc());
62406240
return Result;
62416241
}
62426242

clang/lib/Serialization/ASTReader.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6628,7 +6628,8 @@ void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
66286628
}
66296629

66306630
void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
6631-
TL.setNameLoc(readSourceLocation());
6631+
TL.setDecltypeLoc(readSourceLocation());
6632+
TL.setRParenLoc(readSourceLocation());
66326633
}
66336634

66346635
void TypeLocReader::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,8 @@ void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
427427
}
428428

429429
void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
430-
Record.AddSourceLocation(TL.getNameLoc());
430+
Record.AddSourceLocation(TL.getDecltypeLoc());
431+
Record.AddSourceLocation(TL.getRParenLoc());
431432
}
432433

433434
void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {

clang/unittests/AST/SourceLocationTest.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,33 @@ TEST(TypeLoc, LongRange) {
215215
EXPECT_TRUE(Verifier.match("long a;", typeLoc()));
216216
}
217217

218+
TEST(TypeLoc, DecltypeTypeLocRange) {
219+
llvm::Annotations Code(R"(
220+
$full1[[decltype(1)]] a;
221+
struct A {struct B{};} var;
222+
$full2[[decltype(var)]]::B c;
223+
)");
224+
auto AST = tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{});
225+
ASTContext &Ctx = AST->getASTContext();
226+
const auto &SM = Ctx.getSourceManager();
227+
228+
auto MatchedLocs = clang::ast_matchers::match(
229+
typeLoc(loc(decltypeType())).bind("target"), Ctx);
230+
ASSERT_EQ(MatchedLocs.size(), 2u);
231+
auto verify = [&](SourceRange ActualRange,
232+
const llvm::Annotations::Range &Expected) {
233+
auto ActualCharRange =
234+
Lexer::getAsCharRange(ActualRange, SM, Ctx.getLangOpts());
235+
EXPECT_EQ(SM.getFileOffset(ActualCharRange.getBegin()), Expected.Begin);
236+
EXPECT_EQ(SM.getFileOffset(ActualCharRange.getEnd()), Expected.End);
237+
};
238+
const auto *Target1 = MatchedLocs[0].getNodeAs<DecltypeTypeLoc>("target");
239+
verify(Target1->getSourceRange(), Code.range("full1"));
240+
241+
const auto *Target2 = MatchedLocs[1].getNodeAs<DecltypeTypeLoc>("target");
242+
verify(Target2->getSourceRange(), Code.range("full2"));
243+
}
244+
218245
TEST(TypeLoc, LongDoubleRange) {
219246
RangeVerifier<TypeLoc> Verifier;
220247
Verifier.expectRange(1, 1, 1, 6);
@@ -559,7 +586,7 @@ TEST(FriendDecl, FriendDecltypeLocation) {
559586

560587
TEST(FriendDecl, FriendDecltypeRange) {
561588
RangeVerifier<FriendDecl> Verifier;
562-
Verifier.expectRange(4, 1, 4, 8);
589+
Verifier.expectRange(4, 1, 4, 22);
563590
EXPECT_TRUE(Verifier.match("struct A;\n"
564591
"A foo();\n"
565592
"struct A {\n"

0 commit comments

Comments
 (0)