diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-10-15 17:08:33 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-10-15 17:08:33 +0000 |
commit | 001fe64333f184251ea72aba8b3b8144e2a2b9df (patch) | |
tree | 391de84dfaa5949a547d46c32d325d59642948f7 /clang/unittests/Frontend/FrontendActionTest.cpp | |
parent | 4e0854f23c9b084c4fbfd02e304c28c292588f1a (diff) | |
download | bcm5719-llvm-001fe64333f184251ea72aba8b3b8144e2a2b9df.tar.gz bcm5719-llvm-001fe64333f184251ea72aba8b3b8144e2a2b9df.zip |
Fix late template parsing leak with incremental processing
Add a second late template parser callback meant to cleanup any
resources allocated by late template parsing. Call it from the
Sema::ActOnEndOfTranslationUnit method after all pending template
instantiations have been completed. Teach Parser::ParseTopLevelDecl to
install the cleanup callback when incremental processing is enabled so
that Parser::TemplateIds can be freed.
Patch by Brad King!
llvm-svn: 219810
Diffstat (limited to 'clang/unittests/Frontend/FrontendActionTest.cpp')
-rw-r--r-- | clang/unittests/Frontend/FrontendActionTest.cpp | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp index 31711566921..9973d3f8bea 100644 --- a/clang/unittests/Frontend/FrontendActionTest.cpp +++ b/clang/unittests/Frontend/FrontendActionTest.cpp @@ -14,6 +14,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" @@ -25,10 +26,13 @@ namespace { class TestASTFrontendAction : public ASTFrontendAction { public: - TestASTFrontendAction(bool enableIncrementalProcessing = false) - : EnableIncrementalProcessing(enableIncrementalProcessing) { } + TestASTFrontendAction(bool enableIncrementalProcessing = false, + bool actOnEndOfTranslationUnit = false) + : EnableIncrementalProcessing(enableIncrementalProcessing), + ActOnEndOfTranslationUnit(actOnEndOfTranslationUnit) { } bool EnableIncrementalProcessing; + bool ActOnEndOfTranslationUnit; std::vector<std::string> decl_names; virtual bool BeginSourceFileAction(CompilerInstance &ci, StringRef filename) { @@ -40,15 +44,22 @@ public: virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return llvm::make_unique<Visitor>(decl_names); + return llvm::make_unique<Visitor>(CI, ActOnEndOfTranslationUnit, + decl_names); } private: class Visitor : public ASTConsumer, public RecursiveASTVisitor<Visitor> { public: - Visitor(std::vector<std::string> &decl_names) : decl_names_(decl_names) {} + Visitor(CompilerInstance &ci, bool actOnEndOfTranslationUnit, + std::vector<std::string> &decl_names) : + CI(ci), ActOnEndOfTranslationUnit(actOnEndOfTranslationUnit), + decl_names_(decl_names) {} virtual void HandleTranslationUnit(ASTContext &context) { + if (ActOnEndOfTranslationUnit) { + CI.getSema().ActOnEndOfTranslationUnit(); + } TraverseDecl(context.getTranslationUnitDecl()); } @@ -58,6 +69,8 @@ private: } private: + CompilerInstance &CI; + bool ActOnEndOfTranslationUnit; std::vector<std::string> &decl_names_; }; }; @@ -102,6 +115,34 @@ TEST(ASTFrontendAction, IncrementalParsing) { EXPECT_EQ("x", test_action.decl_names[1]); } +TEST(ASTFrontendAction, LateTemplateIncrementalParsing) { + CompilerInvocation *invocation = new CompilerInvocation; + invocation->getLangOpts()->CPlusPlus = true; + invocation->getLangOpts()->DelayedTemplateParsing = true; + invocation->getPreprocessorOpts().addRemappedFile( + "test.cc", MemoryBuffer::getMemBuffer( + "template<typename T> struct A { A(T); T data; };\n" + "template<typename T> struct B: public A<T> {\n" + " B();\n" + " B(B const& b): A<T>(b.data) {}\n" + "};\n" + "B<char> c() { return B<char>(); }\n").release()); + invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc", + IK_CXX)); + invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly; + invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu"; + CompilerInstance compiler; + compiler.setInvocation(invocation); + compiler.createDiagnostics(); + + TestASTFrontendAction test_action(/*enableIncrementalProcessing=*/true, + /*actOnEndOfTranslationUnit=*/true); + ASSERT_TRUE(compiler.ExecuteAction(test_action)); + ASSERT_EQ(13U, test_action.decl_names.size()); + EXPECT_EQ("A", test_action.decl_names[0]); + EXPECT_EQ("c", test_action.decl_names[12]); +} + struct TestPPCallbacks : public PPCallbacks { TestPPCallbacks() : SeenEnd(false) {} |