[llvm-branch-commits] [cfe-branch] r197320 - Merging r197298:

Bill Wendling isanbard at gmail.com
Fri Dec 13 23:59:40 PST 2013


Author: void
Date: Sat Dec 14 01:59:40 2013
New Revision: 197320

URL: http://llvm.org/viewvc/llvm-project?rev=197320&view=rev
Log:
Merging r197298:
------------------------------------------------------------------------
r197298 | rsmith | 2013-12-13 17:04:22 -0800 (Fri, 13 Dec 2013) | 3 lines

PR18232: implement instantiation for class-scope explicit specializations of
class templates (a Microsoft extension).

------------------------------------------------------------------------

Added:
    cfe/branches/release_34/test/SemaTemplate/ms-class-specialization-class-scope.cpp
      - copied unchanged from r197298, cfe/trunk/test/SemaTemplate/ms-class-specialization-class-scope.cpp
Modified:
    cfe/branches/release_34/   (props changed)
    cfe/branches/release_34/lib/AST/DeclCXX.cpp
    cfe/branches/release_34/lib/Sema/SemaTemplateInstantiateDecl.cpp

Propchange: cfe/branches/release_34/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Dec 14 01:59:40 2013
@@ -1,4 +1,4 @@
 /cfe/branches/type-system-rewrite:134693-134817
-/cfe/trunk:195126,195128,195135-195136,195146,195149,195154,195158,195163,195168,195174,195249,195268,195283,195303,195326,195329,195367,195384,195409,195420,195422,195495,195501,195547,195556,195558,195587,195620,195635,195669,195687,195693,195710,195713,195716,195756,195760,195768,195777,195789,195792,195804,195827,195843-195844,195877,195887-195888,195897,195903,195905-195906,195932,195936-195943,195970,195983,196045,196048,196050,196058,196114-196115,196143,196145,196153,196189-196192,196198-196199,196206,196208-196209,196211,196215,196359-196362,196370,196387,196423,196454,196456,196459,196488,196532-196533,196535,196538,196588,196593,196599,196612,196630,196658,196712,196720,196724,196771,196852,196957,196995,197022,197120,197305
+/cfe/trunk:195126,195128,195135-195136,195146,195149,195154,195158,195163,195168,195174,195249,195268,195283,195303,195326,195329,195367,195384,195409,195420,195422,195495,195501,195547,195556,195558,195587,195620,195635,195669,195687,195693,195710,195713,195716,195756,195760,195768,195777,195789,195792,195804,195827,195843-195844,195877,195887-195888,195897,195903,195905-195906,195932,195936-195943,195970,195983,196045,196048,196050,196058,196114-196115,196143,196145,196153,196189-196192,196198-196199,196206,196208-196209,196211,196215,196359-196362,196370,196387,196423,196454,196456,196459,196488,196532-196533,196535,196538,196588,196593,196599,196612,196630,196658,196712,196720,196724,196771,196852,196957,196995,197022,197120,197298,197305
 /cfe/trunk/test:170344
 /cfe/trunk/test/SemaTemplate:126920

Modified: cfe/branches/release_34/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/AST/DeclCXX.cpp?rev=197320&r1=197319&r2=197320&view=diff
==============================================================================
--- cfe/branches/release_34/lib/AST/DeclCXX.cpp (original)
+++ cfe/branches/release_34/lib/AST/DeclCXX.cpp Sat Dec 14 01:59:40 2013
@@ -1206,7 +1206,7 @@ CXXRecordDecl::setInstantiationOfMemberC
                                              TemplateSpecializationKind TSK) {
   assert(TemplateOrInstantiation.isNull() && 
          "Previous template or instantiation?");
-  assert(!isa<ClassTemplateSpecializationDecl>(this));
+  assert(!isa<ClassTemplatePartialSpecializationDecl>(this));
   TemplateOrInstantiation 
     = new (getASTContext()) MemberSpecializationInfo(RD, TSK);
 }

