a.sidorin updated this revision to Diff 79054.
a.sidorin added a comment.

Add a simple test for import of complex `NestedNameSpecifierLoc`s.


https://reviews.llvm.org/D26753

Files:
  include/clang/AST/TemplateBase.h
  lib/AST/ASTImporter.cpp
  
test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp
  
test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp
  test/ASTMerge/class-template-partial-spec/test.cpp

Index: test/ASTMerge/class-template-partial-spec/test.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/class-template-partial-spec/test.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.1.ast %S/Inputs/class-template-partial-spec1.cpp
+// RUN: %clang_cc1 -emit-pch -std=c++1z -o %t.2.ast %S/Inputs/class-template-partial-spec2.cpp
+// RUN: not %clang_cc1 -std=c++1z -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
+
+static_assert(sizeof(**SingleSource.member) == sizeof(**SingleDest.member));
+static_assert(sizeof(SecondDoubleSource.member) == sizeof(SecondDoubleDest.member));
+static_assert(NumberSource.val == 42);
+static_assert(sizeof(Z0Source.member) == sizeof(char));
+static_assert(sizeof(Dst::Z0Dst.member) == sizeof(double));
+static_assert(sizeof(One::Child1<double, One::Two::Three::Parent<double>>::member) == sizeof(double));
+
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp:21:32: error: external variable 'X1' declared with incompatible types in different translation units ('TwoOptionTemplate<int, double>' vs. 'TwoOptionTemplate<int, float>')
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp:21:31: note: declared here with type 'TwoOptionTemplate<int, float>'
+
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp:24:29: error: external variable 'X4' declared with incompatible types in different translation units ('TwoOptionTemplate<int, int>' vs. 'TwoOptionTemplate<float, float>')
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp:24:33: note: declared here with type 'TwoOptionTemplate<float, float>'
+
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp:38:8: warning: type 'IntTemplateSpec<5, void *>' has incompatible definitions in different translation units
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp:39:7: note: field 'member' has type 'int' here
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp:39:10: note: field 'member' has type 'double' here
+
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp:52:25: error: external variable 'Y3' declared with incompatible types in different translation units ('IntTemplateSpec<2, int>' vs. 'IntTemplateSpec<3, int>')
+// CHECK: /media/build/smrc-llvm/master/llvm/tools/clang/test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp:52:25: note: declared here with type 'IntTemplateSpec<3, int>'
+
+// CHECK-NOT: static_assert
Index: test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec2.cpp
@@ -0,0 +1,79 @@
+template<typename T, typename P>
+struct TwoOptionTemplate {};
+
+template<typename T>
+struct TwoOptionTemplate<T, char> {
+  int member;
+};
+
+
+template<typename T>
+struct TwoOptionTemplate<T, double> {
+  float member;
+};
+
+template<typename T>
+struct TwoOptionTemplate<T, T> {
+  T** member;
+};
+
+TwoOptionTemplate<int, char> X0;
+TwoOptionTemplate<int, double> X1;
+TwoOptionTemplate<void *, wchar_t> X2;
+TwoOptionTemplate<long, long> X3;
+TwoOptionTemplate<int, int> X4;
+TwoOptionTemplate<long, long> SingleDest;
+TwoOptionTemplate<int, double> SecondDoubleDest;
+
+
+template<int I, class C>
+struct IntTemplateSpec {};
+
+template<class C>
+struct IntTemplateSpec<4, C> {
+  C member;
+};
+
+template<int I>
+struct IntTemplateSpec<I, void *> {
+  double member;
+  static constexpr int val = I;
+};
+
+template<int I>
+struct IntTemplateSpec<I, double> {
+  char member;
+  static constexpr int val = I;
+};
+
+IntTemplateSpec<4, wchar_t>Y0;
+IntTemplateSpec<5, void *> Y1;
+IntTemplateSpec<1, int> Y2;
+IntTemplateSpec<2, int> Y3;
+IntTemplateSpec<43, double> NumberDest;
+
+namespace One {
+namespace Two {
+namespace Three {
+
+template<class T>
+class Parent {};
+
+} // namespace Three
+
+} // namespace Two
+
+template<typename T, typename X>
+struct Child1: public Two::Three::Parent<unsigned> {
+  char member;
+};
+
+template<class T>
+struct Child1<T, One::Two::Three::Parent<T>> {
+  T member;
+};
+
+} // namespace One
+
+namespace Dst { One::Child1<double, One::Two::Three::Parent<double>> Z0Dst; }
+One::Child1<int, float> Z1;
Index: test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/class-template-partial-spec/Inputs/class-template-partial-spec1.cpp
@@ -0,0 +1,118 @@
+template<typename T, class P>
+struct TwoOptionTemplate {};
+
+template<typename T>
+struct TwoOptionTemplate<T, char> {
+  int member;
+};
+
+
+template<typename T>
+struct TwoOptionTemplate<T, double> {
+  float member;
+};
+
+template<typename T>
+struct TwoOptionTemplate<T, T> {
+  T** member;
+};
+
+TwoOptionTemplate<int, char> X0;
+TwoOptionTemplate<int, float> X1;
+TwoOptionTemplate<void *, wchar_t> X2;
+TwoOptionTemplate<long, long> X3;
+TwoOptionTemplate<float, float> X4;
+TwoOptionTemplate<long, long> SingleSource;
+TwoOptionTemplate<char, double> SecondDoubleSource;
+
+
+template<int I, class C>
+struct IntTemplateSpec {};
+
+template<class C>
+struct IntTemplateSpec<4, C> {
+  C member;
+};
+
+template<int I>
+struct IntTemplateSpec<I, void *> {
+  int member;
+  static constexpr int val = I;
+};
+
+template<int I>
+struct IntTemplateSpec<I, double> {
+  char member;
+  static constexpr int val = I;
+};
+
+IntTemplateSpec<4, wchar_t> Y0;
+IntTemplateSpec<5, void *> Y1;
+IntTemplateSpec<1, long> Y2;
+IntTemplateSpec<3, int> Y3;
+//template<int I> constexpr int IntTemplateSpec<I, double>::val;
+IntTemplateSpec<42, double> NumberSource;
+static_assert(NumberSource.val == 42);
+
+namespace One {
+namespace Two {
+  // Just an empty namespace to ensure we can deal with multiple namespace decls.
+}
+}
+
+
+namespace One {
+namespace Two {
+namespace Three {
+
+template<class T>
+class Parent {};
+
+} // namespace Three
+
+} // namespace Two
+
+template<typename T, typename X>
+struct Child1: public Two::Three::Parent<unsigned> {
+  char member;
+};
+
+template<class T>
+struct Child1<T, One::Two::Three::Parent<T>> {
+  T member;
+};
+
+} // namespace One
+
+One::Child1<int, double> Z0Source;
+
+// Test import of nested namespace specifiers
+template<typename T>
+struct Outer {
+  template<typename U> class Inner0;
+};
+
+template<typename X>
+template<typename Y>
+class Outer<X>::Inner0 {
+public:
+  void f(X, Y);
+  template<typename Z> struct Inner1;
+};
+
+template<typename X>
+template<typename Y>
+void Outer<X>::Inner0<Y>::f(X, Y) {}
+
+template<typename X>
+template<typename Y>
+template<typename Z>
+class Outer<X>::Inner0<Y>::Inner1 {
+public:
+  void f(Y, Z);
+};
+
+template<typename X>
+template<typename Y>
+template<typename Z>
+void Outer<X>::Inner0<Y>::Inner1<Z>::f(Y, Z) {}
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -71,7 +71,7 @@
     QualType VisitEnumType(const EnumType *T);
     QualType VisitAttributedType(const AttributedType *T);
     QualType VisitTemplateTypeParmType(const TemplateTypeParmType *T);
