Chromium Code Reviews| 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..764217f5f09fa138a482097836bda4e540a836cd 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,36 @@ class BlinkGCPluginConsumer : public ASTConsumer { |
| } |
| } |
| + void ParseFunctionTemplates(TranslationUnitDecl* decl) { |
| + std::set<FunctionDecl*> late_parsed_decls = |
| + GetLateParsedFunctionDecls(decl); |
|
Reid Kleckner
2015/05/15 22:44:32
Traversing the whole AST might be expensive. Maybe
Nico
2015/05/15 22:57:26
We always build with asserts enabled, so that woul
|
| + clang::Sema& sema = instance_.getSema(); |
| + |
| + // If we have any late-parsed functions, make sure the |
| + // -fdelayed-template-parsing flag is on. Otherwise we don't know where |
| + // they came from. |
| + assert((instance_.getLangOpts().DelayedTemplateParsing || |
| + late_parsed_decls.empty()) && |
| + "Should not have late-parsed decls without " |
| + "-fdelayed-template-parsing."); |
| + |
| + 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)) |