Skip to content

Commit

Permalink
win: Make oilpan plugin work better with delayed template parsing.
Browse files Browse the repository at this point in the history
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}
  • Loading branch information
nico authored and Commit bot committed May 17, 2015
1 parent ce6226a commit 2b87ce4
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 2 deletions.
45 changes: 45 additions & 0 deletions tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1017,6 +1035,8 @@ class BlinkGCPluginConsumer : public ASTConsumer {
if (diagnostic_.hasErrorOccurred())
return;

ParseFunctionTemplates(context.getTranslationUnitDecl());

CollectVisitor visitor;
visitor.TraverseDecl(context.getTranslationUnitDecl());

Expand Down Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions tools/clang/blink_gc_plugin/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ class Config {
TRACE_AFTER_DISPATCH_IMPL_METHOD
};

static TraceMethodType GetTraceMethodType(clang::FunctionDecl* method) {
static TraceMethodType GetTraceMethodType(const clang::FunctionDecl* method) {
if (method->getNumParams() != 1)
return NOT_TRACE_METHOD;

Expand Down Expand Up @@ -244,7 +244,7 @@ class Config {
return NOT_TRACE_METHOD;
}

static bool IsTraceMethod(clang::FunctionDecl* method) {
static bool IsTraceMethod(const clang::FunctionDecl* method) {
return GetTraceMethodType(method) != NOT_TRACE_METHOD;
}

Expand Down
25 changes: 25 additions & 0 deletions tools/clang/blink_gc_plugin/tests/delayed_parsing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// 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> {
};

}
1 change: 1 addition & 0 deletions tools/clang/blink_gc_plugin/tests/delayed_parsing.flags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-fdelayed-template-parsing
Empty file.

0 comments on commit 2b87ce4

Please sign in to comment.