Commit 2b87ce49 authored by thakis's avatar thakis Committed by Commit bot

win: Make oilpan plugin work better with delayed template parsing.

This time with correct copyright headers.

On Windows, clang-cl only parses template methods that are
referenced (-fdelayed-template-parsing), so members traced from
unreferenced template methods weren't seen by the plugin, which
caused it to warn about them.

Explicitly parse delayed template methods that look like they
are trace methods and that aren't in system headers to work around
this. This is based on Kim Grasman's patch for the IWYU project:
https://code.google.com/p/include-what-you-use/source/detail?r=566

Together with clang r237531 (
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20150511/129285.html )
this should fix all failing oilpan plugin tests on Windows.

BUG=486571
TBR=hans

Review URL: https://codereview.chromium.org/1135333007

Cr-Commit-Position: refs/heads/master@{#330295}
parent ce6226a7
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Sema/Sema.h"
using namespace clang; using namespace clang;
using std::string; using std::string;
...@@ -144,6 +145,23 @@ const char kClassMustDeclareGCMixinTraceMethod[] = ...@@ -144,6 +145,23 @@ const char kClassMustDeclareGCMixinTraceMethod[] =
"[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must"
" locally declare and override trace(Visitor*)"; " 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 { struct BlinkGCPluginOptions {
BlinkGCPluginOptions() BlinkGCPluginOptions()
: enable_oilpan(false) : enable_oilpan(false)
...@@ -1017,6 +1035,8 @@ class BlinkGCPluginConsumer : public ASTConsumer { ...@@ -1017,6 +1035,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
if (diagnostic_.hasErrorOccurred()) if (diagnostic_.hasErrorOccurred())
return; return;
ParseFunctionTemplates(context.getTranslationUnitDecl());
CollectVisitor visitor; CollectVisitor visitor;
visitor.TraverseDecl(context.getTranslationUnitDecl()); visitor.TraverseDecl(context.getTranslationUnitDecl());
...@@ -1063,6 +1083,31 @@ class BlinkGCPluginConsumer : public ASTConsumer { ...@@ -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. // Main entry for checking a record declaration.
void CheckRecord(RecordInfo* info) { void CheckRecord(RecordInfo* info) {
if (IsIgnored(info)) if (IsIgnored(info))
......
...@@ -214,7 +214,7 @@ class Config { ...@@ -214,7 +214,7 @@ class Config {
TRACE_AFTER_DISPATCH_IMPL_METHOD TRACE_AFTER_DISPATCH_IMPL_METHOD
}; };
static TraceMethodType GetTraceMethodType(clang::FunctionDecl* method) { static TraceMethodType GetTraceMethodType(const clang::FunctionDecl* method) {
if (method->getNumParams() != 1) if (method->getNumParams() != 1)
return NOT_TRACE_METHOD; return NOT_TRACE_METHOD;
...@@ -244,7 +244,7 @@ class Config { ...@@ -244,7 +244,7 @@ class Config {
return NOT_TRACE_METHOD; return NOT_TRACE_METHOD;
} }
static bool IsTraceMethod(clang::FunctionDecl* method) { static bool IsTraceMethod(const clang::FunctionDecl* method) {
return GetTraceMethodType(method) != NOT_TRACE_METHOD; return GetTraceMethodType(method) != NOT_TRACE_METHOD;
} }
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "heap/stubs.h"
namespace blink {
struct HeapObject : public GarbageCollected<HeapObject> {
void trace(Visitor*) { }
};
template<typename T>
class TemplateBase
: public GarbageCollected<TemplateBase<T> > {
public:
void trace(Visitor* visitor) { visitor->trace(m_obj); }
private:
Member<HeapObject> m_obj;
};
class Subclass : public TemplateBase<Subclass> {
};
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment