diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index 679fce62..cc2b8a14 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -44,8 +44,7 @@ #include #include #include -#include -#include + #include #include #include @@ -3278,9 +3277,8 @@ bool Parser::IsValidDeclaration(const clang::SourceLocation& Loc) //-----------------------------------// -void Parser::WalkAST() +void Parser::WalkAST(clang::TranslationUnitDecl* TU) { - auto TU = c->getASTContext().getTranslationUnitDecl(); for (auto D : TU->decls()) { if (D->getBeginLoc().isValid() && @@ -4049,35 +4047,32 @@ void Parser::HandleDiagnostics(ParserResult* res) } } -ParserResult* Parser::ParseHeader(const std::vector& SourceFiles) +void Parser::SetupLLVMCodegen() { - assert(opts->ASTContext && "Expected a valid ASTContext"); - - auto res = new ParserResult(); - - if (SourceFiles.empty()) - { - res->kind = ParserResultKind::FileNotFound; - return res; - } + // Initialize enough Clang codegen machinery so we can get at ABI details. + LLVMModule.reset(new llvm::Module("", LLVMCtx)); - Setup(); + LLVMModule->setTargetTriple(c->getTarget().getTriple().getTriple()); + LLVMModule->setDataLayout(c->getTarget().getDataLayout()); - std::unique_ptr SC(new clang::SemaConsumer()); - c->setASTConsumer(std::move(SC)); + CGM.reset(new clang::CodeGen::CodeGenModule(c->getASTContext(), + c->getHeaderSearchOpts(), c->getPreprocessorOpts(), + c->getCodeGenOpts(), *LLVMModule, c->getDiagnostics())); - c->createSema(clang::TU_Complete, 0); + CGT.reset(new clang::CodeGen::CodeGenTypes(*CGM.get())); - auto DiagClient = new DiagnosticConsumer(); - c->getDiagnostics().setClient(DiagClient); + codeGenTypes = CGT.get(); +} +bool Parser::SetupSourceFiles(const std::vector& SourceFiles, + std::vector& FileEntries) +{ // Check that the file is reachable. const clang::DirectoryLookup *Dir; llvm::SmallVector< std::pair, 0> Includers; - std::vector FileEntries; for (const auto& SourceFile : SourceFiles) { auto FileEntry = c->getPreprocessor().getHeaderSearchInfo().LookupFile(SourceFile, @@ -4085,71 +4080,97 @@ ParserResult* Parser::ParseHeader(const std::vector& SourceFiles) nullptr, Dir, Includers, nullptr, nullptr, nullptr, nullptr, nullptr); if (!FileEntry) - { - res->kind = ParserResultKind::FileNotFound; - return res; - } + return false; + FileEntries.push_back(FileEntry); } // Create a virtual file that includes the header. This gets rid of some // Clang warnings about parsing an header file as the main file. - std::string str; + std::string source; for (const auto& SourceFile : SourceFiles) { - str += "#include \"" + SourceFile + "\"" + "\n"; + source += "#include \"" + SourceFile + "\"" + "\n"; } - str += "\0"; + source += "\0"; - auto buffer = llvm::MemoryBuffer::getMemBuffer(str); + auto buffer = llvm::MemoryBuffer::getMemBufferCopy(source); auto& SM = c->getSourceManager(); SM.setMainFileID(SM.createFileID(std::move(buffer))); - clang::DiagnosticConsumer* client = c->getDiagnostics().getClient(); - client->BeginSourceFile(c->getLangOpts(), &c->getPreprocessor()); + return true; +} - ParseAST(c->getSema()); +class SemaConsumer : public clang::SemaConsumer { + CppSharp::CppParser::Parser& Parser; + std::vector& FileEntries; +public: + SemaConsumer(CppSharp::CppParser::Parser& parser, + std::vector& entries) + : Parser(parser), FileEntries(entries) {} + virtual void HandleTranslationUnit(clang::ASTContext& Ctx) override; +}; - client->EndSourceFile(); +void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx) +{ + auto FileEntry = FileEntries[0]; + auto FileName = FileEntry->getName(); + auto Unit = Parser.opts->ASTContext->FindOrCreateModule(FileName); - HandleDiagnostics(res); + auto TU = Ctx.getTranslationUnitDecl(); + Parser.HandleDeclaration(TU, Unit); - if(client->getNumErrors() != 0) + if (Unit->originalPtr == nullptr) + Unit->originalPtr = (void*)FileEntry; + + Parser.WalkAST(TU); +} + +ParserResult* Parser::ParseHeader(const std::vector& SourceFiles) +{ + assert(opts->ASTContext && "Expected a valid ASTContext"); + + auto res = new ParserResult(); + + if (SourceFiles.empty()) { - res->kind = ParserResultKind::Error; + res->kind = ParserResultKind::FileNotFound; return res; } - auto& AST = c->getASTContext(); + Setup(); + SetupLLVMCodegen(); - auto FileEntry = FileEntries[0]; - auto FileName = FileEntry->getName(); - auto Unit = opts->ASTContext->FindOrCreateModule(FileName); + std::vector FileEntries; + if (!SetupSourceFiles(SourceFiles, FileEntries)) + { + res->kind = ParserResultKind::FileNotFound; + return res; + } - auto TU = AST.getTranslationUnitDecl(); - HandleDeclaration(TU, Unit); + std::unique_ptr SC(new SemaConsumer(*this, FileEntries)); + c->setASTConsumer(std::move(SC)); - if (Unit->originalPtr == nullptr) - Unit->originalPtr = (void*)FileEntry; + c->createSema(clang::TU_Complete, 0); - // Initialize enough Clang codegen machinery so we can get at ABI details. - llvm::LLVMContext Ctx; - std::unique_ptr M(new llvm::Module("", Ctx)); + auto DiagClient = new DiagnosticConsumer(); + c->getDiagnostics().setClient(DiagClient); - M->setTargetTriple(c->getTarget().getTriple().getTriple()); - M->setDataLayout(c->getTarget().getDataLayout()); + clang::DiagnosticConsumer* client = c->getDiagnostics().getClient(); + client->BeginSourceFile(c->getLangOpts(), &c->getPreprocessor()); - std::unique_ptr CGM( - new clang::CodeGen::CodeGenModule(c->getASTContext(), c->getHeaderSearchOpts(), - c->getPreprocessorOpts(), c->getCodeGenOpts(), *M, c->getDiagnostics())); + ParseAST(c->getSema()); - std::unique_ptr CGT( - new clang::CodeGen::CodeGenTypes(*CGM.get())); + client->EndSourceFile(); - codeGenTypes = CGT.get(); + HandleDiagnostics(res); - WalkAST(); + if(client->getNumErrors() != 0) + { + res->kind = ParserResultKind::Error; + return res; + } res->targetInfo = GetTargetInfo(); diff --git a/src/CppParser/Parser.h b/src/CppParser/Parser.h index 998102c4..2c77c081 100644 --- a/src/CppParser/Parser.h +++ b/src/CppParser/Parser.h @@ -18,6 +18,9 @@ #include #include +#include +#include + #include "CXXABI.h" #include "CppParser.h" @@ -53,11 +56,19 @@ public: ParserResult* ParseHeader(const std::vector& SourceFiles); ParserResult* ParseLibrary(const std::string& File); + void WalkAST(clang::TranslationUnitDecl* TU); + void HandleDeclaration(const clang::Decl* D, Declaration* Decl); + CppParserOptions* opts; + private: + + void SetupLLVMCodegen(); + bool SetupSourceFiles(const std::vector& SourceFiles, + std::vector& FileEntries); + bool IsSupported(const clang::NamedDecl* ND); bool IsSupported(const clang::CXXMethodDecl* MD); // AST traversers - void WalkAST(); Declaration* WalkDeclaration(const clang::Decl* D); Declaration* WalkDeclarationDef(clang::Decl* D); Enumeration* WalkEnum(const clang::EnumDecl* ED); @@ -137,7 +148,6 @@ private: DeclarationContext* GetNamespace(const clang::Decl* D, const clang::DeclContext* Ctx); DeclarationContext* GetNamespace(const clang::Decl* D); - void HandleDeclaration(const clang::Decl* D, Declaration* Decl); void HandleOriginalText(const clang::Decl* D, Declaration* Decl); void HandleComments(const clang::Decl* D, Declaration* Decl); void HandleDiagnostics(ParserResult* res); @@ -154,9 +164,12 @@ private: ParserTargetInfo* GetTargetInfo(); int index; - CppParserOptions* opts; std::unique_ptr c; clang::TargetCXXABI::Kind targetABI; + llvm::LLVMContext LLVMCtx; + std::unique_ptr LLVMModule; + std::unique_ptr CGM; + std::unique_ptr CGT; clang::CodeGen::CodeGenTypes* codeGenTypes; std::unordered_map walkedTypeTemplateParameters; std::unordered_map walkedTemplateTemplateParameters; diff --git a/tests/Common/Common.h b/tests/Common/Common.h index 3e8cd3ee..8e32acd0 100644 --- a/tests/Common/Common.h +++ b/tests/Common/Common.h @@ -1433,3 +1433,27 @@ enum ItemsDifferByCase Case_a, Case_A }; + +template struct MyListBase +{ +protected: + ~MyListBase() {} +}; + +template +class MyList : public MyListBase +{ +public: + inline MyList() { } +}; + +template <> struct MyListBase +{ +}; + +class MyIntList : public MyList +{ + inline MyIntList(MyList &&l) { } +}; + +void MyFunc(MyList *list);