-    // FIXME: SubstTemplateTypeParmType
+    QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
     QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
     QualType VisitElaboratedType(const ElaboratedType *T);
     // FIXME: DependentNameType
@@ -275,6 +275,8 @@
     Expr *VisitInitListExpr(InitListExpr *E);
     Expr *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
     Expr *VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
+    Expr *VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
+
 
     template<typename IIter, typename OIter>
     void ImportArray(IIter Ibegin, IIter Iend, OIter Obegin) {
@@ -394,6 +396,9 @@
                                      QualType T1, QualType T2);
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
                                      Decl *D1, Decl *D2);
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+                                     const TemplateArgument &Arg1,
+                                     const TemplateArgument &Arg2);
 
 /// \brief Determine structural equivalence of two expressions.
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
@@ -418,8 +423,103 @@
 static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
                                      NestedNameSpecifier *NNS1,
                                      NestedNameSpecifier *NNS2) {
-  // FIXME: Implement!
-  return true;
+  if (NNS1->getKind() != NNS2->getKind())
+    return false;
+
+  NestedNameSpecifier *Prefix1 = NNS1->getPrefix(),
+      *Prefix2 = NNS2->getPrefix();
+  if ((bool)Prefix1 != (bool)Prefix2)
+    return false;
+
+  if (Prefix1)
+    if (!IsStructurallyEquivalent(Context, Prefix1, Prefix2))
+      return false;
+
+  switch (NNS1->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    return IsStructurallyEquivalent(NNS1->getAsIdentifier(),
+                                    NNS2->getAsIdentifier());
+  case NestedNameSpecifier::Namespace:
+    return IsStructurallyEquivalent(Context, NNS1->getAsNamespace(),
+                                    NNS2->getAsNamespace());
+  case NestedNameSpecifier::NamespaceAlias:
+    return IsStructurallyEquivalent(Context, NNS1->getAsNamespaceAlias(),
+                                    NNS2->getAsNamespaceAlias());
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+    return IsStructurallyEquivalent(Context, QualType(NNS1->getAsType(), 0),
+                                    QualType(NNS2->getAsType(), 0));
+  case NestedNameSpecifier::Global:
+    return true;
+  case NestedNameSpecifier::Super:
+    return IsStructurallyEquivalent(Context, NNS1->getAsRecordDecl(),
+                                    NNS2->getAsRecordDecl());
+  }
+  return false;
+}
+
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+                                     const TemplateName &N1,
+                                     const TemplateName &N2) {
+  if (N1.getKind() != N2.getKind())
+    return false;
+  switch (N1.getKind()) {
+  case TemplateName::Template:
+    return IsStructurallyEquivalent(Context, N1.getAsTemplateDecl(),
+                                    N2.getAsTemplateDecl());
+
+  case TemplateName::OverloadedTemplate: {
+    OverloadedTemplateStorage *OS1 = N1.getAsOverloadedTemplate(),
+        *OS2 = N2.getAsOverloadedTemplate();
+    OverloadedTemplateStorage::iterator I1 = OS1->begin(), I2 = OS2->begin(),
+        E1 = OS1->end(), E2 = OS2->end();
+    for (; I1 != E1 && I2 != E2; ++I1, ++I2)
+      if (!IsStructurallyEquivalent(Context, *I1, *I2))
+        return false;
+    return I1 == E1 && I2 == E2;
+  }
+
+  case TemplateName::QualifiedTemplate: {
+    QualifiedTemplateName *QN1 = N1.getAsQualifiedTemplateName(),
+        *QN2 = N2.getAsQualifiedTemplateName();
+    return IsStructurallyEquivalent(Context, QN1->getDecl(), QN2->getDecl()) &&
+        IsStructurallyEquivalent(Context, QN1->getQualifier(),
+                                 QN2->getQualifier());
+  }
+
+  case TemplateName::DependentTemplate: {
+      DependentTemplateName *DN1 = N1.getAsDependentTemplateName(),
+          *DN2 = N2.getAsDependentTemplateName();
+      if (!IsStructurallyEquivalent(Context, DN1->getQualifier(),
+                                    DN2->getQualifier()))
+        return false;
+      if (DN1->isIdentifier() && DN2->isIdentifier())
+        return IsStructurallyEquivalent(DN1->getIdentifier(),
+                                        DN2->getIdentifier());
+      else if (DN1->isOverloadedOperator() && DN2->isOverloadedOperator())
+        return DN1->getOperator() == DN2->getOperator();
+      return false;
+  }
+
+  case TemplateName::SubstTemplateTemplateParm: {
+    SubstTemplateTemplateParmStorage *TS1 = N1.getAsSubstTemplateTemplateParm(),
+        *TS2 = N2.getAsSubstTemplateTemplateParm();
+    return IsStructurallyEquivalent(Context, TS1->getParameter(),
+                                    TS2->getParameter()) &&
+        IsStructurallyEquivalent(Context, TS1->getReplacement(),
+                                 TS2->getReplacement());
+    }
+  case TemplateName::SubstTemplateTemplateParmPack: {
+    SubstTemplateTemplateParmPackStorage
+        *P1 = N1.getAsSubstTemplateTemplateParmPack(),
+        *P2 = N2.getAsSubstTemplateTemplateParmPack();
+    return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
+                                    P2->getArgumentPack()) &&
+        IsStructurallyEquivalent(Context, P1->getParameterPack(),
+                                 P2->getParameterPack());
+  }
+  }
+  return false;
 }
 
 /// \brief Determine whether two template arguments are equivalent.
