Chromium Code Reviews| 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. |
|
dcheng
2016/03/30 18:29:22
Fix this comment. Also, how come we don't need to
|
| + clang::LateParsedTemplate* lpt = sema.LateParsedTemplateMap[fd]; |
| + sema.LateTemplateParser(sema.OpaqueParser, *lpt); |
| + } |
| +} |
| + |
| } // namespace chrome_checker |