Modified: cfe/branches/release_34/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_34/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=197320&r1=197319&r2=197320&view=diff
==============================================================================
--- cfe/branches/release_34/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/branches/release_34/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Dec 14 01:59:40 2013
@@ -2317,8 +2317,144 @@ Decl *TemplateDeclInstantiator::VisitRec
 Decl *
 TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
     ClassTemplateSpecializationDecl *D) {
-  llvm_unreachable("Only ClassTemplatePartialSpecializationDecls occur"
-                   "inside templates");
+  // As a MS extension, we permit class-scope explicit specialization
+  // of member class templates.
+  ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate();
+  assert(ClassTemplate->getDeclContext()->isRecord() &&
+         D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
+         "can only instantiate an explicit specialization "
+         "for a member class template");
+
+  // Lookup the already-instantiated declaration in the instantiation
+  // of the class template. FIXME: Diagnose or assert if this fails?
+  DeclContext::lookup_result Found
+    = Owner->lookup(ClassTemplate->getDeclName());
+  if (Found.empty())
+    return 0;
+  ClassTemplateDecl *InstClassTemplate
+    = dyn_cast<ClassTemplateDecl>(Found.front());
+  if (!InstClassTemplate)
+    return 0;
+
+  // Substitute into the template arguments of the class template explicit
+  // specialization.
+  TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc().
+                                        castAs<TemplateSpecializationTypeLoc>();
+  TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(),
+                                            Loc.getRAngleLoc());
+  SmallVector<TemplateArgumentLoc, 4> ArgLocs;
+  for (unsigned I = 0; I != Loc.getNumArgs(); ++I)
+    ArgLocs.push_back(Loc.getArgLoc(I));
+  if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(),
+                    InstTemplateArgs, TemplateArgs))
+    return 0;
+
+  // Check that the template argument list is well-formed for this
+  // class template.
+  SmallVector<TemplateArgument, 4> Converted;
+  if (SemaRef.CheckTemplateArgumentList(InstClassTemplate,
+                                        D->getLocation(),
+                                        InstTemplateArgs,
+                                        false,
+                                        Converted))
+    return 0;
+
+  // Figure out where to insert this class template explicit specialization
+  // in the member template's set of class template explicit specializations.
+  void *InsertPos = 0;
+  ClassTemplateSpecializationDecl *PrevDecl =
+      InstClassTemplate->findSpecialization(Converted.data(), Converted.size(),
+                                            InsertPos);
+
+  // Check whether we've already seen a conflicting instantiation of this
+  // declaration (for instance, if there was a prior implicit instantiation).
+  bool Ignored;
+  if (PrevDecl &&
+      SemaRef.CheckSpecializationInstantiationRedecl(D->getLocation(),
+                                                     D->getSpecializationKind(),
+                                                     PrevDecl,
+                                                     PrevDecl->getSpecializationKind(),
+                                                     PrevDecl->getPointOfInstantiation(),
+                                                     Ignored))
+    return 0;
+
+  // If PrevDecl was a definition and D is also a definition, diagnose.
+  // This happens in cases like:
+  //
+  //   template<typename T, typename U>
+  //   struct Outer {
+  //     template<typename X> struct Inner;
+  //     template<> struct Inner<T> {};
+  //     template<> struct Inner<U> {};
+  //   };
+  //
+  //   Outer<int, int> outer; // error: the explicit specializations of Inner
+  //                          // have the same signature.
+  if (PrevDecl && PrevDecl->getDefinition() &&
+      D->isThisDeclarationADefinition()) {
+    SemaRef.Diag(D->getLocation(), diag::err_redefinition) << PrevDecl;
+    SemaRef.Diag(PrevDecl->getDefinition()->getLocation(),
+                 diag::note_previous_definition);
+    return 0;
+  }
+
+  // Create the class template partial specialization declaration.
+  ClassTemplateSpecializationDecl *InstD
+    = ClassTemplateSpecializationDecl::Create(SemaRef.Context,
+                                              D->getTagKind(),
+                                              Owner,
+                                              D->getLocStart(),
+                                              D->getLocation(),
+                                              InstClassTemplate,
+                                              Converted.data(),
+                                              Converted.size(),
+                                              PrevDecl);
+
+  // Add this partial specialization to the set of class template partial
+  // specializations.
+  if (!PrevDecl)
+    InstClassTemplate->AddSpecialization(InstD, InsertPos);
+
+  // Substitute the nested name specifier, if any.
+  if (SubstQualifier(D, InstD))
+    return 0;
+
+  // Build the canonical type that describes the converted template
+  // arguments of the class template explicit specialization.
+  QualType CanonType = SemaRef.Context.getTemplateSpecializationType(
+      TemplateName(InstClassTemplate), Converted.data(), Converted.size(),
+      SemaRef.Context.getRecordType(InstD));
+
+  // Build the fully-sugared type for this class template
+  // specialization as the user wrote in the specialization
+  // itself. This means that we'll pretty-print the type retrieved
+  // from the specialization's declaration the way that the user
+  // actually wrote the specialization, rather than formatting the
+  // name based on the "canonical" representation used to store the
+  // template arguments in the specialization.
+  TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo(
+      TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs,
+      CanonType);
+
+  InstD->setAccess(D->getAccess());
+  InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
+  InstD->setSpecializationKind(D->getSpecializationKind());
+  InstD->setTypeAsWritten(WrittenTy);
+  InstD->setExternLoc(D->getExternLoc());
+  InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc());
+
+  Owner->addDecl(InstD);
+
+  // Instantiate the members of the class-scope explicit specialization eagerly.
+  // We don't have support for lazy instantiation of an explicit specialization
+  // yet, and MSVC eagerly instantiates in this case.
+  if (D->isThisDeclarationADefinition() &&
+      SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs,
+                               TSK_ImplicitInstantiation,
+                               /*Complain=*/true))
+    return 0;
+
+  return InstD;
 }
 
 Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(





More information about the llvm-branch-commits mailing list