@@ -1965,6 +2065,23 @@
         T->getDepth(), T->getIndex(), T->isParameterPack(), ParmDecl);
 }
 
+QualType ASTNodeImporter::VisitSubstTemplateTypeParmType(
+    const SubstTemplateTypeParmType *T) {
+  const TemplateTypeParmType *Replaced =
+      cast_or_null<TemplateTypeParmType>(Importer.Import(
+        QualType(T->getReplacedParameter(), 0)).getTypePtr());
+  if (!Replaced)
+    return QualType();
+
+  QualType Replacement = Importer.Import(T->getReplacementType());
+  if (Replacement.isNull())
+    return QualType();
+  Replacement = Replacement.getCanonicalType();
+
+  return Importer.getToContext().getSubstTemplateTypeParmType(
+        Replaced, Replacement);
+}
+
 QualType ASTNodeImporter::VisitTemplateSpecializationType(
                                        const TemplateSpecializationType *T) {
   TemplateName ToTemplate = Importer.Import(T->getTemplateName());
@@ -3660,6 +3777,9 @@
   if (ImportDefinition(D, ToVar))
     return nullptr;
 
+  if (D->isConstexpr())
+    ToVar->setConstexpr(true);
+
   return ToVar;
 }
 
@@ -4743,12 +4863,46 @@
     }
   } else {
     // Create a new specialization.
-    D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), 
-                                                 D->getTagKind(), DC, 
-                                                 StartLoc, IdLoc,
-                                                 ClassTemplate,
-                                                 TemplateArgs,
-                                                 /*PrevDecl=*/nullptr);
+    if (ClassTemplatePartialSpecializationDecl *PartialSpec =
+        dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
+
+      // Import TemplateArgumentListInfo
+      TemplateArgumentListInfo ToTAInfo;
+      auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
+      for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) {
+        bool Error = false;
+        auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I], Error);
+        if (Error)
+          return nullptr;
+        ToTAInfo.addArgument(ToLoc);
+      }
+
+      QualType CanonInjType = Importer.Import(
+            PartialSpec->getInjectedSpecializationType());
+      if (CanonInjType.isNull())
+        return nullptr;
+      CanonInjType = CanonInjType.getCanonicalType();
+
+      TemplateParameterList *ToTPList = ImportTemplateParameterList(
+            PartialSpec->getTemplateParameters());
+      if (!ToTPList && PartialSpec->getTemplateParameters())
+        return nullptr;
+
+      D2 = ClassTemplatePartialSpecializationDecl::Create(
+            Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc,
+            ToTPList, ClassTemplate,
+            llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()),
+            ToTAInfo, CanonInjType, nullptr);
+
+    } else {
+      D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(),
+                                                   D->getTagKind(), DC,
+                                                   StartLoc, IdLoc,
+                                                   ClassTemplate,
+                                                   TemplateArgs,
+                                                   /*PrevDecl=*/nullptr);
+    }
+
     D2->setSpecializationKind(D->getSpecializationKind());
 
     // Add this specialization to the class template.
