diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -391,6 +391,8 @@ )cpp", "DeclRefExpr"}, {"[[decltype^(1)]] b;", "DecltypeTypeLoc"}, // Not the VarDecl. + // decltype(auto) is an AutoTypeLoc! + {"[[de^cltype(a^uto)]] a = 1;", "AutoTypeLoc"}, // Objective-C nullability attributes. { diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -2081,6 +2081,9 @@ NamedDecl *FoundDecl; SourceLocation LAngleLoc; SourceLocation RAngleLoc; + + // For decltype(auto). + SourceLocation RParenLoc; }; class AutoTypeLoc @@ -2093,6 +2096,10 @@ return getTypePtr()->getKeyword(); } + bool isDecltypeAuto() const { return getTypePtr()->isDecltypeAuto(); } + SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; } + void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; } + bool isConstrained() const { return getTypePtr()->isConstrained(); } @@ -2173,16 +2180,13 @@ } SourceRange getLocalSourceRange() const { - return{ - isConstrained() - ? (getNestedNameSpecifierLoc() - ? getNestedNameSpecifierLoc().getBeginLoc() - : (getTemplateKWLoc().isValid() - ? getTemplateKWLoc() - : getConceptNameLoc())) - : getNameLoc(), - getNameLoc() - }; + return {isConstrained() + ? (getNestedNameSpecifierLoc() + ? getNestedNameSpecifierLoc().getBeginLoc() + : (getTemplateKWLoc().isValid() ? getTemplateKWLoc() + : getConceptNameLoc())) + : getNameLoc(), + isDecltypeAuto() ? getRParenLoc() : getNameLoc()}; } void copy(AutoTypeLoc Loc) { diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -622,6 +622,7 @@ setFoundDecl(nullptr); setRAngleLoc(Loc); setLAngleLoc(Loc); + setRParenLoc(Loc); TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), getTypePtr()->getArgs(), getArgInfos(), Loc); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -22,6 +22,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/DeclSpec.h" @@ -6041,6 +6042,8 @@ DS.getTypeSpecType() == TST_auto_type || DS.getTypeSpecType() == TST_unspecified); TL.setNameLoc(DS.getTypeSpecTypeLoc()); + if (DS.getTypeSpecType() == TST_decltype_auto) + TL.setRParenLoc(DS.getTypeofParensRange().getEnd()); if (!DS.isConstrainedAuto()) return; TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId(); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6652,6 +6652,8 @@ TL.setArgLocInfo(i, Reader.readTemplateArgumentLocInfo( TL.getTypePtr()->getArg(i).getKind())); } + if (Reader.readBool()) + TL.setRParenLoc(readSourceLocation()); } void TypeLocReader::VisitDeducedTemplateSpecializationTypeLoc( diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -452,6 +452,9 @@ Record.AddTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), TL.getArgLocInfo(I)); } + Record.push_back(TL.isDecltypeAuto()); + if (TL.isDecltypeAuto()) + Record.AddSourceLocation(TL.getRParenLoc()); } void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc( diff --git a/clang/test/AST/ast-dump-template-decls-json.cpp b/clang/test/AST/ast-dump-template-decls-json.cpp --- a/clang/test/AST/ast-dump-template-decls-json.cpp +++ b/clang/test/AST/ast-dump-template-decls-json.cpp @@ -2130,9 +2130,9 @@ // CHECK-NEXT: "tokLen": 8 // CHECK-NEXT: }, // CHECK-NEXT: "end": { -// CHECK-NEXT: "offset": 705, -// CHECK-NEXT: "col": 11, -// CHECK-NEXT: "tokLen": 8 +// CHECK-NEXT: "offset": 718, +// CHECK-NEXT: "col": 24, +// CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "type": { diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -90,7 +90,7 @@ template // CHECK: ClassTemplateDecl 0x{{[^ ]*}} col:8 U -// CHECK-NEXT: NonTypeTemplateParmDecl 0x{{[^ ]*}} col:25 'decltype(auto)' depth 0 index 0 +// CHECK-NEXT: NonTypeTemplateParmDecl 0x{{[^ ]*}} col:25 'decltype(auto)' depth 0 index 0 struct U {}; template diff --git a/clang/unittests/AST/SourceLocationTest.cpp b/clang/unittests/AST/SourceLocationTest.cpp --- a/clang/unittests/AST/SourceLocationTest.cpp +++ b/clang/unittests/AST/SourceLocationTest.cpp @@ -242,6 +242,13 @@ verify(Target2->getSourceRange(), Code.range("full2")); } +TEST(TypeLoc, AutoTypeLocRange) { + RangeVerifier Verifier; + Verifier.expectRange(1, 1, 1, 14); + EXPECT_TRUE(Verifier.match("decltype(auto) a = 1;", typeLoc(loc(autoType())), + Lang_CXX11)); +} + TEST(TypeLoc, LongDoubleRange) { RangeVerifier Verifier; Verifier.expectRange(1, 1, 1, 6);