How to get the source text from line number using clang?
Asked Answered
P

1

7

I am using clang matcher to obtain the result nodes. From the result nodes, I am able to get the line number, let us say 17. Now, I would like to get the entire source code in that line. Please help.

Let me explain in detail. I have a clang matcher that finds the floating literal in the source code. For example, line 17, sr = 2.0 * rt_urand_Upu32_Yd_f_pw_snf(u); is the source code, then it matches the 2.0. This is my matcher:

const auto PA = floatLiteral(
                                isExpansionInMainFile(), 
                                unless(hasAncestor(arraySubscriptExpr()))
                            ).bind("pa");
            MatchFinder MatchFinder;
            MatchFinder.addMatcher(PA, &Handler);
            MatchFinder.matchAST(Context);

From the matcher, I am able to obtain the node where it got matched. I am able to retrieve the line number (line 17) and column number (6). Please find my code below:

const clang::FloatingLiteral* Variable = Result.Nodes.getNodeAs<clang::FloatingLiteral>("pa");
clang::SourceRange loc = Variable16->getSourceRange();
locStart = srcMgr.getPresumedLoc(loc.getBegin());
locEnd = srcMgr.getPresumedLoc(loc.getEnd());
std::cout << locStart.getLine()<< ":" << locEnd.getLine() << std::endl;
std::cout << locStart.getColumn() <<":" << locEnd.getColumn() << std::endl;

Now, if I try to retrieve the source code I am getting only the partial data. After doing some research in online, I tried to retrieve the source code in two ways. First approach is using lexer, please find the code below:

llvm::StringRef ref = Lexer::getSourceText(CharSourceRange::getCharRange(statement->getSourceRange()), srcMgr, LangOptions());
cout << ref.str() << endl;

Second approach is using rewriter, please find the code below:

clang::Rewriter rewriter;
rewriter.setSourceMgr(Result.Context->getSourceManager(),Result.Context->getLangOpts());
cout<<rewriter.getRewrittenText (loc)<<endl;

To my understanding, it seems that I need the sourcerange starting from column 0 of line 17 to end of column in line 17. The AST matcher only matches specific node, so my question is:

1) is it possible to get the final column number of line 17?

2) is there any other approach to get the source code from line number?

3) is there any other approach to get the source code from matcher?

Thanks for the help.

Pangermanism answered 17/6, 2018 at 3:24 Comment(1)
Did You get the solution for the number 2 question in your post? If yes Please let us know the answerVasyuta
I
0
  1. There is no direct way to get the last column of a line , but there is a solution to get the beginning of the line . I assume that you have the SourceManager(SM) and the SourceLocation(SL)
SM.translateLineCol(SM.getMainFileID(),SM.getSpellingLineNumber(SL),1);

If you really want to get the end of specific line you can set the column number to a incredible number , like 1000 . If the line has less than 1000 characters , it will stuck at last character , but if the line has more than 1000 characters , it will not appear at the end of line , so this solution is not stable . The example is getting the end location of line 17.

SM.translateLineCol(SM.getMainFileID(),17,1000);
  1. By Using the solution above , you can get source code by using Rewriter(Rw) . For example , if you want to get the code in line 17 , and store it in string result
SourceLocation thisline=SM.translateLineCol(SM.getMainFileID(),17,1); // get the beginning of line 17
SourceLocation nextline=SM.translateLineCol(SM.getMainFileID(),18,1); // get the beginning of line 18
string result = Rw.getRewrittenText(SourceRange(thisline,nextline));
  1. Yes , if you have proper SourceRange and Rewriter , you can use getRewrittenText() from match result .
Indwell answered 26/10, 2021 at 12:34 Comment(2)
Where is the rewriter to use?Bargeboard
Shat do you mean? @BargeboardGarpike

© 2022 - 2024 — McMap. All rights reserved.