@@ -4756,13 +4910,31 @@
     
     // Import the qualifier, if any.
     D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
-    
+
+    Importer.Imported(D, D2);
+
+    if (auto *TSI = D->getTypeAsWritten()) {
+      TypeSourceInfo *TInfo = Importer.Import(TSI);
+      if (!TInfo)
+        return nullptr;
+      D2->setTypeAsWritten(TInfo);
+      D2->setTemplateKeywordLoc(Importer.Import(D->getTemplateKeywordLoc()));
+      D2->setExternLoc(Importer.Import(D->getExternLoc()));
+    }
+
+    SourceLocation POI = Importer.Import(D->getPointOfInstantiation());
+    if (POI.isValid())
+      D2->setPointOfInstantiation(POI);
+    else if (D->getPointOfInstantiation().isValid())
+      return nullptr;
+
+    D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind());
+
     // Add the specialization to this context.
     D2->setLexicalDeclContext(LexicalDC);
     LexicalDC->addDeclInternal(D2);
   }
   Importer.Imported(D, D2);
-  
   if (D->isCompleteDefinition() && ImportDefinition(D, D2))
     return nullptr;
 
@@ -6599,6 +6771,27 @@
   }
 }
 
+
+Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
+    SubstNonTypeTemplateParmExpr *E) {
+  QualType T = Importer.Import(E->getType());
+  if (T.isNull())
+    return nullptr;
+
+  NonTypeTemplateParmDecl *Param = cast_or_null<NonTypeTemplateParmDecl>(
+        Importer.Import(E->getParameter()));
+  if (!Param)
+    return nullptr;
+
+  Expr *Replacement = Importer.Import(E->getReplacement());
+  if (!Replacement)
+    return nullptr;
+
+  return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr(
+        T, E->getValueKind(), Importer.Import(E->getExprLoc()), Param,
+        Replacement);
+}
+
 ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
                          ASTContext &FromContext, FileManager &FromFileManager,
                          bool MinimalImport)
