balazske created this revision.
Herald added subscribers: cfe-commits, martong.
Herald added a reviewer: a.sidorin.

At import of a record describing a template set its type to
InjectedClassNameType (instead of RecordType).


Repository:
  rC Clang

https://reviews.llvm.org/D47450

Files:
  lib/AST/ASTImporter.cpp
  test/ASTMerge/injected-class-name-decl-1/Inputs/inject1.cpp
  test/ASTMerge/injected-class-name-decl-1/test.cpp
  test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp
  test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp
  test/ASTMerge/injected-class-name-decl/test.cpp

Index: test/ASTMerge/injected-class-name-decl/test.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/injected-class-name-decl/test.cpp
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.ast %S/Inputs/inject1.cpp
+// RUN: %clang_cc1 -std=c++1z -emit-obj -o /dev/null -ast-merge %t.ast %S/Inputs/inject2.cpp
+// expected-no-diagnostics
Index: test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/injected-class-name-decl/Inputs/inject2.cpp
@@ -0,0 +1 @@
+template<class X> X C<X>::x;
Index: test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/injected-class-name-decl/Inputs/inject1.cpp
@@ -0,0 +1 @@
+template<class X> class C { static X x; };
Index: test/ASTMerge/injected-class-name-decl-1/test.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/injected-class-name-decl-1/test.cpp
@@ -0,0 +1,6 @@
+// Trigger a case when at import of template record and replacing its type
+// with InjectedClassNameType there is a PrevDecl of the record.
+
+// RUN: %clang_cc1 -std=c++1z -emit-pch -o %t.ast %S/Inputs/inject1.cpp
+// RUN: %clang_cc1 -std=c++1z -fsyntax-only -ast-merge %t.ast %s
+// expected-no-diagnostics
Index: test/ASTMerge/injected-class-name-decl-1/Inputs/inject1.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/injected-class-name-decl-1/Inputs/inject1.cpp
@@ -0,0 +1,43 @@
+namespace a {
+template <typename> struct b;
+template <typename> struct c;
+template <typename, typename d> using e = d;
+class f;
+} // namespace a
+namespace google {
+namespace protobuf {
+namespace internal {
+class LogMessage {
+  LogMessage &operator<<(const char *);
+};
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+namespace a {
+template <typename> class g;
+namespace i {
+struct h;
+template <typename> struct F;
+struct G;
+template <bool> struct j;
+using k = g<int>;
+template <typename> struct l {};
+} // namespace i
+} // namespace a
+namespace a {
+using n = c<b<i::h>>;
+template <typename m> class g : i::F<e<int, i::j<m::p>>> {
+  template <typename> friend struct i::l;
+};
+} // namespace a
+namespace a {
+using i::G;
+}
+namespace google {
+namespace protobuf {
+namespace internal {
+LogMessage &LogMessage::operator<<(const char *) { return *this; }
+a::f *o;
+} // namespace internal
+} // namespace protobuf
+} // namespace google
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -2128,6 +2128,29 @@
         if (!ToDescribed)
           return nullptr;
         D2CXX->setDescribedClassTemplate(ToDescribed);
+        if (!DCXX->isInjectedClassName()) {
+          // In a record describing a template the type should be a
+          // InjectedClassNameType (see Sema::CheckClassTemplate). Update the
+          // previously set type to the correct value here (ToDescribed is not
+          // available at record create).
+          // FIXME: The previous type is cleared but not removed from
+          // ASTContext's internal storage.
+          CXXRecordDecl *Injected = nullptr;
+          for (NamedDecl *Found : D2CXX->noload_lookup(Name)) {
+            auto *Record = dyn_cast<CXXRecordDecl>(Found);
+            if (Record && Record->isInjectedClassName()) {
+              Injected = Record;
+              break;
+            }
+          }
+          D2CXX->setTypeForDecl(nullptr);
+          Importer.getToContext().getInjectedClassNameType(D2CXX,
+              ToDescribed->getInjectedClassNameSpecialization());
+          if (Injected) {
+            Injected->setTypeForDecl(nullptr);
+            Importer.getToContext().getTypeDeclType(Injected, D2CXX);
+          }
+        }
       } else if (MemberSpecializationInfo *MemberInfo =
                    DCXX->getMemberSpecializationInfo()) {
         TemplateSpecializationKind SK =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to