[clang-tools-extra] ab3f100 - Reland (2) "[AST] Add RParen loc for decltype AutoTypeloc.""

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 17 02:33:47 PST 2022


Author: Haojian Wu
Date: 2022-01-17T11:33:11+01:00
New Revision: ab3f100bec03d72ecee947a323c51698d4b95207

URL: https://github.com/llvm/llvm-project/commit/ab3f100bec03d72ecee947a323c51698d4b95207
DIFF: https://github.com/llvm/llvm-project/commit/ab3f100bec03d72ecee947a323c51698d4b95207.diff

LOG: Reland (2) "[AST] Add RParen loc for decltype AutoTypeloc.""

The patch was reverted because it caused a crash during PCH build -- we
missed to update the RParenLoc in TreeTransform<Derived>::TransformAutoType.

This relands 55d96ac and 37ec65e with a test and fix.

Added: 
    clang/test/PCH/cxx14-decltype-auto.cpp

Modified: 
    clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
    clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
    clang-tools-extra/clangd/unittests/SelectionTests.cpp
    clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
    clang/include/clang/AST/TypeLoc.h
    clang/lib/AST/TypeLoc.cpp
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Sema/SemaType.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/test/AST/ast-dump-template-decls-json.cpp
    clang/test/AST/ast-dump-template-decls.cpp
    clang/unittests/AST/SourceLocationTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
index d5c9fa7de811e..2b9907d162664 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
@@ -285,15 +285,12 @@ SourceRange UseTrailingReturnTypeCheck::findReturnTypeAndCVSourceRange(
     return {};
   }
 
-  // If the return type is a constrained 'auto' or 'decltype(auto)', we need to
-  // include the tokens after the concept. Unfortunately, the source range of an
-  // AutoTypeLoc, if it is constrained, does not include the 'auto' or
-  // 'decltype(auto)'. If the return type is a plain 'decltype(...)', the
-  // source range only contains the first 'decltype' token.
+  // If the return type is a constrained 'auto', we need to include the token
+  // after the concept. Unfortunately, the source range of an AutoTypeLoc, if it
+  // is constrained, does not include the 'auto'.
+  // FIXME: fix the AutoTypeLoc location in clang.
   auto ATL = ReturnLoc.getAs<AutoTypeLoc>();