@@ -6805,14 +6998,14 @@
 
   case NestedNameSpecifier::Namespace:
     if (NamespaceDecl *NS = 
-          cast<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
+          cast_or_null<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) {
       return NestedNameSpecifier::Create(ToContext, prefix, NS);
     }
     return nullptr;
 
   case NestedNameSpecifier::NamespaceAlias:
     if (NamespaceAliasDecl *NSAD = 
-          cast<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) {
+          cast_or_null<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) {
       return NestedNameSpecifier::Create(ToContext, prefix, NSAD);
     }
     return nullptr;
@@ -6822,7 +7015,7 @@
 
   case NestedNameSpecifier::Super:
     if (CXXRecordDecl *RD =
-            cast<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
+            cast_or_null<CXXRecordDecl>(Import(FromNNS->getAsRecordDecl()))) {
       return NestedNameSpecifier::SuperSpecifier(ToContext, RD);
     }
     return nullptr;
@@ -6844,8 +7037,74 @@
 }
 
 NestedNameSpecifierLoc ASTImporter::Import(NestedNameSpecifierLoc FromNNS) {
-  // FIXME: Implement!
-  return NestedNameSpecifierLoc();
+  // Copied from NestedNameSpecifier mostly.
+  SmallVector<NestedNameSpecifierLoc , 8> NestedNames;
+  NestedNameSpecifierLoc NNS = FromNNS;
+
+  // Push each of the nested-name-specifiers's onto a stack for
+  // serialization in reverse order.
+  while (NNS) {
+    NestedNames.push_back(NNS);
+    NNS = NNS.getPrefix();
+  }
+
+  NestedNameSpecifierLocBuilder Builder;
+
+  while (!NestedNames.empty()) {
+    NNS = NestedNames.pop_back_val();
+    NestedNameSpecifier *Spec = Import(NNS.getNestedNameSpecifier());
+    if (!Spec)
+      return NestedNameSpecifierLoc();
+
+    NestedNameSpecifier::SpecifierKind Kind = Spec->getKind();
+    switch (Kind) {
+    case NestedNameSpecifier::Identifier:
+      Builder.Extend(getToContext(),
+                     Spec->getAsIdentifier(),
+                     Import(NNS.getLocalBeginLoc()),
+                     Import(NNS.getLocalEndLoc()));
+      break;
+
+    case NestedNameSpecifier::Namespace:
+      Builder.Extend(getToContext(),
+                     Spec->getAsNamespace(),
+                     Import(NNS.getLocalBeginLoc()),
+                     Import(NNS.getLocalEndLoc()));
+      break;
+
+    case NestedNameSpecifier::NamespaceAlias:
+      Builder.Extend(getToContext(),
+                     Spec->getAsNamespaceAlias(),
+                     Import(NNS.getLocalBeginLoc()),
+                     Import(NNS.getLocalEndLoc()));
+      break;
+
+    case NestedNameSpecifier::TypeSpec:
+    case NestedNameSpecifier::TypeSpecWithTemplate: {
+      TypeSourceInfo *TSI = getToContext().getTrivialTypeSourceInfo(
+            QualType(Spec->getAsType(), 0));
+      Builder.Extend(getToContext(),
+                     Import(NNS.getLocalBeginLoc()),
+                     TSI->getTypeLoc(),
+                     Import(NNS.getLocalEndLoc()));
+      break;
+    }
+
+    case NestedNameSpecifier::Global:
+      Builder.MakeGlobal(getToContext(), Import(NNS.getLocalBeginLoc()));
+      break;
+
+    case NestedNameSpecifier::Super: {
+      SourceRange ToRange = Import(NNS.getSourceRange());
+      Builder.MakeSuper(getToContext(),
+                        Spec->getAsRecordDecl(),
+                        ToRange.getBegin(),
+                        ToRange.getEnd());
+    }
+  }
+  }
+
+  return Builder.getWithLocInContext(getToContext());
 }
 
 TemplateName ASTImporter::Import(TemplateName From) {
Index: include/clang/AST/TemplateBase.h
===================================================================
--- include/clang/AST/TemplateBase.h
+++ include/clang/AST/TemplateBase.h
@@ -574,6 +574,7 @@
                                     TemplateArgumentLoc> {
 private:
   friend TrailingObjects;
+  friend class ASTNodeImporter;
 
   ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to