Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -76,7 +76,7 @@ QualType VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); QualType VisitTemplateSpecializationType(const TemplateSpecializationType *T); QualType VisitElaboratedType(const ElaboratedType *T); - // FIXME: DependentNameType + QualType VisitDependentNameType(const DependentNameType *T); // FIXME: DependentTemplateSpecializationType QualType VisitObjCInterfaceType(const ObjCInterfaceType *T); QualType VisitObjCObjectType(const ObjCObjectType *T); @@ -273,8 +273,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); @@ -774,6 +776,25 @@ ToQualifier, ToNamedType); } +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) { ObjCInterfaceDecl *Class = dyn_cast_or_null(Importer.Import(T->getDecl())); @@ -5467,6 +5488,33 @@ 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; + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + for (const auto &FromLoc : E->template_arguments()) { + bool Error = false; + TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); + if (Error) + return nullptr; + ToTAInfo.addArgument(ToTALoc); + } + ResInfo = &ToTAInfo; + } + + return DependentScopeDeclRefExpr::Create( + Importer.getToContext(), Importer.Import(E->getQualifierLoc()), + Importer.Import(E->getTemplateKeywordLoc()), NameInfo, ResInfo); +} + Expr *ASTNodeImporter::VisitCXXUnresolvedConstructExpr( CXXUnresolvedConstructExpr *CE) { @@ -5573,6 +5621,53 @@ Importer.Import(E->getTildeLoc()), Storage); } +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(Importer.Import(D))) + ToDecls.addDecl(To); + else + return nullptr; + } + + TemplateArgumentListInfo ToTAInfo; + TemplateArgumentListInfo *ResInfo = nullptr; + if (E->hasExplicitTemplateArgs()) { + for (const auto &FromLoc : E->template_arguments()) { + bool Error = false; + TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); + if (Error) + return nullptr; + ToTAInfo.addArgument(ToTALoc); + } + 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()) Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -551,5 +551,68 @@ } +const internal::VariadicDynCastAllOfMatcher + unresolvedMemberExpr; +TEST(ImportExpr, ImportUnresolvedMemberExpr) { + MatchVerifier Verifier; + EXPECT_TRUE(testImport("struct S { template void mem(); };" + "template void declToImport() {" + "S s;" + "s.mem();" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(has(functionDecl(has(compoundStmt( + has(callExpr(has(unresolvedMemberExpr())))))))))); +} + +const internal::VariadicDynCastAllOfMatcher + dependentScopeDeclRefExpr; +TEST(ImportExpr, ImportDependentScopeDeclRefExpr) { + MatchVerifier Verifier; + EXPECT_TRUE(testImport("template struct S;" + "template void declToImport() {" + "S::foo;" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(has(functionDecl(has(compoundStmt( + has(dependentScopeDeclRefExpr())))))))); + + EXPECT_TRUE(testImport("template struct S;" + "template void declToImport() {" + "S::template foo;" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(has(functionDecl(has(compoundStmt( + has(dependentScopeDeclRefExpr())))))))); + + EXPECT_TRUE(testImport("template struct S;" + "template void declToImport() {" + "S::template foo<>;" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(has(functionDecl(has(compoundStmt( + has(dependentScopeDeclRefExpr())))))))); + + EXPECT_TRUE(testImport("template struct S;" + "template void declToImport() {" + "S::template foo;" + "}", + Lang_CXX, "", Lang_CXX, Verifier, + functionTemplateDecl(has(functionDecl(has(compoundStmt( + has(dependentScopeDeclRefExpr())))))))); +} + +const internal::VariadicDynCastAllOfMatcher + dependentNameType; +TEST(ImportExpr, DependentNameType) { + MatchVerifier Verifier; + EXPECT_TRUE(testImport("template 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