szepet updated this revision to Diff 143925.
szepet added a comment.

Rewritten the tests using the newly added TEST_P method.
This patch failed earlier when -fdelayed-template-parsing flag was enabled, 
however, the actual import process was OK but the original AST havent included 
the checked nodes.
TEST_P made possible to check whether the original code contains the node we 
would like to import (and we test only in this case, since otherwise it does 
not make sense).


https://reviews.llvm.org/D38845

Files:
  lib/AST/ASTImporter.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===================================================================
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -1503,5 +1503,91 @@
     ParameterizedTests, ImportFunctions,
     ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
 
+const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
+    unresolvedMemberExpr;
+
+struct NoDelayedTemplateParsing : ASTImporterTestBase {};
+TEST_P(NoDelayedTemplateParsing, UnresolvedMemberExpr) {
+  auto Code = "struct S { template <typename T> void mem(); };"
+              "template <typename U> void declToImport() {"
+              "  S s;"
+              "  s.mem<U>();"
+              "}";
+  Decl *FromTU = getTuDecl(Code, Lang_CXX);
+  auto Pattern = functionTemplateDecl(has(functionDecl(
+      has(compoundStmt(has(callExpr(has(unresolvedMemberExpr()))))))));
+  auto *FromUME =
+      FirstDeclMatcher<FunctionTemplateDecl>().match(FromTU, Pattern);
+  if (!FromUME)
+    return;
+
+  auto To = cast<FunctionTemplateDecl>(Import(FromUME, Lang_CXX));
+  EXPECT_TRUE(FirstDeclMatcher<FunctionTemplateDecl>().match(To, Pattern));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
+    dependentScopeDeclRefExpr;
+TEST_P(NoDelayedTemplateParsing, ImportDependentScopeDeclRefExpr) {
+  llvm::SmallVector<StringRef, 4> Codes;
+  Codes.push_back("template <typename T> struct S;"
+                  "template <typename T> void declToImport() {"
+                  "  S<T>::foo;"
+                  "}");
+
+  Codes.push_back("template <typename T> struct S;"
+                  "template <typename T> void declToImport() {"
+                  "  S<T>::template foo;"
+                  "}");
+
+  Codes.push_back("template <typename T> struct S;"
+                  "template <typename T> void declToImport() {"
+                  "  S<T>::template foo<>;"
+                  "}");
+
+  Codes.push_back("template <typename T> struct S;"
+                  "template <typename T> void declToImport() {"
+                  "  S<T>::template foo<T>;"
+                  "}");
+
+  auto Pattern = functionTemplateDecl(
+      has(functionDecl(has(compoundStmt(has(dependentScopeDeclRefExpr()))))));
+  llvm::SmallVector<Decl *, 4> FromTUs;
+  // Converting code texts into TUs
+  std::transform(Codes.begin(), Codes.end(), std::back_inserter(FromTUs),
+                 [this](StringRef Code) {
+                   static int cnt = 0;
+                   ++cnt;
+                   return getTuDecl(Code, Lang_CXX,
+                                    std::to_string(cnt) + std::string(".cc"));
+                 });
+
+  for (llvm::SmallVector<Decl *, 4>::const_iterator TB = FromTUs.begin(),
+                                                    TE = FromTUs.end();
+       TB != TE; ++TB) {
+    auto *FromDSDRE =
+        FirstDeclMatcher<FunctionTemplateDecl>().match(*TB, Pattern);
+    if (!FromDSDRE)
+      return;
+
+    auto To = cast<FunctionTemplateDecl>(Import(FromDSDRE, Lang_CXX));
+    EXPECT_TRUE(FirstDeclMatcher<FunctionTemplateDecl>().match(To, Pattern));
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, NoDelayedTemplateParsing,
+                        ::testing::Values(ArgVector()), );
+
+const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
+    dependentNameType;
+TEST(ImportExpr, DependentNameType) {
+  MatchVerifier<Decl> Verifier;
+  testImport("template <typename T> struct declToImport {"
+             "  typedef typename T::type dependent_name;"
+             "};",
+             Lang_CXX11, "", Lang_CXX11, Verifier,
+             classTemplateDecl(has(
+                 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
+}
+
 } // end namespace ast_matchers
 } // end namespace clang
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -121,7 +121,7 @@
     QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T);
     QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T);
     QualType VisitElaboratedType(const ElaboratedType *T);
-    // FIXME: DependentNameType
+    QualType VisitDependentNameType(const DependentNameType *T);
     QualType VisitPackExpansionType(const PackExpansionType *T);
     QualType VisitDependentTemplateSpecializationType(
         const DependentTemplateSpecializationType *T);
@@ -347,8 +347,10 @@
     Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
     Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
     Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+    Expr *VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
     Expr *VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *CE);
     Expr *VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
