Index: include/clang/AST/ASTImporter.h =================================================================== --- include/clang/AST/ASTImporter.h +++ include/clang/AST/ASTImporter.h @@ -123,6 +123,13 @@ /// context, or NULL if an error occurred. TypeSourceInfo *Import(TypeSourceInfo *FromTSI); + /// \brief Get an imported declaration in "to" context + /// if it is already been imported + /// + /// \ returns an imported declaration if it is already imported, + /// or a NULL type if is not imported yet. + Decl *GetImported(Decl *FromD); + /// \brief Import the given declaration from the "from" context into the /// "to" context. /// Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -1193,6 +1193,19 @@ /// matches \code using X::x \endcode const internal::VariadicDynCastAllOfMatcher usingDecl; +/// \brief Matches shadow declarations introduced into a scope by a +/// (resolved) using declaration. +/// +/// Given +/// \code +/// namespace n { int f; } +/// namespace declToImport { using n::f; } +/// \endcode +/// usingShadowDecl() +/// matches \code f \endcode +const internal::VariadicDynCastAllOfMatcher usingShadowDecl; + /// \brief Matches using namespace declarations. /// /// Given Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -175,6 +175,8 @@ Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D); Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D); + Decl *VisitUsingDecl(UsingDecl *D); + Decl *VisitUsingShadowDecl(UsingShadowDecl *D); ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); @@ -4288,6 +4290,68 @@ return ToLinkageSpec; } +Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *AlreadyImported; + if (ImportDeclParts(D, DC, LexicalDC, Name, AlreadyImported, Loc)) + return NULL; + assert(DC && "Null DeclContext after importing decl parts"); + if (AlreadyImported) + return AlreadyImported; + + DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); + ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + + // If a UsingShadowDecl has a pointer to its UsingDecl, then we may + // already have imported this UsingDecl. That should have been caught + // above when checking if ToD is non-null. + assert(!Importer.GetImported(D) && + "Decl imported but not assigned to AlreadyImported"); + + UsingDecl *ToD = UsingDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), + NameInfo, D->hasTypename()); + ImportAttributes(D, ToD); + ToD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToD); + Importer.Imported(D, ToD); + + for (UsingShadowDecl *I : D->shadows()) { + UsingShadowDecl *SD = cast(Importer.Import(I)); + ToD->addShadowDecl(SD); + } + return ToD; +} + +Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *AlreadyImported; + if (ImportDeclParts(D, DC, LexicalDC, Name, AlreadyImported, Loc)) + return NULL; + assert(DC && "Null DeclContext after importing decl parts"); + if (AlreadyImported) + return AlreadyImported; + + UsingShadowDecl *ToD = UsingShadowDecl::Create( + Importer.getToContext(), DC, Loc, + cast(Importer.Import(D->getUsingDecl())), + cast_or_null(Importer.Import(D->getTargetDecl()))); + + ImportAttributes(D, ToD); + ToD->setAccess(D->getAccess()); + ToD->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToD); + + LexicalDC->addDeclInternal(ToD); + + return ToD; +} + bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { @@ -7018,6 +7082,11 @@ } } +Decl *ASTImporter::GetImported(Decl *FromD) { + llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD); + return Pos != ImportedDecls.end() ? Pos->second : NULL; +} + Decl *ASTImporter::Import(Decl *FromD) { if (!FromD) return nullptr; Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -420,6 +420,7 @@ REGISTER_MATCHER(unresolvedUsingValueDecl); REGISTER_MATCHER(userDefinedLiteral); REGISTER_MATCHER(usingDecl); + REGISTER_MATCHER(usingShadowDecl); REGISTER_MATCHER(usingDirectiveDecl); REGISTER_MATCHER(valueDecl); REGISTER_MATCHER(varDecl); Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -558,5 +558,35 @@ } +TEST(ImportDecl, ImportUsingDecl) { + MatchVerifier Verifier; + EXPECT_TRUE( + testImport( + "namespace foo { int bar; }" + "int declToImport(){ using foo::bar; }", + Lang_CXX, "", Lang_CXX, Verifier, + functionDecl( + has( + compoundStmt( + has( + declStmt( + has( + usingDecl())))))))); +} + + +TEST(ImportDecl, ImportUsingShadowDecl) { + MatchVerifier Verifier; + EXPECT_TRUE( + testImport( + "namespace foo { int bar; }" + "namespace declToImport { using foo::bar; }", + Lang_CXX, "", Lang_CXX, Verifier, + namespaceDecl( + has( + usingShadowDecl())))); +} + + } // end namespace ast_matchers } // end namespace clang