| Index: tools/clang/plugins/FindBadConstructsConsumer.cpp
|
| diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
|
| index d1fc29df7ce5117d8a58fcf762917d730d7eddc0..8bd48b8c0d761fb2d43b20e962cfdff3bfb7c362 100644
|
| --- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
|
| +++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
|
| @@ -7,6 +7,7 @@
|
| #include "clang/Frontend/CompilerInstance.h"
|
| #include "clang/AST/Attr.h"
|
| #include "clang/Lex/Lexer.h"
|
| +#include "clang/Sema/Sema.h"
|
| #include "llvm/Support/raw_ostream.h"
|
|
|
| using namespace clang;
|
| @@ -98,11 +99,32 @@ bool IsPodOrTemplateType(const CXXRecordDecl& record) {
|
| record.isDependentType();
|
| }
|
|
|
| +// 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;
|
| +}
|
| +
|
| } // namespace
|
|
|
| FindBadConstructsConsumer::FindBadConstructsConsumer(CompilerInstance& instance,
|
| const Options& options)
|
| : ChromeClassTester(instance, options) {
|
| + if (options.check_ipc) {
|
| + ipc_visitor_.reset(new CheckIPCVisitor(instance));
|
| + }
|
| +
|
| // Messages for virtual method specifiers.
|
| diag_method_requires_override_ =
|
| diagnostic().getCustomDiagID(getErrorLevel(), kMethodRequiresOverride);
|
| @@ -136,6 +158,22 @@ FindBadConstructsConsumer::FindBadConstructsConsumer(CompilerInstance& instance,
|
| DiagnosticsEngine::Note, kNoteProtectedNonVirtualDtor);
|
| }
|
|
|
| +void FindBadConstructsConsumer::Traverse(ASTContext& context) {
|
| + if (ipc_visitor_) {
|
| + ipc_visitor_->set_context(&context);
|
| + ParseFunctionTemplates(context.getTranslationUnitDecl());
|
| + }
|
| + RecursiveASTVisitor::TraverseDecl(context.getTranslationUnitDecl());
|
| + if (ipc_visitor_) ipc_visitor_->set_context(nullptr);
|
| +}
|
| +
|
| +bool FindBadConstructsConsumer::TraverseDecl(Decl* decl) {
|
| + if (ipc_visitor_) ipc_visitor_->BeginDecl(decl);
|
| + bool result = RecursiveASTVisitor::TraverseDecl(decl);
|
| + if (ipc_visitor_) ipc_visitor_->EndDecl();
|
| + return result;
|
| +}
|
| +
|
| bool FindBadConstructsConsumer::VisitDecl(clang::Decl* decl) {
|
| clang::TagDecl* tag_decl = dyn_cast<clang::TagDecl>(decl);
|
| if (tag_decl && tag_decl->isCompleteDefinition())
|
| @@ -143,6 +181,17 @@ bool FindBadConstructsConsumer::VisitDecl(clang::Decl* decl) {
|
| return true;
|
| }
|
|
|
| +bool FindBadConstructsConsumer::VisitTemplateSpecializationType(
|
| + TemplateSpecializationType* spec) {
|
| + if (ipc_visitor_) ipc_visitor_->VisitTemplateSpecializationType(spec);
|
| + return true;
|
| +}
|
| +
|
| +bool FindBadConstructsConsumer::VisitCallExpr(CallExpr* call_expr) {
|
| + if (ipc_visitor_) ipc_visitor_->VisitCallExpr(call_expr);
|
| + return true;
|
| +}
|
| +
|
| void FindBadConstructsConsumer::CheckChromeClass(SourceLocation record_location,
|
| CXXRecordDecl* record) {
|
| // By default, the clang checker doesn't check some types (templates, etc).
|
| @@ -876,4 +925,22 @@ void FindBadConstructsConsumer::CheckWeakPtrFactoryMembers(
|
| }
|
| }
|
|
|
| +void FindBadConstructsConsumer::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());
|
| +
|
| + // 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);
|
| + }
|
| +}
|
| +
|
| } // namespace chrome_checker
|
|
|