From: Sean Callanan Date: Tue, 25 Jul 2017 19:54:22 +0000 (+0000) Subject: [ExternalASTMerger] Import Objective-C classes X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0f53b50dc88bbfb4e5dd2267763a8dc430e0be63;p=clang [ExternalASTMerger] Import Objective-C classes 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 --- diff --git a/lib/AST/ExternalASTMerger.cpp b/lib/AST/ExternalASTMerger.cpp index 4f4a99794c..f69b5d6284 100644 --- a/lib/AST/ExternalASTMerger.cpp +++ b/lib/AST/ExternalASTMerger.cpp @@ -44,6 +44,9 @@ public: ToTag->setMustBuildLookupTable(); } else if (auto ToNamespace = dyn_cast(To)) { ToNamespace->setHasExternalVisibleStorage(); + } else if (auto ToContainer = dyn_cast(To)) { + ToContainer->setHasExternalLexicalStorage(); + ToContainer->setMustBuildLookupTable(); } return ASTImporter::Imported(From, To); } @@ -80,11 +83,12 @@ LookupSameContext(Source SourceTU, const DeclContext *DC, } bool IsForwardDeclaration(Decl *D) { - assert(!isa(D)); // TODO handle this case if (auto TD = dyn_cast(D)) { return !TD->isThisDeclarationADefinition(); } else if (auto FD = dyn_cast(D)) { return !FD->isThisDeclarationADefinition(); + } else if (auto OID = dyn_cast(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 index 0000000000..cf8ffaa602 --- /dev/null +++ b/test/Import/objc-method/Inputs/S.m @@ -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 index 0000000000..7707110d82 --- /dev/null +++ b/test/Import/objc-method/test.m @@ -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]; +} diff --git a/tools/clang-import-test/clang-import-test.cpp b/tools/clang-import-test/clang-import-test.cpp index 6b724e9cf5..286cb05219 100644 --- a/tools/clang-import-test/clang-import-test.cpp +++ b/tools/clang-import-test/clang-import-test.cpp @@ -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 llvm::cl::desc("Argument to pass to the CompilerInvocation"), llvm::cl::CommaSeparated); +static llvm::cl::opt + Input("x", llvm::cl::Optional, + llvm::cl::desc("The language to parse (default: c++)"), + llvm::cl::init("c++")); + static llvm::cl::opt 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 -BuildCompilerInstance(ArrayRef ClangArgv) { +BuildCompilerInstance() { auto Ins = llvm::make_unique(); auto DC = llvm::make_unique(); const bool ShouldOwnClient = true; @@ -151,13 +158,27 @@ BuildCompilerInstance(ArrayRef ClangArgv) { auto Inv = llvm::make_unique(); + std::vector 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 BuildIndirect(std::unique_ptr &CI) { - std::vector ClangArgv(ClangArgs.size()); - std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(), - [](const std::string &s) -> const char * { return s.data(); }); std::unique_ptr IndirectCI = - init_convenience::BuildCompilerInstance(ClangArgv); + init_convenience::BuildCompilerInstance(); auto ST = llvm::make_unique(); auto BC = llvm::make_unique(); std::unique_ptr AST = @@ -247,11 +265,8 @@ llvm::Expected> Parse(const std::string &Path, llvm::ArrayRef> Imports, bool ShouldDumpAST) { - std::vector ClangArgv(ClangArgs.size()); - std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(), - [](const std::string &s) -> const char * { return s.data(); }); std::unique_ptr CI = - init_convenience::BuildCompilerInstance(ClangArgv); + init_convenience::BuildCompilerInstance(); auto ST = llvm::make_unique(); auto BC = llvm::make_unique(); std::unique_ptr AST =