-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Лабораторная работа №3. Крапивенских Степан. 381906-3 #51
base: main
Are you sure you want to change the base?
Conversation
main.cpp
Outdated
void run(const MatchFinder::MatchResult& Result) override { | ||
const auto* cast_expression = Result.Nodes.getNodeAs<CStyleCastexpr>("cast"); | ||
auto replace = CharSourceRange::getCharRange(cast_expression->getLParenLoc(), | ||
cast_expression->getSubexprAsWritten()->getBeginLoc()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please describe the difference between getSubExprAsWritten()->getBeginLoc()
and getRParenLoc().getLocWithOffset(1)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getSubExprAsWritten()->getBeginLoc()
вернет SourceLocation
начала имени самой переменной, для который мы выполняем приведение.
getRParenLoc().getLocWithOffset(1)
вернет SourceLocation
закрывающей скобки после типа + смещение вправо на 1.
Рассмотрим использование этих функций для кода :
int main() {
float f;
int i = (int) f;
return 0;
}
Если использовать getSubExprAsWritten()->getBeginLoc()
, результат:
int main() {
float f;
int i = static_cast<int>(f);
return 0;
}
getRParenLoc().getLocWithOffset(1)
:
int main() {
float f;
int i = static_cast<int>( f);
return 0;
}
Таким образом, лучше использовать getSubExprAsWritten()->getBeginLoc()
.
main.cpp
Outdated
auto replace = CharSourceRange::getCharRange(cast_expression->getLParenLoc(), | ||
cast_expression->getSubexprAsWritten()->getBeginLoc()); | ||
auto& src_mngmnt = *Result.SourceManager; | ||
auto typename = Lexer::getSourceText(CharSourceRange::getTokenRange( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please descrbe the difference between the use of getCharRange()
and getTokenRange()
with examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- "
getCharRange()
returns range specifying the starting/ending character by the specified locations." - "
getTokenRange()
returns range specifying the start of the range and the start of the last token of the range."
Для примера запустим такой код:
const auto* cast_expression = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
auto& src_mngmnt = *Result.SourceManager;
auto charRange = Lexer::getAsCharRange(
CharSourceRange::getCharRange(cast_expression->getLParenLoc().getLocWithOffset(1),
cast_expression->getRParenLoc().getLocWithOffset(-2)),
src_mngmnt, Result.Context->getLangOpts());
auto tokenRange = Lexer::getAsCharRange(
CharSourceRange::getTokenRange(cast_expression->getLParenLoc().getLocWithOffset(1),
cast_expression->getRParenLoc().getLocWithOffset(-2)),
src_mngmnt, Result.Context->getLangOpts());
llvm::outs() << "\n char range start: " << charRange.getBegin().printToString(src_mngmnt)
<< ",\n char range end: " << charRange.getEnd().printToString(src_mngmnt) << "\n";
llvm::outs() << "\n token range start: " << tokenRange.getBegin().printToString(src_mngmnt)
<< ",\n token range end: " << tokenRange.getEnd().printToString(src_mngmnt) << "\n";
Для кода:
#include <iostream>
int main() {
float foooo;
//f - pos 11
int i = (int)(foooo);
return 0;
}
Результат будет:
char range start: D:\Prog\llvm\build\MinSizeRel\bin\.\main.cpp:4:11,
char range end: D:\Prog\llvm\build\MinSizeRel\bin\.\main.cpp:4:12
token range start: D:\Prog\llvm\build\MinSizeRel\bin\.\main.cpp:4:11,
token range end: D:\Prog\llvm\build\MinSizeRel\bin\.\main.cpp:4:14
main.cpp
Outdated
src_mngmnt, LangOptions()); | ||
const auto* expr = cast_expression->getSubexprAsWritten()->IgnoreImpCasts(); | ||
auto new_text_begin = ("static_cast<" + typename + ">(").str(); | ||
auto new_expr = Lexer::getLocForEndOfToken(expr->getEndLoc(), 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please describe the reason of using theLexer::getLocForEndOfToken()
function here.
What would be the difference if rewriter.InsertText(styleCastExpr->getEndLoc().getLocOffset(1), ")");
was used here?
What would be the difference if rewriter.InsertTextAfterToken(styleCastExpr->getEndLoc(), ")");
was used here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lexer::getLocForEndOfToken()
возвращает SourceLocation
сразу после токена SubExpr->getEndLoc()
. Я использую его, чтобы захватить всё имя переменной целиком.
SubExpr->getEndLoc()
же возвращает просто SourceLocation
последней позиции в SubExpr
.
Возьмем для примера код:
int main() {
float foooo;
int i = (int)foooo;
return 0;
}
Если использовать _rewriter.InsertText(cast_expression->getEndLoc().getLocOffset(1), ")");
, в скобках будет только первая буква имени переменной:
int main() {
float foooo;
int i = static_cast<int>(f)oooo;
return 0;
}
При использовании _rewriter.InsertTextAfterToken(cast_expression->getEndLoc(), ")");
в скобках будет всё имя переменной:
int main() {
float foooo;
int i = static_cast<int>(foooo);
return 0;
}
// Your code goes here | ||
}; | ||
CastCallBack(Rewriter& rewriter) : _rewriter(rewriter) {}; | ||
void run(const MatchFinder::MatchResult& Result) override { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- How to prevent parentheses from being added if they are already present in the (int)(f) code?
- How to prevent changing the C style cast code for a special case - when we want to suppress warnings about unused variables?
- How to prevent changing the C style cast code in macros?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- How to prevent parentheses from being added if they are already present in the (int)(f) code?
Использовать проверку на isa<ParenExpr>
:
if (!isa<ParenExpr>(cast_expression->getSubExprAsWritten()->IgnoreImpCasts())) {
new_text_begin.append(")");
_rewriter.InsertTextAfterToken(cast_expression->getEndLoc(), ")");
}
- How to prevent changing the C style cast code for a special case - when we want to suppress warnings about unused variables?
Использовать проверку на CK_ToVoid
:
if (cast_expression->getCastKind() == CK_ToVoid) return;
- How to prevent changing the C style cast code in macros?
Использовать проверку на isMacroID
if (cast_expression->getExprLoc().isMacroID()) return;
Включил эти изменения в свой код
The program does not compile. Please fix and describe the reason of failure. |
Исправил, ошибся в названии переменных и функций. |
No description provided.