@@ -6385,16 +6385,19 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) {
63856385
63866386ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl (
63876387 VarTemplateSpecializationDecl *D) {
6388- // If this record has a definition in the translation unit we're coming from,
6389- // but this particular declaration is not that definition, import the
6390- // definition and map to that.
6391- VarDecl *Definition = D->getDefinition ();
6392- if (Definition && Definition != D) {
6393- if (ExpectedDecl ImportedDefOrErr = import (Definition))
6394- return Importer.MapImported (D, *ImportedDefOrErr);
6395- else
6396- return ImportedDefOrErr.takeError ();
6388+ // A VarTemplateSpecializationDecl inherits from VarDecl, the import is done
6389+ // in an analog way (but specialized for this case).
6390+
6391+ SmallVector<Decl *, 2 > Redecls = getCanonicalForwardRedeclChain (D);
6392+ auto RedeclIt = Redecls.begin ();
6393+ // Import the first part of the decl chain. I.e. import all previous
6394+ // declarations starting from the canonical decl.
6395+ for (; RedeclIt != Redecls.end () && *RedeclIt != D; ++RedeclIt) {
6396+ ExpectedDecl RedeclOrErr = import (*RedeclIt);
6397+ if (!RedeclOrErr)
6398+ return RedeclOrErr.takeError ();
63976399 }
6400+ assert (*RedeclIt == D);
63986401
63996402 VarTemplateDecl *VarTemplate = nullptr ;
64006403 if (Error Err = importInto (VarTemplate, D->getSpecializedTemplate ()))
@@ -6422,116 +6425,132 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
64226425
64236426 // Try to find an existing specialization with these template arguments.
64246427 void *InsertPos = nullptr ;
6425- VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization (
6426- TemplateArgs, InsertPos);
6427- if (D2) {
6428- // We already have a variable template specialization with these template
6429- // arguments.
6430-
6431- // FIXME: Check for specialization vs. instantiation errors.
6432-
6433- if (VarDecl *FoundDef = D2->getDefinition ()) {
6434- if (!D->isThisDeclarationADefinition () ||
6435- IsStructuralMatch (D, FoundDef)) {
6436- // The record types structurally match, or the "from" translation
6437- // unit only had a forward declaration anyway; call it the same
6438- // variable.
6439- return Importer.MapImported (D, FoundDef);
6428+ VarTemplateSpecializationDecl *FoundSpecialization =
6429+ VarTemplate->findSpecialization (TemplateArgs, InsertPos);
6430+ if (FoundSpecialization) {
6431+ if (IsStructuralMatch (D, FoundSpecialization)) {
6432+ VarDecl *FoundDef = FoundSpecialization->getDefinition ();
6433+ if (D->getDeclContext ()->isRecord ()) {
6434+ // In a record, it is allowed only to have one optional declaration and
6435+ // one definition of the (static or constexpr) variable template.
6436+ assert (
6437+ FoundSpecialization->getDeclContext ()->isRecord () &&
6438+ " Member variable template specialization imported as non-member, "
6439+ " inconsistent imported AST?" );
6440+ if (FoundDef)
6441+ return Importer.MapImported (D, FoundDef);
6442+ if (!D->isThisDeclarationADefinition ())
6443+ return Importer.MapImported (D, FoundSpecialization);
6444+ } else {
6445+ // If definition is imported and there is already one, map to it.
6446+ // Otherwise create a new variable and link it to the existing.
6447+ if (FoundDef && D->isThisDeclarationADefinition ())
6448+ return Importer.MapImported (D, FoundDef);
64406449 }
6450+ } else {
6451+ return make_error<ASTImportError>(ASTImportError::NameConflict);
64416452 }
6442- } else {
6443- TemplateArgumentListInfo ToTAInfo;
6444- if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo ()) {
6445- if (Error Err = ImportTemplateArgumentListInfo (*Args, ToTAInfo))
6446- return std::move (Err);
6447- }
6453+ }
64486454
6449- using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
6450- // Create a new specialization.
6451- if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) {
6452- // Import TemplateArgumentListInfo
6453- TemplateArgumentListInfo ArgInfos;
6454- const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten ();
6455- // NOTE: FromTAArgsAsWritten and template parameter list are non-null.
6456- if (Error Err = ImportTemplateArgumentListInfo (
6457- *FromTAArgsAsWritten, ArgInfos))
6458- return std::move (Err);
6455+ VarTemplateSpecializationDecl *D2 = nullptr ;
64596456
6460- auto ToTPListOrErr = import (FromPartial->getTemplateParameters ());
6461- if (!ToTPListOrErr)
6462- return ToTPListOrErr.takeError ();
6457+ TemplateArgumentListInfo ToTAInfo;
6458+ if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo ()) {
6459+ if (Error Err = ImportTemplateArgumentListInfo (*Args, ToTAInfo))
6460+ return std::move (Err);
6461+ }
64636462
6464- PartVarSpecDecl *ToPartial;
6465- if (GetImportedOrCreateDecl (ToPartial, D, Importer.getToContext (), DC,
6466- *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
6467- VarTemplate, QualType (), nullptr ,
6468- D->getStorageClass (), TemplateArgs, ArgInfos))
6469- return ToPartial;
6463+ using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
6464+ // Create a new specialization.
6465+ if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) {
6466+ // Import TemplateArgumentListInfo
6467+ TemplateArgumentListInfo ArgInfos;
6468+ const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten ();
6469+ // NOTE: FromTAArgsAsWritten and template parameter list are non-null.
6470+ if (Error Err =
6471+ ImportTemplateArgumentListInfo (*FromTAArgsAsWritten, ArgInfos))
6472+ return std::move (Err);
64706473
6471- if (Expected<PartVarSpecDecl *> ToInstOrErr = import (
6472- FromPartial->getInstantiatedFromMember ()))
6473- ToPartial->setInstantiatedFromMember (*ToInstOrErr);
6474- else
6475- return ToInstOrErr.takeError ();
6476-
6477- if (FromPartial->isMemberSpecialization ())
6478- ToPartial->setMemberSpecialization ();
6479-
6480- D2 = ToPartial;
6481-
6482- // FIXME: Use this update if VarTemplatePartialSpecializationDecl is fixed
6483- // to adopt template parameters.
6484- // updateLookupTableForTemplateParameters(**ToTPListOrErr);
6485- } else { // Full specialization
6486- if (GetImportedOrCreateDecl (D2, D, Importer.getToContext (), DC,
6487- *BeginLocOrErr, *IdLocOrErr, VarTemplate,
6488- QualType (), nullptr , D->getStorageClass (),
6489- TemplateArgs))
6490- return D2;
6491- }
6474+ auto ToTPListOrErr = import (FromPartial->getTemplateParameters ());
6475+ if (!ToTPListOrErr)
6476+ return ToTPListOrErr.takeError ();
64926477
6493- QualType T;
6494- if (Error Err = importInto (T, D->getType ()))
6495- return std::move (Err);
6496- D2->setType (T);
6478+ PartVarSpecDecl *ToPartial;
6479+ if (GetImportedOrCreateDecl (ToPartial, D, Importer.getToContext (), DC,
6480+ *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
6481+ VarTemplate, QualType (), nullptr ,
6482+ D->getStorageClass (), TemplateArgs, ArgInfos))
6483+ return ToPartial;
64976484
6498- auto TInfoOrErr = import (D->getTypeSourceInfo ());
6499- if (!TInfoOrErr)
6500- return TInfoOrErr.takeError ();
6501- D2->setTypeSourceInfo (*TInfoOrErr);
6485+ if (Expected<PartVarSpecDecl *> ToInstOrErr =
6486+ import (FromPartial->getInstantiatedFromMember ()))
6487+ ToPartial->setInstantiatedFromMember (*ToInstOrErr);
6488+ else
6489+ return ToInstOrErr.takeError ();
65026490
6503- if (D->getPointOfInstantiation ().isValid ()) {
6504- if (ExpectedSLoc POIOrErr = import (D->getPointOfInstantiation ()))
6505- D2->setPointOfInstantiation (*POIOrErr);
6506- else
6507- return POIOrErr.takeError ();
6508- }
6491+ if (FromPartial->isMemberSpecialization ())
6492+ ToPartial->setMemberSpecialization ();
6493+
6494+ D2 = ToPartial;
65096495
6510- D2->setSpecializationKind (D->getSpecializationKind ());
6511- D2->setTemplateArgsInfo (ToTAInfo);
6496+ // FIXME: Use this update if VarTemplatePartialSpecializationDecl is fixed
6497+ // to adopt template parameters.
6498+ // updateLookupTableForTemplateParameters(**ToTPListOrErr);
6499+ } else { // Full specialization
6500+ if (GetImportedOrCreateDecl (D2, D, Importer.getToContext (), DC,
6501+ *BeginLocOrErr, *IdLocOrErr, VarTemplate,
6502+ QualType (), nullptr , D->getStorageClass (),
6503+ TemplateArgs))
6504+ return D2;
6505+ }
65126506
6513- // Add this specialization to the class template.
6514- VarTemplate->AddSpecialization (D2, InsertPos);
6507+ QualType T;
6508+ if (Error Err = importInto (T, D->getType ()))
6509+ return std::move (Err);
6510+ D2->setType (T);
65156511
6516- // Import the qualifier, if any.
6517- if (auto LocOrErr = import (D->getQualifierLoc ()))
6518- D2->setQualifierInfo (*LocOrErr);
6512+ auto TInfoOrErr = import (D->getTypeSourceInfo ());
6513+ if (!TInfoOrErr)
6514+ return TInfoOrErr.takeError ();
6515+ D2->setTypeSourceInfo (*TInfoOrErr);
6516+
6517+ if (D->getPointOfInstantiation ().isValid ()) {
6518+ if (ExpectedSLoc POIOrErr = import (D->getPointOfInstantiation ()))
6519+ D2->setPointOfInstantiation (*POIOrErr);
65196520 else
6520- return LocOrErr.takeError ();
6521+ return POIOrErr.takeError ();
6522+ }
65216523
6522- if (D->isConstexpr ())
6523- D2->setConstexpr ( true );
6524+ D2-> setSpecializationKind (D->getSpecializationKind ());
6525+ D2->setTemplateArgsInfo (ToTAInfo );
65246526
6525- // Add the specialization to this context.
6526- D2->setLexicalDeclContext (LexicalDC);
6527- LexicalDC->addDeclInternal (D2);
6527+ if (auto LocOrErr = import (D->getQualifierLoc ()))
6528+ D2->setQualifierInfo (*LocOrErr);
6529+ else
6530+ return LocOrErr.takeError ();
65286531
6529- D2->setAccess (D->getAccess ());
6530- }
6532+ if (D->isConstexpr ())
6533+ D2->setConstexpr (true );
6534+
6535+ D2->setAccess (D->getAccess ());
65316536
65326537 if (Error Err = ImportInitializer (D, D2))
65336538 return std::move (Err);
65346539
6540+ if (FoundSpecialization)
6541+ D2->setPreviousDecl (FoundSpecialization->getMostRecentDecl ());
6542+
6543+ VarTemplate->AddSpecialization (D2, InsertPos);
6544+
6545+ addDeclToContexts (D, D2);
6546+
6547+ // Import the rest of the chain. I.e. import all subsequent declarations.
6548+ for (++RedeclIt; RedeclIt != Redecls.end (); ++RedeclIt) {
6549+ ExpectedDecl RedeclOrErr = import (*RedeclIt);
6550+ if (!RedeclOrErr)
6551+ return RedeclOrErr.takeError ();
6552+ }
6553+
65356554 return D2;
65366555}
65376556
0 commit comments