Tyker created this revision.
Tyker added a reviewer: rsmith.
Tyker added a project: clang.
Herald added a subscriber: cfe-commits.
Tyker added a parent revision: D69360: [NFC] Refactor representation of 
materialized temporaries.

Add support for merging lifetime-extended temporaries


Repository:
  rC Clang

https://reviews.llvm.org/D70190

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/AST/TextNodeDumper.h
  clang/include/clang/Serialization/ASTReader.h
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Serialization/ASTReaderDecl.cpp
  clang/test/Modules/Inputs/merge-lifetime-extended-temporary/a.h
  clang/test/Modules/Inputs/merge-lifetime-extended-temporary/b.h
  clang/test/Modules/Inputs/merge-lifetime-extended-temporary/c.h
  clang/test/Modules/Inputs/merge-lifetime-extended-temporary/module.modulemap
  clang/test/Modules/merge-lifetime-extended-temporary.cpp

Index: clang/test/Modules/merge-lifetime-extended-temporary.cpp
===================================================================
--- /dev/null
+++ clang/test/Modules/merge-lifetime-extended-temporary.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-lifetime-extended-temporary -verify -std=c++11 %s -DORDER=1
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x c++ -I%S/Inputs/merge-lifetime-extended-temporary -verify -std=c++11 %s -DORDER=2
+
+// expected-no-diagnostics
+#if ORDER == 1
+#include "c.h"
+#include "b.h"
+#else
+#include "b.h"
+#include "c.h"
+#endif
+
+static_assert(PtrTemp1 == &LETemp, "");
+static_assert(PtrTemp1 == PtrTemp2, "");
Index: clang/test/Modules/Inputs/merge-lifetime-extended-temporary/module.modulemap
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/merge-lifetime-extended-temporary/module.modulemap
@@ -0,0 +1,14 @@
+module "a" {
+  export *
+  header "a.h"
+}
+
+module "b" {
+  export *
+  header "b.h"
+}
+
+module "c" {
+  export *
+  header "c.h"
+}
\ No newline at end of file
Index: clang/test/Modules/Inputs/merge-lifetime-extended-temporary/c.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/merge-lifetime-extended-temporary/c.h
@@ -0,0 +1,4 @@
+
+#include "a.h"
+
+constexpr const int* PtrTemp2 = &LETemp;
\ No newline at end of file
Index: clang/test/Modules/Inputs/merge-lifetime-extended-temporary/b.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/merge-lifetime-extended-temporary/b.h
@@ -0,0 +1,4 @@
+
+#include "a.h"
+
+constexpr const int* PtrTemp1 = &LETemp;
\ No newline at end of file
Index: clang/test/Modules/Inputs/merge-lifetime-extended-temporary/a.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/merge-lifetime-extended-temporary/a.h
@@ -0,0 +1,2 @@
+
+constexpr const int& LETemp = 0;
Index: clang/lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderDecl.cpp
+++ clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2355,6 +2355,7 @@
   if (Record.readInt())
     D->Value = new (D->getASTContext()) APValue(Record.readAPValue());
   D->ManglingNumber = Record.readInt();
+  mergeMergeable(D);
 }
 
 std::pair<uint64_t, uint64_t>
@@ -2562,17 +2563,32 @@
   if (!Reader.getContext().getLangOpts().Modules)
     return;
 
+  Decl* RealDecl = static_cast<T *>(D);
+
   // ODR-based merging is performed in C++ and in some cases (tag types) in C.
   // Note that C identically-named things in different translation units are
   // not redeclarations, but may still have compatible types, where ODR-like
   // semantics may apply.
   if (!Reader.getContext().getLangOpts().CPlusPlus &&
-      !allowODRLikeMergeInC(dyn_cast<NamedDecl>(static_cast<T*>(D))))
+      !allowODRLikeMergeInC(dyn_cast<NamedDecl>(RealDecl)))
+    return;
+
+  if (auto *LETDecl = dyn_cast<LifetimeExtendedTemporaryDecl>(RealDecl)) {
+    LETDecl->dump();
+    auto LookupResult =
+        Reader.LETemporaryForMerging.FindAndConstruct(std::make_pair(
+            LETDecl->getExtendingDecl(), LETDecl->getManglingNumber()));
+    if (LookupResult.getSecond())
+      Reader.getContext().setPrimaryMergedDecl(
+          LETDecl, LookupResult.getSecond()->getCanonicalDecl());
+    else
+      LookupResult.getSecond() = LETDecl;
     return;
+  }
 
-  if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
+  if (FindExistingResult ExistingRes = findExisting(cast<NamedDecl>(RealDecl)))
     if (T *Existing = ExistingRes)
-      Reader.getContext().setPrimaryMergedDecl(static_cast<T *>(D),
+      Reader.getContext().setPrimaryMergedDecl(RealDecl,
                                                Existing->getCanonicalDecl());
 }
 
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1338,6 +1338,18 @@
     OS << " <<<NULL params x " << D->getNumParams() << ">>>";
 }
 
+void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D) {
+  OS << " extended by ";
+  dumpBareDeclRef(D->getExtendingDecl());
+  OS << " mangling ";
+  {
+    ColorScope Color(OS, ShowColors, ValueColor);
+    OS << D->getManglingNumber();
+  }
+  OS << " subexpr";
+  dumpPointer(D);
+}
+
 void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) {
   dumpName(D);
   dumpType(D->getType());
Index: clang/include/clang/Serialization/ASTReader.h
===================================================================
--- clang/include/clang/Serialization/ASTReader.h
+++ clang/include/clang/Serialization/ASTReader.h
@@ -551,6 +551,14 @@
   llvm::DenseMap<Decl*, llvm::SmallVector<NamedDecl*, 2>>
     AnonymousDeclarationsForMerging;
 
+  /// Key used to identify LifetimeExtendedTemporaryDecl for merging.
+  /// containg the lifetime-extending declaration and the mangling number.
+  using LETemporaryKey = std::pair<Decl *, unsigned>;
+
+  /// Map of already deserialiazed temporaries.
+  llvm::DenseMap<LETemporaryKey, LifetimeExtendedTemporaryDecl *>
+      LETemporaryForMerging;
+
   struct FileDeclsInfo {
     ModuleFile *Mod = nullptr;
     ArrayRef<serialization::LocalDeclID> Decls;
Index: clang/include/clang/AST/TextNodeDumper.h
===================================================================
--- clang/include/clang/AST/TextNodeDumper.h
+++ clang/include/clang/AST/TextNodeDumper.h
@@ -346,6 +346,8 @@
   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
   void VisitBlockDecl(const BlockDecl *D);
   void VisitConceptDecl(const ConceptDecl *D);
+  void
+  VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
 };
 
 } // namespace clang
Index: clang/include/clang/AST/DeclCXX.h
===================================================================
--- clang/include/clang/AST/DeclCXX.h
+++ clang/include/clang/AST/DeclCXX.h
@@ -3054,7 +3054,9 @@
 
 /// Implicit declartion of a temporary that was materialized by
 /// MaterializeTemporaryExpr
-class LifetimeExtendedTemporaryDecl final : public Decl {
+class LifetimeExtendedTemporaryDecl final
+    : public Decl,
+      public Mergeable<LifetimeExtendedTemporaryDecl> {
   friend class MaterializeTemporaryExpr;
   friend class ASTDeclReader;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to