-  if ((ATL && (ATL.isConstrained() ||
-               ATL.getAutoKeyword() == AutoTypeKeyword::DecltypeAuto)) ||
-      ReturnLoc.getAs<DecltypeTypeLoc>()) {
+  if (ATL && ATL.isConstrained() && !ATL.isDecltypeAuto()) {
     SourceLocation End =
         expandIfMacroId(ReturnLoc.getSourceRange().getEnd(), SM);
     SourceLocation BeginNameF = expandIfMacroId(F.getLocation(), SM);

diff  --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
index 3776e1c3505d1..914564e9ae218 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp
@@ -96,9 +96,7 @@ bool ExpandAutoType::prepare(const Selection& Inputs) {
   if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
     if (auto *TypeNode = Node->ASTNode.get<TypeLoc>()) {
       if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
-        // Code in apply() does handle 'decltype(auto)' yet.
-        if (!Result.getTypePtr()->isDecltypeAuto() &&
-            !isStructuredBindingType(Node) &&
+        if (!isStructuredBindingType(Node) &&
             !isDeducedAsLambda(Node, Result.getBeginLoc()) &&
             !isTemplateParam(Node))
           CachedLocation = Result;

diff  --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
index b3a0847c2a4a8..a2b7071540405 100644
--- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -399,6 +399,8 @@ TEST(SelectionTest, CommonAncestor) {
         )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-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
index 96574a67b5a46..6d9d4362be7af 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
@@ -71,7 +71,8 @@ TEST_F(ExpandAutoTypeTest, Test) {
       apply("void ns::Func() { au^to x = new ns::Class::Nested{}; }"),
       "void ns::Func() { ns::Class::Nested * x = new ns::Class::Nested{}; }");
 
-  EXPECT_UNAVAILABLE("dec^ltype(au^to) x = 10;");
+  EXPECT_EQ(apply("dec^ltype(auto) x = 10;"), "int x = 10;");
+  EXPECT_EQ(apply("decltype(au^to) x = 10;"), "int x = 10;");
   // expanding types in structured bindings is syntactically invalid.
   EXPECT_UNAVAILABLE("const ^auto &[x,y] = (int[]){1,2};");
 

diff  --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index 9a43d34a9ec38..8cfa579a22da7 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2081,6 +2081,11 @@ struct AutoTypeLocInfo : TypeSpecLocInfo {
   NamedDecl *FoundDecl;
   SourceLocation LAngleLoc;
   SourceLocation RAngleLoc;
+
+  // For decltype(auto).
+  SourceLocation RParenLoc;
+
+  // Followed by a TemplateArgumentLocInfo[]
 };
 
 class AutoTypeLoc
@@ -2093,6 +2098,10 @@ class AutoTypeLoc
     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 +2182,13 @@ class AutoTypeLoc
   }
 
   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
index c3ed08d5a8b3e..13aa54c48f66c 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -622,6 +622,7 @@ void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) {
   setFoundDecl(nullptr);
   setRAngleLoc(Loc);
   setLAngleLoc(Loc);
+  setRParenLoc(Loc);
   TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(),
                                                    getTypePtr()->getArgs(),
                                                    getArgInfos(), Loc);

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index e1074f78c062d..cff8c76183f6a 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3576,6 +3576,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
             }
           }
           ConsumedEnd = Tok.getLocation();
+          DS.setTypeofParensRange(Tracker.getRange());
           // Even if something went wrong above, continue as if we've seen
           // `decltype(auto)`.
           isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec,

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index f0bbbcf59c751..959f4903b0306 100644
--- 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 @@ namespace {
              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/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c9feedbe5a89c..e43b3ca968ebb 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -6635,6 +6635,7 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB,
   NewTL.setFoundDecl(TL.getFoundDecl());
   NewTL.setLAngleLoc(TL.getLAngleLoc());
   NewTL.setRAngleLoc(TL.getRAngleLoc());
+  NewTL.setRParenLoc(TL.getRParenLoc());
   for (unsigned I = 0; I < NewTL.getNumArgs(); ++I)
     NewTL.setArgLocInfo(I, NewTemplateArgs.arguments()[I].getLocInfo());
 

diff  --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index b8ec5b2722a95..9056f00978c8f 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6652,6 +6652,8 @@ void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
       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
index 40772bb7dd7f5..c2bee93b077e6 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -452,6 +452,9 @@ void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
       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
index fc1b883f5dacc..5fc466bd9908a 100644
--- a/clang/test/AST/ast-dump-template-decls-json.cpp
+++ b/clang/test/AST/ast-dump-template-decls-json.cpp
@@ -2130,9 +2130,9 @@ void i();
 // 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
index e58731ae6d51d..51ec673ab8f3a 100644
--- a/clang/test/AST/ast-dump-template-decls.cpp
+++ b/clang/test/AST/ast-dump-template-decls.cpp
@@ -90,7 +90,7 @@ struct T {};
 
 template <decltype(auto)>
 // CHECK: ClassTemplateDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:[[@LINE+2]]:11> col:8 U
-// CHECK-NEXT: NonTypeTemplateParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11> col:25 'decltype(auto)' depth 0 index 0
+// CHECK-NEXT: NonTypeTemplateParmDecl 0x{{[^ ]*}} <line:[[@LINE-2]]:11, col:24> col:25 'decltype(auto)' depth 0 index 0
 struct U {};
 
 template <typename Ty>

diff  --git a/clang/test/PCH/cxx14-decltype-auto.cpp b/clang/test/PCH/cxx14-decltype-auto.cpp
new file mode 100644
index 0000000000000..d5f83c2543fb8
--- /dev/null
+++ b/clang/test/PCH/cxx14-decltype-auto.cpp
@@ -0,0 +1,16 @@
+// Test with pch.
+// RUN: %clang_cc1 -emit-pch -std=c++14 -o %t %s
+// RUN: %clang_cc1 -include-pch %t -emit-llvm -std=c++14 -o - %s
+
+#ifndef HEADER
+#define HEADER
+
+template <typename T>
+constexpr decltype(auto) test(T) { return T(); }
+class A {};
+void k() {  test(A()); }
+
+#else
+
+auto s = test(A());
+#endif

diff  --git a/clang/unittests/AST/SourceLocationTest.cpp b/clang/unittests/AST/SourceLocationTest.cpp
index 832d3751362f6..a798f6b2225ba 100644
--- a/clang/unittests/AST/SourceLocationTest.cpp
+++ b/clang/unittests/AST/SourceLocationTest.cpp
@@ -242,6 +242,13 @@ TEST(TypeLoc, DecltypeTypeLocRange) {
   verify(Target2->getSourceRange(), Code.range("full2"));
 }
 
+TEST(TypeLoc, AutoTypeLocRange) {
+  RangeVerifier<TypeLoc> Verifier;
+  Verifier.expectRange(1, 1, 1, 14);
+  EXPECT_TRUE(Verifier.match("decltype(auto) a = 1;", typeLoc(loc(autoType())),
+                             Lang_CXX14));
+}
+
 TEST(TypeLoc, LongDoubleRange) {
   RangeVerifier<TypeLoc> Verifier;
   Verifier.expectRange(1, 1, 1, 6);


        


More information about the cfe-commits mailing list