khazem created this revision.
khazem added reviewers: spyffe, a.sidorin.
khazem added subscribers: cfe-commits, phosek, seanklein, klimek.

Some of this patch comes from Aleksei's branch [1], with minor revisions. I've 
added unit tests and AST Matcher support. Copying in Manuel in case there is no 
need for a dedicated usingShadowDecl() matcher, in which case I could define it 
only in the test suite.

[1] 
https://github.com/haoNoQ/clang/blob/summary-ipa-draft/lib/AST/ASTImporter.cpp#L3594


https://reviews.llvm.org/D27181

Files:
  include/clang/AST/ASTImporter.h
  include/clang/ASTMatchers/ASTMatchers.h
  lib/AST/ASTImporter.cpp
  lib/ASTMatchers/Dynamic/Registry.cpp
  unittests/AST/ASTImporterTest.cpp

Index: unittests/AST/ASTImporterTest.cpp
===================================================================
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -558,5 +558,35 @@
 }
 
 
+TEST(ImportDecl, ImportUsingDecl) {
+  MatchVerifier<Decl> 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<Decl> 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
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: 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<UsingShadowDecl>(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<UsingDecl>(Importer.Import(D->getUsingDecl())),
+        cast_or_null<NamedDecl>(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<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD);
+  return Pos != ImportedDecls.end() ? Pos->second : NULL;
+}
+
 Decl *ASTImporter::Import(Decl *FromD) {
   if (!FromD)
     return nullptr;
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<Decl, UsingDecl> 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<Decl,
+                                            UsingShadowDecl> usingShadowDecl;
+
 /// \brief Matches using namespace declarations.
 ///
 /// Given
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.
     ///
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to