r220400 - Reland r219810 "Fix late template parsing leak with incremental processing"
Reid Kleckner
reid at kleckner.net
Wed Oct 22 10:50:19 PDT 2014
Author: rnk
Date: Wed Oct 22 12:50:19 2014
New Revision: 220400
URL: http://llvm.org/viewvc/llvm-project?rev=220400&view=rev
Log:
Reland r219810 "Fix late template parsing leak with incremental processing"
Original message:
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!
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/unittests/Frontend/FrontendActionTest.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=220400&r1=220399&r2=220400&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Oct 22 12:50:19 2014
@@ -1155,6 +1155,7 @@ private:
void ParseLateTemplatedFuncDef(LateParsedTemplate &LPT);
static void LateTemplateParserCallback(void *P, LateParsedTemplate &LPT);
+ static void LateTemplateParserCleanupCallback(void *P);
Sema::ParsingClassState
PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface);
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=220400&r1=220399&r2=220400&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Oct 22 12:50:19 2014
@@ -480,11 +480,16 @@ public:
/// \brief Callback to the parser to parse templated functions when needed.
typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT);
+ typedef void LateTemplateParserCleanupCB(void *P);
LateTemplateParserCB *LateTemplateParser;
+ LateTemplateParserCleanupCB *LateTemplateParserCleanup;
void *OpaqueParser;
- void SetLateTemplateParser(LateTemplateParserCB *LTP, void *P) {
+ void SetLateTemplateParser(LateTemplateParserCB *LTP,
+ LateTemplateParserCleanupCB *LTPCleanup,
+ void *P) {
LateTemplateParser = LTP;
+ LateTemplateParserCleanup = LTPCleanup;
OpaqueParser = P;
}
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=220400&r1=220399&r2=220400&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Wed Oct 22 12:50:19 2014
@@ -510,6 +510,13 @@ namespace {
};
}
+void Parser::LateTemplateParserCleanupCallback(void *P) {
+ // While this RAII helper doesn't bracket any actual work, the destructor will
+ // clean up annotations that were created during ActOnEndOfTranslationUnit
+ // when incremental processing is enabled.
+ DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(((Parser *)P)->TemplateIds);
+}
+
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
/// action tells us to. This returns true if the EOF was encountered.
bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
@@ -542,7 +549,10 @@ bool Parser::ParseTopLevelDecl(DeclGroup
case tok::eof:
// Late template parsing can begin.
if (getLangOpts().DelayedTemplateParsing)
- Actions.SetLateTemplateParser(LateTemplateParserCallback, this);
+ Actions.SetLateTemplateParser(LateTemplateParserCallback,
+ PP.isIncrementalProcessingEnabled() ?
+ LateTemplateParserCleanupCallback : nullptr,
+ this);
if (!PP.isIncrementalProcessingEnabled())
Actions.ActOnEndOfTranslationUnit();
//else don't tell Sema that we ended parsing: more input might come.
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=220400&r1=220399&r2=220400&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Oct 22 12:50:19 2014
@@ -88,6 +88,7 @@ Sema::Sema(Preprocessor &pp, ASTContext
CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
IsBuildingRecoveryCallExpr(false),
ExprNeedsCleanups(false), LateTemplateParser(nullptr),
+ LateTemplateParserCleanup(nullptr),
OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr),
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
NSNumberDecl(nullptr),
@@ -672,6 +673,9 @@ void Sema::ActOnEndOfTranslationUnit() {
}
PerformPendingInstantiations();
+ if (LateTemplateParserCleanup)
+ LateTemplateParserCleanup(OpaqueParser);
+
CheckDelayedMemberExceptionSpecs();
}
Modified: cfe/trunk/unittests/Frontend/FrontendActionTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Frontend/FrontendActionTest.cpp?rev=220400&r1=220399&r2=220400&view=diff
==============================================================================
--- cfe/trunk/unittests/Frontend/FrontendActionTest.cpp (original)
+++ cfe/trunk/unittests/Frontend/FrontendActionTest.cpp Wed Oct 22 12:50:19 2014
@@ -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, IncrementalParsi
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) {}
More information about the cfe-commits
mailing list