Skip to content
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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Stepakrap
Copy link

No description provided.

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());
Copy link
Owner

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).

Copy link
Author

@Stepakrap Stepakrap May 29, 2022

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(
Copy link
Owner

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.

Copy link
Author

@Stepakrap Stepakrap May 29, 2022

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,
Copy link
Owner

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?

Copy link
Author

@Stepakrap Stepakrap May 29, 2022

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 {
Copy link
Owner

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?

Copy link
Author

@Stepakrap Stepakrap May 29, 2022

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;

Включил эти изменения в свой код

@ElizJogar
Copy link
Owner

The program does not compile. Please fix and describe the reason of failure.

@Stepakrap
Copy link
Author

The program does not compile. Please fix and describe the reason of failure.

Исправил, ошибся в названии переменных и функций.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants