teemperor updated this revision to Diff 301577.
teemperor added a comment.

- Respect forced deserialisation.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80878/new/

https://reviews.llvm.org/D80878

Files:
  clang/include/clang/AST/TextNodeDumper.h
  clang/lib/AST/ASTDumper.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/test/AST/ast-dump-lambda.cpp
  clang/test/AST/ast-dump-records.cpp
  clang/unittests/AST/ASTDumpTest.cpp
  clang/unittests/AST/CMakeLists.txt

Index: clang/unittests/AST/CMakeLists.txt
===================================================================
--- clang/unittests/AST/CMakeLists.txt
+++ clang/unittests/AST/CMakeLists.txt
@@ -6,6 +6,7 @@
 
 add_clang_unittest(ASTTests
   ASTContextParentMapTest.cpp
+  ASTDumpTest.cpp
   ASTImporterFixtures.cpp
   ASTImporterTest.cpp
   ASTImporterGenericRedeclTest.cpp
Index: clang/unittests/AST/ASTDumpTest.cpp
===================================================================
--- /dev/null
+++ clang/unittests/AST/ASTDumpTest.cpp
@@ -0,0 +1,182 @@
+//===- unittests/AST/ASTDumpTest.cpp --- Declaration tests ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Tests Decl::dump().
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+
+namespace clang {
+namespace ast {
+
+namespace {
+/// An ExternalASTSource that asserts if it is queried for information about
+/// any declaration.
+class TrappingExternalASTSource : public ExternalASTSource {
+  ~TrappingExternalASTSource() override = default;
+  bool FindExternalVisibleDeclsByName(const DeclContext *,
+                                      DeclarationName) override {
+    assert(false && "Unexpected call to FindExternalVisibleDeclsByName");
+    return true;
+  }
+
+  void FindExternalLexicalDecls(const DeclContext *,
+                                llvm::function_ref<bool(Decl::Kind)>,
+                                SmallVectorImpl<Decl *> &) override {
+    assert(false && "Unexpected call to FindExternalLexicalDecls");
+  }
+
+  void completeVisibleDeclsMap(const DeclContext *) override {
+    assert(false && "Unexpected call to completeVisibleDeclsMap");
+  }
+
+  void CompleteRedeclChain(const Decl *) override {
+    assert(false && "Unexpected call to CompleteRedeclChain");
+  }
+
+  void CompleteType(TagDecl *) override {
+    assert(false && "Unexpected call to CompleteType(Tag Decl*)");
+  }
+
+  void CompleteType(ObjCInterfaceDecl *) override {
+    assert(false && "Unexpected call to CompleteType(ObjCInterfaceDecl *)");
+  }
+};
+
+/// An ExternalASTSource that records which DeclContexts were queried so far.
+class RecordingExternalASTSource : public ExternalASTSource {
+public:
+  llvm::DenseSet<const DeclContext *> QueriedDCs;
+  ~RecordingExternalASTSource() override = default;
+
+  void FindExternalLexicalDecls(const DeclContext *DC,
+                                llvm::function_ref<bool(Decl::Kind)>,
+                                SmallVectorImpl<Decl *> &) override {
+    QueriedDCs.insert(DC);
+  }
+};
+
+
+class ASTDumpTestBase : public ::testing::Test {
+protected:
+  ASTDumpTestBase(clang::ExternalASTSource *Source)
+      : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
+        Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
+        SourceMgr(Diags, FileMgr), Idents(LangOpts, nullptr),
+        Ctxt(LangOpts, SourceMgr, Idents, Sels, Builtins) {
+    Ctxt.setExternalSource(Source);
+  }
+
+  FileSystemOptions FileMgrOpts;
+  FileManager FileMgr;
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  LangOptions LangOpts;
+  IdentifierTable Idents;
+  SelectorTable Sels;
+  Builtin::Context Builtins;
+  ASTContext Ctxt;
+};
+
+/// Tests that Decl::dump doesn't load additional declarations from the
+/// ExternalASTSource.
+class NoDeserializeTest : public ASTDumpTestBase {
+protected:
+  NoDeserializeTest() : ASTDumpTestBase(new TrappingExternalASTSource()) {}
+};
+
+/// Tests which declarations Decl::dump deserializes;
+class DeserializeTest : public ASTDumpTestBase {
+protected:
+  DeserializeTest() : ASTDumpTestBase(Recorder = new RecordingExternalASTSource()) {}
+  RecordingExternalASTSource *Recorder;
+};
+} // unnamed namespace
+
+/// Set all flags that activate queries to the ExternalASTSource.
+static void setExternalStorageFlags(DeclContext *DC) {
+  DC->setHasExternalLexicalStorage();
+  DC->setHasExternalVisibleStorage();
+  DC->setMustBuildLookupTable();
+}
+
+/// Dumps the given Decl.
+static void dumpDecl(Decl *D, bool Deserialize) {
+  // Try dumping the decl which shouldn't trigger any calls to the
+  // ExternalASTSource.
+
+  std::string Out;
+  llvm::raw_string_ostream OS(Out);
+  D->dump(OS, Deserialize);
+}
+
+TEST_F(NoDeserializeTest, DumpObjCInterfaceDecl) {
+  // Define an Objective-C interface.
+  ObjCInterfaceDecl *I = ObjCInterfaceDecl::Create(
+      Ctxt, Ctxt.getTranslationUnitDecl(), SourceLocation(),
+      &Ctxt.Idents.get("c"), nullptr, nullptr);
+  Ctxt.getTranslationUnitDecl()->addDecl(I);
+
+  setExternalStorageFlags(I);
+  dumpDecl(I, /*Deserialize*/false);
+}
+
+TEST_F(NoDeserializeTest, DumpRecordDecl) {
+  // Define a struct.
+  RecordDecl *R = RecordDecl::Create(
+      Ctxt, TagDecl::TagKind::TTK_Class, Ctxt.getTranslationUnitDecl(),
+      SourceLocation(), SourceLocation(), &Ctxt.Idents.get("c"));
+  R->startDefinition();
+  R->completeDefinition();
+  Ctxt.getTranslationUnitDecl()->addDecl(R);
+
+  setExternalStorageFlags(R);
+  dumpDecl(R, /*Deserialize*/false);
+}
+
+TEST_F(NoDeserializeTest, DumpCXXRecordDecl) {
+  // Define a class.
+  CXXRecordDecl *R = CXXRecordDecl::Create(
+      Ctxt, TagDecl::TagKind::TTK_Class, Ctxt.getTranslationUnitDecl(),
+      SourceLocation(), SourceLocation(), &Ctxt.Idents.get("c"));
+  R->startDefinition();
+  R->completeDefinition();
+  Ctxt.getTranslationUnitDecl()->addDecl(R);
+
+  setExternalStorageFlags(R);
+  dumpDecl(R, /*Deserialize*/false);
+}
+
+TEST_F(DeserializeTest, DumpCXXRecordDecl) {
+  // Define a class.
+  CXXRecordDecl *R = CXXRecordDecl::Create(
+      Ctxt, TagDecl::TagKind::TTK_Class, Ctxt.getTranslationUnitDecl(),
+      SourceLocation(), SourceLocation(), &Ctxt.Idents.get("c"));
+  R->startDefinition();
+  R->completeDefinition();
+  Ctxt.getTranslationUnitDecl()->addDecl(R);
+
+  setExternalStorageFlags(R);
+  // Check that our record gets deserialized while dumping.
+  EXPECT_FALSE(Recorder->QueriedDCs.contains(R));
+  dumpDecl(R, /*Deserialize*/true);
+  EXPECT_TRUE(Recorder->QueriedDCs.contains(R));
+}
+
+} // end namespace ast
+} // end namespace clang
Index: clang/test/AST/ast-dump-records.cpp
===================================================================
--- clang/test/AST/ast-dump-records.cpp
+++ clang/test/AST/ast-dump-records.cpp
@@ -22,7 +22,7 @@
   // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
   // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
   // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-  // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+  // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
   // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:8> col:8 implicit struct A
   int a;
@@ -57,7 +57,7 @@
   // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
   // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
   // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-  // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+  // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
   // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:8> col:8 implicit struct C
   struct {
@@ -68,7 +68,7 @@
     // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
     // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
     // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-    // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+    // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
     int a;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
   } b;
@@ -82,7 +82,7 @@
     // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
     // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
     // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-    // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+    // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
     int c;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 c 'int'
     float d;
@@ -104,7 +104,7 @@
     // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
     // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
     // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-    // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+    // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
     int e, f;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 e 'int'
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:5, col:12> col:12 f 'int'
@@ -126,7 +126,7 @@
   // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
   // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
   // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-  // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+  // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
   // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:8> col:8 implicit struct D
   int a;
@@ -151,7 +151,7 @@
   // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
   // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
   // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-  // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+  // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
   // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:7> col:7 implicit union E
   int a;
@@ -186,7 +186,7 @@
   // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
   // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
   // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-  // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+  // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
   // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <col:1, col:7> col:7 implicit union G
   struct {
@@ -197,7 +197,7 @@
     // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
     // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
     // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-    // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+    // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
     int a;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
@@ -214,7 +214,7 @@
     // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
     // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
     // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-    // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+    // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
     int c;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 c 'int'
@@ -237,7 +237,7 @@
     // CHECK-NEXT: MoveConstructor exists simple trivial needs_implicit
     // CHECK-NEXT: CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
     // CHECK-NEXT: MoveAssignment exists simple trivial needs_implicit
-    // CHECK-NEXT: Destructor simple irrelevant trivial needs_implicit
+    // CHECK-NEXT: Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 
     int e, f;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 e 'int'
Index: clang/test/AST/ast-dump-lambda.cpp
===================================================================
--- clang/test/AST/ast-dump-lambda.cpp
+++ clang/test/AST/ast-dump-lambda.cpp
@@ -48,7 +48,7 @@
 // CHECK-NEXT:    |   | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    |   | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    |   | |-MoveAssignment exists simple trivial needs_implicit
-// CHECK-NEXT:    |   | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    |   | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    |   |-CXXRecordDecl {{.*}} <col:3, col:10> col:10{{( imported)?}} implicit struct V
 // CHECK-NEXT:    |   `-CXXMethodDecl {{.*}} <line:17:5, line:20:5> line:17:10{{( imported)?}} f 'void ()'
 // CHECK-NEXT:    |     `-CompoundStmt {{.*}} <col:14, line:20:5>
@@ -60,7 +60,7 @@
 // CHECK-NEXT:    |       | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    |       | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    |       | | | |-MoveAssignment
-// CHECK-NEXT:    |       | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    |       | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    |       | | |-CXXMethodDecl {{.*}} <col:12, col:15> col:7{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    |       | | | `-CompoundStmt {{.*}} <col:14, col:15>
 // CHECK-NEXT:    |       | | `-FieldDecl {{.*}} <col:8> col:8{{( imported)?}} implicit 'V *'
@@ -75,7 +75,7 @@
 // CHECK-NEXT:    |         | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    |         | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    |         | | |-MoveAssignment
-// CHECK-NEXT:    |         | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    |         | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    |         | |-CXXMethodDecl {{.*}} <col:13, col:16> col:7{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    |         | | `-CompoundStmt {{.*}} <col:15, col:16>
 // CHECK-NEXT:    |         | `-FieldDecl {{.*}} <col:8> col:8{{( imported)?}} implicit 'V'
@@ -94,7 +94,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:6, col:9> col:3{{( imported)?}} operator() 'auto () const' inline
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:8, col:9>
 // CHECK-NEXT:    | | |-CXXConversionDecl {{.*}} <col:3, col:9> col:3{{( imported)?}} implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
@@ -108,7 +108,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:16, col:19> col:3{{( imported)?}} operator() 'auto (int, ...) const' inline
 // CHECK-NEXT:    | | | |-ParmVarDecl {{.*}} <col:6, col:10> col:10{{( imported)?}} a 'int'
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:18, col:19>
@@ -124,7 +124,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:8, col:11> col:3{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:10, col:11>
 // CHECK-NEXT:    | | `-FieldDecl {{.*}} <col:4> col:4{{( imported)?}} implicit 'Ts...'
@@ -139,7 +139,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | `-CXXMethodDecl {{.*}} <col:5, col:8> col:3{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    | |   `-CompoundStmt {{.*}} <col:7, col:8>
 // CHECK-NEXT:    | `-CompoundStmt {{.*}} <col:7, col:8>
@@ -151,7 +151,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | `-CXXMethodDecl {{.*}} <col:5, col:19> col:3{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    | |   `-CompoundStmt {{.*}} <col:7, col:19>
 // CHECK-NEXT:    | |     `-ReturnStmt {{.*}} <col:9, col:16>
@@ -167,7 +167,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | `-CXXMethodDecl {{.*}} <col:5, col:8> col:3{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    | |   `-CompoundStmt {{.*}} <col:7, col:8>
 // CHECK-NEXT:    | `-CompoundStmt {{.*}} <col:7, col:8>
@@ -179,7 +179,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | `-CXXMethodDecl {{.*}} <col:5, col:19> col:3{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    | |   `-CompoundStmt {{.*}} <col:7, col:19>
 // CHECK-NEXT:    | |     `-ReturnStmt {{.*}} <col:9, col:16>
@@ -195,7 +195,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:9, col:27> col:3{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:11, col:27>
 // CHECK-NEXT:    | | |   `-ReturnStmt {{.*}} <col:13, col:24>
@@ -224,7 +224,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:16, col:19> col:3{{( imported)?}} operator() 'auto () const -> auto' inline
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:18, col:19>
 // CHECK-NEXT:    | | |-FieldDecl {{.*}} <col:4> col:4{{( imported)?}} implicit 'Ts...'
@@ -241,7 +241,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:8, col:19> col:3{{( imported)?}} constexpr operator() 'auto () const' inline
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:18, col:19>
 // CHECK-NEXT:    | | |-CXXConversionDecl {{.*}} <col:3, col:19> col:3{{( imported)?}} implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
@@ -255,7 +255,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:8, col:17> col:3{{( imported)?}} operator() 'auto ()' inline
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:16, col:17>
 // CHECK-NEXT:    | | |-CXXConversionDecl {{.*}} <col:3, col:17> col:3{{( imported)?}} implicit constexpr operator auto (*)() 'auto (*() const noexcept)()' inline
@@ -269,7 +269,7 @@
 // CHECK-NEXT:    | | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:    | | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:    | | | |-MoveAssignment
-// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:    | | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:    | | |-CXXMethodDecl {{.*}} <col:8, col:18> col:3{{( imported)?}} operator() 'auto () const noexcept' inline
 // CHECK-NEXT:    | | | `-CompoundStmt {{.*}} <col:17, col:18>
 // CHECK-NEXT:    | | |-CXXConversionDecl {{.*}} <col:3, col:18> col:3{{( imported)?}} implicit constexpr operator auto (*)() noexcept 'auto (*() const noexcept)() noexcept' inline
@@ -283,7 +283,7 @@
 // CHECK-NEXT:      | | |-MoveConstructor exists simple trivial needs_implicit
 // CHECK-NEXT:      | | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param
 // CHECK-NEXT:      | | |-MoveAssignment
-// CHECK-NEXT:      | | `-Destructor simple irrelevant trivial needs_implicit
+// CHECK-NEXT:      | | `-Destructor simple irrelevant trivial{{( maybe_constexpr)?}} needs_implicit
 // CHECK-NEXT:      | |-CXXMethodDecl {{.*}} <col:11, col:27> col:3{{( imported)?}} operator() 'auto () const -> int' inline
 // CHECK-NEXT:      | | `-CompoundStmt {{.*}} <col:15, col:27>
 // CHECK-NEXT:      | |   `-ReturnStmt {{.*}} <col:17, col:24>
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1972,7 +1972,12 @@
       FLAG(hasTrivialDestructor, trivial);
       FLAG(hasNonTrivialDestructor, non_trivial);
       FLAG(hasUserDeclaredDestructor, user_declared);
-      FLAG(hasConstexprDestructor, constexpr);
+      // Avoid calls to the external source unless we are explicitly allowed
+      // to do so.
+      if (!D->hasExternalVisibleStorage() || getDeserialize()) {
+        FLAG(hasConstexprDestructor, constexpr);
+      } else
+        OS << " maybe_constexpr";
       FLAG(needsImplicitDestructor, needs_implicit);
       FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution);
       if (!D->needsOverloadResolutionForDestructor())
Index: clang/lib/AST/ASTDumper.cpp
===================================================================
--- clang/lib/AST/ASTDumper.cpp
+++ clang/lib/AST/ASTDumper.cpp
@@ -196,6 +196,7 @@
   } else {
     ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
     P.setDeserialize(Deserialize);
+    P.doGetNodeDelegate().setDeserialize(Deserialize);
     P.Visit(this);
   }
 }
Index: clang/include/clang/AST/TextNodeDumper.h
===================================================================
--- clang/include/clang/AST/TextNodeDumper.h
+++ clang/include/clang/AST/TextNodeDumper.h
@@ -42,10 +42,16 @@
   /// Indicates if we're handling the first child after entering a new depth.
   bool FirstChild = true;
 
+  /// Indicates if we can deserialize declarations from the ExternalASTSource.
+  bool Deserialize = true;
+
   /// Prefix for currently-being-dumped entity.
   std::string Prefix;
 
 public:
+  void setDeserialize(bool D) { Deserialize = D; }
+  bool getDeserialize() const { return Deserialize; }
+
   /// Add a child of the current node.  Calls DoAddChild without arguments
   template <typename Fn> void AddChild(Fn DoAddChild) {
     return AddChild("", DoAddChild);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to