]> granicus.if.org Git - clang/commitdiff
[modules] Reconstruct template default argument inheritance on reload rather
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 10 Jun 2015 01:47:58 +0000 (01:47 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 10 Jun 2015 01:47:58 +0000 (01:47 +0000)
than wasting storage and triggering eager deserializations by serializing it.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@239454 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp

index 63841fbca1a7707dfda97209ad761d5d5405b8c8..af125cf660cd8cf1697879820a5f8589f74ed9fd 100644 (file)
@@ -2034,11 +2034,6 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
   D->setDeclaredWithTypename(Record[Idx++]);
 
   if (Record[Idx++])
-    // FIXME: Rebuild inherited default argument chain when linking together
-    // the redecl chain.
-    D->setInheritedDefaultArgument(
-        Reader.getContext(), ReadDeclAs<TemplateTypeParmDecl>(Record, Idx));
-  else
     D->setDefaultArgument(GetTypeSourceInfo(Record, Idx));
 }
 
@@ -2057,12 +2052,6 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
     // Rest of NonTypeTemplateParmDecl.
     D->ParameterPack = Record[Idx++];
     if (Record[Idx++])
-      // FIXME: Rebuild inherited default argument chain when linking together
-      // the redecl chain.
-      D->setInheritedDefaultArgument(
-          Reader.getContext(),
-          ReadDeclAs<NonTypeTemplateParmDecl>(Record, Idx));
-    else
       D->setDefaultArgument(Reader.ReadExpr(F));
   }
 }
@@ -2081,12 +2070,6 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
     // Rest of TemplateTemplateParmDecl.
     D->ParameterPack = Record[Idx++];
     if (Record[Idx++])
-      // FIXME: Rebuild inherited default argument chain when linking together
-      // the redecl chain.
-      D->setInheritedDefaultArgument(
-          Reader.getContext(),
-          ReadDeclAs<TemplateTemplateParmDecl>(Record, Idx));
-    else
       D->setDefaultArgument(Reader.getContext(),
                             Reader.ReadTemplateArgumentLoc(F, Record, Idx));
   }
@@ -2917,6 +2900,44 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
   llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
 }
 
+/// Inherit the default template argument from \p From to \p To. Returns
+/// \c false if there is no default template for \p From.
+template <typename ParmDecl>
+static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From,
+                                           Decl *ToD) {
+  auto *To = cast<ParmDecl>(ToD);
+  if (!From->hasDefaultArgument())
+    return false;
+  if (!To->hasDefaultArgument())
+    To->setInheritedDefaultArgument(Context, From);
+  return true;
+}
+
+static void inheritDefaultTemplateArguments(ASTContext &Context,
+                                            TemplateDecl *From,
+                                            TemplateDecl *To) {
+  auto *FromTP = From->getTemplateParameters();
+  auto *ToTP = To->getTemplateParameters();
+  assert(FromTP->size() == ToTP->size() && "merged mismatched templates?");
+
+  for (unsigned I = 0, N = FromTP->size(); I != N; ++I) {
+    NamedDecl *FromParam = FromTP->getParam(N - I - 1);
+    NamedDecl *ToParam = ToTP->getParam(N - I - 1);
+
+    if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam)) {
+      if (inheritDefaultTemplateArgument(Context, FTTP, ToParam))
+        break;
+    } else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) {
+      if (inheritDefaultTemplateArgument(Context, FNTTP, ToParam))
+        break;
+    } else {
+      if (inheritDefaultTemplateArgument(
+              Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam))
+        break;
+    }
+  }
+}
+
 void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
                                        Decl *Previous, Decl *Canon) {
   assert(D && Previous);
@@ -2943,6 +2964,12 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
   // be too.
   if (Previous->Used)
     D->Used = true;
+
+  // If the declaration declares a template, it may inherit default arguments
+  // from the previous declaration.
+  if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+    inheritDefaultTemplateArguments(Reader.getContext(),
+                                    cast<TemplateDecl>(Previous), TD);
 }
 
 template<typename DeclT>
index f08f1409916f0b7d4bfa4bcffe8da521b520d2ae..29b948d3214bec655d5fb3ea78ed1e918a50e584 100644 (file)
@@ -1380,10 +1380,11 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
   VisitTypeDecl(D);
 
   Record.push_back(D->wasDeclaredWithTypename());
-  Record.push_back(D->defaultArgumentWasInherited());
-  if (D->defaultArgumentWasInherited())
-    Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record);
-  else
+
+  bool OwnsDefaultArg = D->hasDefaultArgument() &&
+                        !D->defaultArgumentWasInherited();
+  Record.push_back(OwnsDefaultArg);
+  if (OwnsDefaultArg)
     Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record);
 
   Code = serialization::DECL_TEMPLATE_TYPE_PARM;
@@ -1411,10 +1412,10 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
   } else {
     // Rest of NonTypeTemplateParmDecl.
     Record.push_back(D->isParameterPack());
-    Record.push_back(D->defaultArgumentWasInherited());
-    if (D->defaultArgumentWasInherited())
-      Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record);
-    else
+    bool OwnsDefaultArg = D->hasDefaultArgument() &&
+                          !D->defaultArgumentWasInherited();
+    Record.push_back(OwnsDefaultArg);
+    if (OwnsDefaultArg)
       Writer.AddStmt(D->getDefaultArgument());
     Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
   }
@@ -1441,10 +1442,10 @@ void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
   } else {
     // Rest of TemplateTemplateParmDecl.
     Record.push_back(D->isParameterPack());
-    Record.push_back(D->defaultArgumentWasInherited());
-    if (D->defaultArgumentWasInherited())
-      Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record);
-    else
+    bool OwnsDefaultArg = D->hasDefaultArgument() &&
+                          !D->defaultArgumentWasInherited();
+    Record.push_back(OwnsDefaultArg);
+    if (OwnsDefaultArg)
       Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record);
     Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM;
   }