[cfe-dev] Analysing a file with AST matcher tool takes significant more time than just compile the same file
Manuel Klimek
klimek at google.com
Thu Jul 16 03:11:53 PDT 2015
Shouldn't be... you also don't have overly unspecific matchers... I'd be
curious about some profiling in your case...
On Thu, Jul 16, 2015 at 12:07 PM Han Wang <wanghan02 at gmail.com> wrote:
> We use truly a lot of templates in the files. Is it a possible reason why
> it's so slow?
>
> On Thu, Jul 16, 2015 at 11:57 AM, Han Wang <wanghan02 at gmail.com> wrote:
>
>> Hi Manuel,
>>
>> After using -O2 the speed is 30% faster from 10min to 7min. If I use
>> clang to just compile this source file, it takes 40sec.
>>
>> Best regards,
>> Han
>>
>> On Thu, Jul 16, 2015 at 11:33 AM, Manuel Klimek <klimek at google.com>
>> wrote:
>>
>>> You'll want to use Lexer::getSourceText instead of trying to write your
>>> own (trust me, it's hard ;), but otherwise your code looks innocent enough.
>>> Are you compiling with at least -O2 and NDEBUG enabled?
>>>
>>> On Thu, Jul 16, 2015 at 11:26 AM Han Wang <wanghan02 at gmail.com> wrote:
>>>
>>>> #include <stdio.h>
>>>> #include <string>
>>>> #include <vector>
>>>> #include <system_error>
>>>> #include <type_traits>
>>>> #include "clang/AST/AST.h"
>>>> #include "clang/Frontend/TextDiagnosticPrinter.h"
>>>> #include "clang/Tooling/CommonOptionsParser.h"
>>>> #include "clang/ASTMatchers/ASTMatchers.h"
>>>> #include "clang/ASTMatchers/ASTMatchFinder.h"
>>>> #include "clang/Basic/SourceManager.h"
>>>> #include "clang/Frontend/FrontendActions.h"
>>>> #include "clang/Lex/Lexer.h"
>>>> #include "clang/Tooling/CompilationDatabase.h"
>>>> #include "clang/Tooling/Refactoring.h"
>>>> #include "clang/Tooling/Tooling.h"
>>>> #include "llvm/ADT/Twine.h"
>>>> #include "llvm/Support/CommandLine.h"
>>>> #include "llvm/Support/MemoryBuffer.h"
>>>> #include "llvm/Support/Path.h"
>>>> #include "llvm/Support/Signals.h"
>>>> #include "llvm/Support/raw_ostream.h"
>>>> #include "llvm/Support/TargetSelect.h"
>>>>
>>>> using namespace llvm;
>>>> using clang::tooling::newFrontendActionFactory;
>>>> using clang::tooling::Replacement;
>>>> using clang::tooling::CompilationDatabase;
>>>> using namespace clang;
>>>> using namespace clang::ast_matchers;
>>>> using namespace clang::driver;
>>>> using namespace clang::tooling;
>>>>
>>>> static llvm::cl::OptionCategory ToolingSampleCategory("IsEmpty");
>>>>
>>>>
>>>> // Returns the text that makes up 'node' in the source.
>>>> // Returns an empty string if the text cannot be found.
>>>> template <typename T>
>>>> static std::string getText(const SourceManager &SourceManager, const T
>>>> &Node) {
>>>> SourceLocation StartSpellingLocation =
>>>> SourceManager.getSpellingLoc(Node.getLocStart());
>>>> SourceLocation EndSpellingLocation =
>>>> SourceManager.getSpellingLoc(Node.getLocEnd());
>>>> if (!StartSpellingLocation.isValid() ||
>>>> !EndSpellingLocation.isValid()) {
>>>> return std::string();
>>>> }
>>>> bool Invalid = true;
>>>> const char *Text =
>>>> SourceManager.getCharacterData(StartSpellingLocation, &Invalid);
>>>> if (Invalid) {
>>>> return std::string();
>>>> }
>>>> std::pair<FileID, unsigned> Start =
>>>> SourceManager.getDecomposedLoc(StartSpellingLocation);
>>>> std::pair<FileID, unsigned> End =
>>>> SourceManager.getDecomposedLoc(Lexer::getLocForEndOfToken(
>>>> EndSpellingLocation, 0, SourceManager, LangOptions()));
>>>> if (Start.first != End.first) {
>>>> // Start and end are in different files.
>>>> return std::string();
>>>> }
>>>> if (End.second < Start.second) {
>>>> // Shuffling text with macros may cause this.
>>>> return std::string();
>>>> }
>>>> return std::string(Text, End.second - Start.second);
>>>> }
>>>>
>>>> class ColIsEmptyHandler: public MatchFinder::MatchCallback {
>>>> public:
>>>> ColIsEmptyHandler(Replacements *Replace): Replace(Replace) {};
>>>> virtual void run(const MatchFinder::MatchResult &Result) {
>>>> if (const CXXMemberCallExpr *callExpr =
>>>> Result.Nodes.getNodeAs<clang::CXXMemberCallExpr>("Col::IsEmptyExpr")) {
>>>> const std::string text = getText(*(Result.SourceManager),
>>>> *callExpr);
>>>> Replacement Rep(*(Result.SourceManager),
>>>> CharSourceRange::getTokenRange(SourceRange(callExpr->getCallee()->getExprLoc())),
>>>> "IsEmpty");
>>>> Replace->insert(Rep);
>>>> }
>>>> }
>>>> private:
>>>> Replacements *Replace;
>>>> };
>>>>
>>>> class ColIsEmptyInClassHandler: public MatchFinder::MatchCallback {
>>>> public:
>>>> ColIsEmptyInClassHandler(Replacements *Replace): Replace(Replace) {};
>>>> virtual void run(const MatchFinder::MatchResult &Result) {
>>>> if (const CXXMethodDecl *decl =
>>>> Result.Nodes.getNodeAs<clang::CXXMethodDecl>("Col::IsEmptyInClass")) {
>>>> const std::string text = getText(*(Result.SourceManager), *decl);
>>>> Replacement Rep(*(Result.SourceManager),
>>>> CharSourceRange::getTokenRange(SourceRange(decl->getNameInfo().getLoc())),
>>>> "IsEmpty");
>>>> Replace->insert(Rep);
>>>> }
>>>> }
>>>> private:
>>>> Replacements *Replace;
>>>> };
>>>>
>>>> int main(int argc, const char **argv) {
>>>> llvm::InitializeAllTargets();
>>>> llvm::InitializeAllTargetMCs();
>>>> llvm::InitializeAllAsmPrinters();
>>>> llvm::InitializeAllAsmParsers();
>>>> CommonOptionsParser op(argc, argv, ToolingSampleCategory);
>>>> RefactoringTool Tool(op.getCompilations(), op.getSourcePathList());
>>>> // Set up AST matcher callbacks.
>>>> ColIsEmptyHandler HandlerForColIsEmpty(&Tool.getReplacements());
>>>> ColIsEmptyInClassHandler
>>>> HandlerForColIsEmptyInClass(&Tool.getReplacements());
>>>> MatchFinder Finder;
>>>> Finder.addMatcher(memberCallExpr(hasDeclaration(methodDecl(
>>>> hasName("Empty"),
>>>> ofClass(isSameOrDerivedFrom(hasName("Col")))))).bind("Col::IsEmptyExpr"),
>>>> &HandlerForColIsEmpty);
>>>> Finder.addMatcher(methodDecl(hasName("Empty"),
>>>> ofClass(isSameOrDerivedFrom(hasName("Col")))).bind("Col::IsEmptyInClass"),
>>>> &HandlerForColIsEmptyInClass);
>>>> // Run the tool and collect a list of replacements.
>>>> if (int Result =
>>>> Tool.runAndSave(newFrontendActionFactory(&Finder).get())) {
>>>> return Result;
>>>> }
>>>> llvm::outs() << "Replacements collected by the tool:\n";
>>>> for (auto &r : Tool.getReplacements()) {
>>>> llvm::outs() << r.toString() << "\n";
>>>> }
>>>> return 0;
>>>> }
>>>>
>>>> On Thu, Jul 16, 2015 at 11:11 AM, Manuel Klimek <klimek at google.com>
>>>> wrote:
>>>>
>>>>> Can you post the code for the matcher?
>>>>>
>>>>> On Thu, Jul 16, 2015 at 11:02 AM Han Wang <wanghan02 at gmail.com> wrote:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> I'm using clang AST matcher tool on MAC to analyse complex files with
>>>>>> many many headers included. It turns out that it takes more than 10 times
>>>>>> longer than just compile the same file with clang. Is it normal or am I
>>>>>> doing something wrong? Thanks!
>>>>>>
>>>>>> Best regards,
>>>>>> Han
>>>>>> _______________________________________________
>>>>>> cfe-dev mailing list
>>>>>> cfe-dev at cs.uiuc.edu
>>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>>>>>
>>>>>
>>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150716/dd37b1da/attachment.html>
More information about the cfe-dev
mailing list