+    Expr *VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
     Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
     Expr *VisitCXXThisExpr(CXXThisExpr *E);
     Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
@@ -938,6 +940,25 @@
         T->getKeyword(), Qualifier, Name, ToPack);
 }
 
+QualType ASTNodeImporter::VisitDependentNameType(const DependentNameType *T) {
+  NestedNameSpecifier *NNS = Importer.Import(T->getQualifier());
+  if (!NNS && T->getQualifier())
+    return QualType();
+
+  IdentifierInfo *Name = Importer.Import(T->getIdentifier());
+  if (!Name && T->getIdentifier())
+    return QualType();
+
+  QualType Canon = (T == T->getCanonicalTypeInternal().getTypePtr())
+                       ? QualType()
+                       : Importer.Import(T->getCanonicalTypeInternal());
+  if (!Canon.isNull())
+    Canon = Canon.getCanonicalType();
+
+  return Importer.getToContext().getDependentNameType(T->getKeyword(), NNS,
+                                                      Name, Canon);
+}
+
 QualType ASTNodeImporter::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
   auto *Class =
       dyn_cast_or_null<ObjCInterfaceDecl>(Importer.Import(T->getDecl()));
@@ -6159,6 +6180,29 @@
       cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo);
 }
 
+Expr *
+ASTNodeImporter::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
+  DeclarationName Name = Importer.Import(E->getDeclName());
+  if (!E->getDeclName().isEmpty() && Name.isEmpty())
+    return nullptr;
+
+  DeclarationNameInfo NameInfo(Name, Importer.Import(E->getExprLoc()));
+  ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+
+  TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()),
+                                    Importer.Import(E->getRAngleLoc()));
+  TemplateArgumentListInfo *ResInfo = nullptr;
+  if (E->hasExplicitTemplateArgs()) {
+    if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+      return nullptr;
+    ResInfo = &ToTAInfo;
+  }
+
+  return DependentScopeDeclRefExpr::Create(
+      Importer.getToContext(), Importer.Import(E->getQualifierLoc()),
+      Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo);
+}
+
 Expr *ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
     CXXUnresolvedConstructExpr *CE) {
   unsigned NumArgs = CE->arg_size();
@@ -6216,6 +6260,47 @@
       E->isOverloaded(), ToDecls.begin(), ToDecls.end());
 }
 
+Expr *ASTNodeImporter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+  DeclarationName Name = Importer.Import(E->getName());
+  if (!E->getName().isEmpty() && Name.isEmpty())
+    return nullptr;
+  DeclarationNameInfo NameInfo(Name, Importer.Import(E->getNameLoc()));
+  // Import additional name location/type info.
+  ImportDeclarationNameLoc(E->getNameInfo(), NameInfo);
+
+  QualType BaseType = Importer.Import(E->getType());
+  if (!E->getType().isNull() && BaseType.isNull())
+    return nullptr;
+
+  UnresolvedSet<8> ToDecls;
+  for (Decl *D : E->decls()) {
+    if (NamedDecl *To = cast_or_null<NamedDecl>(Importer.Import(D)))
+      ToDecls.addDecl(To);
+    else
+      return nullptr;
+  }
+
+  TemplateArgumentListInfo ToTAInfo;
+  TemplateArgumentListInfo *ResInfo = nullptr;
+  if (E->hasExplicitTemplateArgs()) {
+    if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
+      return nullptr;
+    ResInfo = &ToTAInfo;
+  }
+
+  Expr *BaseE = E->isImplicitAccess() ? nullptr : Importer.Import(E->getBase());
+  if (!BaseE && !E->isImplicitAccess() && E->getBase()) {
+    return nullptr;
+  }
+
+  return UnresolvedMemberExpr::Create(
+      Importer.getToContext(), E->hasUnresolvedUsing(), BaseE, BaseType,
+      E->isArrow(), Importer.Import(E->getOperatorLoc()),
+      Importer.Import(E->getQualifierLoc()),
+      Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo,
+      ToDecls.begin(), ToDecls.end());
+}
+
 Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
   QualType T = Importer.Import(E->getType());
   if (T.isNull())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to