| Index: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| index 2d221d7667a858c0d1ff8ec4bf1c7ca5b79f919b..2d6eff256817f7b2c897a7a851329e47a54fd382 100644
|
| --- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| +++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
|
| @@ -17,6 +17,7 @@
|
| #include "clang/AST/RecursiveASTVisitor.h"
|
| #include "clang/Frontend/CompilerInstance.h"
|
| #include "clang/Frontend/FrontendPluginRegistry.h"
|
| +#include "clang/Sema/Sema.h"
|
|
|
| using namespace clang;
|
| using std::string;
|
| @@ -144,6 +145,23 @@ const char kClassMustDeclareGCMixinTraceMethod[] =
|
| "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must"
|
| " locally declare and override trace(Visitor*)";
|
|
|
| +// Use a local RAV implementation to simply collect all FunctionDecls marked for
|
| +// late template parsing. This happens with the flag -fdelayed-template-parsing,
|
| +// which is on by default in MSVC-compatible mode.
|
| +std::set<FunctionDecl*> GetLateParsedFunctionDecls(TranslationUnitDecl* decl) {
|
| + struct Visitor : public RecursiveASTVisitor<Visitor> {
|
| + bool VisitFunctionDecl(FunctionDecl* function_decl) {
|
| + if (function_decl->isLateTemplateParsed())
|
| + late_parsed_decls.insert(function_decl);
|
| + return true;
|
| + }
|
| +
|
| + std::set<FunctionDecl*> late_parsed_decls;
|
| + } v;
|
| + v.TraverseDecl(decl);
|
| + return v.late_parsed_decls;
|
| +}
|
| +
|
| struct BlinkGCPluginOptions {
|
| BlinkGCPluginOptions()
|
| : enable_oilpan(false)
|
| @@ -1017,6 +1035,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| if (diagnostic_.hasErrorOccurred())
|
| return;
|
|
|
| + ParseFunctionTemplates(context.getTranslationUnitDecl());
|
| +
|
| CollectVisitor visitor;
|
| visitor.TraverseDecl(context.getTranslationUnitDecl());
|
|
|
| @@ -1063,6 +1083,31 @@ class BlinkGCPluginConsumer : public ASTConsumer {
|
| }
|
| }
|
|
|
| + void ParseFunctionTemplates(TranslationUnitDecl* decl) {
|
| + if (!instance_.getLangOpts().DelayedTemplateParsing)
|
| + return; // Nothing to do.
|
| +
|
| + std::set<FunctionDecl*> late_parsed_decls =
|
| + GetLateParsedFunctionDecls(decl);
|
| + clang::Sema& sema = instance_.getSema();
|
| +
|
| + for (const FunctionDecl* fd : late_parsed_decls) {
|
| + assert(fd->isLateTemplateParsed());
|
| +
|
| + if (!Config::IsTraceMethod(fd))
|
| + continue;
|
| +
|
| + if (instance_.getSourceManager().isInSystemHeader(
|
| + instance_.getSourceManager().getSpellingLoc(fd->getLocation())))
|
| + continue;
|
| +
|
| + // Force parsing and AST building of the yet-uninstantiated function
|
| + // template trace method bodies.
|
| + clang::LateParsedTemplate* lpt = sema.LateParsedTemplateMap[fd];
|
| + sema.LateTemplateParser(sema.OpaqueParser, *lpt);
|
| + }
|
| + }
|
| +
|
| // Main entry for checking a record declaration.
|
| void CheckRecord(RecordInfo* info) {
|
| if (IsIgnored(info))
|
|
|