]> granicus.if.org Git - clang/commitdiff
[ExternalASTMerger] Import Objective-C classes
authorSean Callanan <scallanan@apple.com>
Tue, 25 Jul 2017 19:54:22 +0000 (19:54 +0000)
committerSean Callanan <scallanan@apple.com>
Tue, 25 Jul 2017 19:54:22 +0000 (19:54 +0000)
This patch adds functionality and a test for importing Objective-C classes
and their methods.

It also adds a flag to clang-import-test to set the language used for
parsing. This takes the same argument format as the -x option to the
driver.

Differential Revision: https://reviews.llvm.org/D35274

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@309014 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExternalASTMerger.cpp
test/Import/objc-method/Inputs/S.m [new file with mode: 0644]
test/Import/objc-method/test.m [new file with mode: 0644]
tools/clang-import-test/clang-import-test.cpp

index 4f4a99794c5b074f0270c5568808d4748c3445fd..f69b5d6284065395f7af5f19a15bb329e36f2c5b 100644 (file)
@@ -44,6 +44,9 @@ public:
       ToTag->setMustBuildLookupTable();
     } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
       ToNamespace->setHasExternalVisibleStorage();
+    } else if (auto ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
+      ToContainer->setHasExternalLexicalStorage();
+      ToContainer->setMustBuildLookupTable();
     }
     return ASTImporter::Imported(From, To);
   }
@@ -80,11 +83,12 @@ LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
 }
 
 bool IsForwardDeclaration(Decl *D) {
-  assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case
   if (auto TD = dyn_cast<TagDecl>(D)) {
     return !TD->isThisDeclarationADefinition();
   } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
     return !FD->isThisDeclarationADefinition();
+  } else if (auto OID = dyn_cast<ObjCInterfaceDecl>(D)) {
+     return OID->isThisDeclarationADefinition();
   } else {
     return false;
   }
diff --git a/test/Import/objc-method/Inputs/S.m b/test/Import/objc-method/Inputs/S.m
new file mode 100644 (file)
index 0000000..cf8ffaa
--- /dev/null
@@ -0,0 +1,4 @@
+@interface C {
+}
+-(int)m;
+@end
diff --git a/test/Import/objc-method/test.m b/test/Import/objc-method/test.m
new file mode 100644 (file)
index 0000000..7707110
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: clang-import-test -x objective-c++ -import %S/Inputs/S.m -expression %s
+void expr() {
+  C *c;
+  int i = [c m];
+}
index 6b724e9cf5faea2f8b9473a2ae1109999a35cad0..286cb05219c75e1b0fb453fe01733e367ba2c978 100644 (file)
@@ -17,6 +17,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TargetOptions.h"
 #include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Driver/Types.h"
 #include "clang/Frontend/ASTConsumers.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/MultiplexConsumer.h"
@@ -53,6 +54,11 @@ static llvm::cl::list<std::string>
               llvm::cl::desc("Argument to pass to the CompilerInvocation"),
               llvm::cl::CommaSeparated);
 
+static llvm::cl::opt<std::string>
+    Input("x", llvm::cl::Optional,
+          llvm::cl::desc("The language to parse (default: c++)"),
+          llvm::cl::init("c++"));
+
 static llvm::cl::opt<bool>
 DumpAST("dump-ast", llvm::cl::init(false),
         llvm::cl::desc("Dump combined AST"));
@@ -110,6 +116,7 @@ private:
     llvm::errs() << LineString << '\n';
     llvm::errs().indent(LocColumn);
     llvm::errs() << '^';
+    llvm::errs() << '\n';
   }
 
   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
@@ -143,7 +150,7 @@ private:
 };
 
 std::unique_ptr<CompilerInstance>
-BuildCompilerInstance(ArrayRef<const char *> ClangArgv) {
+BuildCompilerInstance() {
   auto Ins = llvm::make_unique<CompilerInstance>();
   auto DC = llvm::make_unique<TestDiagnosticConsumer>();
   const bool ShouldOwnClient = true;
@@ -151,13 +158,27 @@ BuildCompilerInstance(ArrayRef<const char *> ClangArgv) {
 
   auto Inv = llvm::make_unique<CompilerInvocation>();
 
+  std::vector<const char *> ClangArgv(ClangArgs.size());
+  std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
+                 [](const std::string &s) -> const char * { return s.data(); });
   CompilerInvocation::CreateFromArgs(*Inv, ClangArgv.data(),
                                      &ClangArgv.data()[ClangArgv.size()],
                                      Ins->getDiagnostics());
 
-  Inv->getLangOpts()->CPlusPlus = true;
-  Inv->getLangOpts()->CPlusPlus11 = true;
-  Inv->getHeaderSearchOpts().UseLibcxx = true;
+  {
+    using namespace driver::types;
+    ID Id = lookupTypeForTypeSpecifier(Input.c_str());
+    assert(Id != TY_INVALID);
+    if (isCXX(Id)) {
+      Inv->getLangOpts()->CPlusPlus = true;
+      Inv->getLangOpts()->CPlusPlus11 = true;
+      Inv->getHeaderSearchOpts().UseLibcxx = true;
+    }
+    if (isObjC(Id)) {
+      Inv->getLangOpts()->ObjC1 = 1;
+      Inv->getLangOpts()->ObjC2 = 1;
+    }
+  }
   Inv->getLangOpts()->Bool = true;
   Inv->getLangOpts()->WChar = true;
   Inv->getLangOpts()->Blocks = true;
@@ -216,11 +237,8 @@ void AddExternalSource(
 }
 
 std::unique_ptr<CompilerInstance> BuildIndirect(std::unique_ptr<CompilerInstance> &CI) {
-  std::vector<const char *> ClangArgv(ClangArgs.size());
-  std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
-                 [](const std::string &s) -> const char * { return s.data(); });
   std::unique_ptr<CompilerInstance> IndirectCI =
-      init_convenience::BuildCompilerInstance(ClangArgv);
+      init_convenience::BuildCompilerInstance();
   auto ST = llvm::make_unique<SelectorTable>();
   auto BC = llvm::make_unique<Builtin::Context>();
   std::unique_ptr<ASTContext> AST =
@@ -247,11 +265,8 @@ llvm::Expected<std::unique_ptr<CompilerInstance>>
 Parse(const std::string &Path,
       llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports,
       bool ShouldDumpAST) {
-  std::vector<const char *> ClangArgv(ClangArgs.size());
-  std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
-                 [](const std::string &s) -> const char * { return s.data(); });
   std::unique_ptr<CompilerInstance> CI =
-      init_convenience::BuildCompilerInstance(ClangArgv);
+      init_convenience::BuildCompilerInstance();
   auto ST = llvm::make_unique<SelectorTable>();
   auto BC = llvm::make_unique<Builtin::Context>();
   std::unique_ptr<ASTContext> AST =