-
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-2 #50
base: main
Are you sure you want to change the base?
Conversation
|
||
void run(const MatchFinder::MatchResult &Result) override { | ||
// Your code goes here | ||
|
||
const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("cast"); |
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.
What if CastExpr
is a null pointer? How to protect the program from crashing in such cases?
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.
Как сказано во втором вопросе, это приводит к сбоям. Тогда необходимо добавить условие, предотвращающее такую ситуацию:
if (CastExpr == nullptr)
return;
// Your code goes here | ||
|
||
const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("cast"); | ||
auto newRange = CharSourceRange::getCharRange(CastExpr->getLParenLoc(), CastExpr->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()
указывает на начало названия переменной, а getRParenLoc().getLocWithOffset(1)
указывает символы после закрывающей скобки типа.
Рассмотрим такой пример:
int main() {
float foo;
int i = (int) foo ;
return 0;
}
В случае с getRParenLoc().getLocWithOffset(1)
все, что было после закрывающей скобки до точки с запятой :
int main() {
float foo;
int i = static_cast<int>( foo) ;
return 0;
}
Но, используя getSubExprAsWritten()->getBeginLoc()
мы получаем просто название:
int main() {
float foo;
int i = static_cast<int>(foo) ;
return 0;
}
Поэтому использование 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.
Sorry but I don't understand the explanation:
В случае с getRParenLoc().getLocWithOffset(1) все, что было после закрывающей скобки до точки с запятой :
Но, используя 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.
Это пояснения к примерам. Первый пример кода - то, что подается.
В случае getRParenLoc().getLocWithOffset(1)
сохранились пробелы, так как "захват" шел с закрывающей скобки, а в случае с getSubExprAsWritten()->getBeginLoc()
- пробелов нет и мы получаем название переменной, так как "захват" шел с первого символа названия переменной.
auto newRange = CharSourceRange::getCharRange(CastExpr->getLParenLoc(), CastExpr->getSubExprAsWritten()->getBeginLoc()); | ||
auto &sManager = *Result.SourceManager; | ||
|
||
auto sText = Lexer::getSourceText(CharSourceRange::getTokenRange(CastExpr->getLParenLoc().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.
Please describe 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.
What will be the deduced type of the sText
variable?
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()
возвращает range символов до последнего символа включительно, а getTokenRange()
возвращает range токенов до начала последнего токена.
auto charRange = Lexer::getAsCharRange(
CharSourceRange::getCharRange(node->getLParenLoc().getLocWithOffset(1),
node->getRParenLoc().getLocWithOffset(-2)),
SM, Result.Context->getLangOpts());
auto tokenRange = Lexer::getAsCharRange(
CharSourceRange::getTokenRange(node->getLParenLoc().getLocWithOffset(1),
node->getRParenLoc().getLocWithOffset(-2)),
SM, Result.Context->getLangOpts());
llvm::outs() << "\n char range start: " << charRange.getBegin().printToString(SM) << ",\n char range end: " << charRange.getEnd().printToString(SM) << "\n";
llvm::outs() << "\n token range start: " << tokenRange.getBegin().printToString(SM) << ",\n token range
end: " << tokenRange.getEnd().printToString(SM) << "\n";
Вывод:
char range start: /UNN-C-Style-Checker/test/test.cpp:3:14,
char range end: /UNN-C-Style-Checker/test/test.cpp:3:15
token range start: /UNN-C-Style-Checker/test/test.cpp
:3:14,
token range end: /UNN-C-Style-Checker/test/test.cpp:3:17
Для примера:
int main() {
float foo;
int i = (int) foo ;
return 0;
}
sText
- llvm::StringRef
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.
auto sText = Lexer::getSourceText(CharSourceRange::getTokenRange(CastExpr->getLParenLoc().getLocWithOffset(1), | ||
CastExpr->getRParenLoc().getLocWithOffset(-1)), sManager, LangOptions()); | ||
|
||
const auto *mesneExpr = CastExpr->getSubExprAsWritten()->IgnoreImpCasts(); |
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 why you are using here getSubExprAsWritten()
and IgnoreImpCasts()
.
What would be the difference with the use of getSubExprAsWritten()->IgnoreImpCasts()
, getSubExpr()->IgnoreImpCasts()
and getSubExprAsWritten()
?
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()
получает подвыражение приведения в том виде, в каком оно было записано в исходном коде, просматривая любые неявные приведения или другие промежуточные узлы, введенные семантическим анализом. Затем используется IgnoreImpCasts()
для того, чтобы игнорировать любые неявные приведения типов, которые могут окружать это выражение.
У нас есть test.cpp
. Запуская код из файла, можно заметить, что не будет иметь значения, будем ли мы использовать getSubExprAsWritten()
с/без IgnoreImpCasts(). getSubExprAsWritten()->IgnoreImpCasts()
, так как getSubExpr()->IgnoreImpCasts()
и getSubExprAsWritten()
дадут нам один и тот же результат.
Чтобы продемонстрировать это более наглядно, давайте запустим следующее:
llvm::outs() << "getSubExprAsWritten()->IgnoreImpCasts(): " << castNode->getSubExprAsWritten()->IgnoreImpCasts()->getStmtClassName();
llvm::outs() << "getSubExpr()->ignoreImpCasts(): " << castNode->getSubExpr()->IgnoreImpCasts()->getStmtClassName();
llvm::outs() << "getSubExprAsWritten(): " << castNode->getSubExprAsWritten()->getStmtClassName();
Получаем такой результат. На выходе будет ImplicitCastExpr
, так как getSubExpr()
извлекает первое подвыражение приведения.:
getSubExprAsWritten()->IgnoreImpCasts(): DeclRefExpr
getSubExpr()->ignoreImpCasts(): DeclRefExpr
getSubExprAsWritten(): DeclRefExpr
Please provide code examples. |
Для предотвращения возникновения нежеланных скобок можно использовать в нашем исходном выражении
Для ответа на второй вопроса мы можем поместить переменную в выражение
или
Для предотвращения изменения кода в макросах мы добавляем проверку:
|
|
Для подавления таких предупреждений часто помещают переменную в выражение |
|
Я имел в виду использование метода в условии, а не сам метод. Сам по себе метод |
I still don't understand what you want to use in your solution to prevent changing a C style cast to a C++ style cast for cases like this. Please update the code. |
Добавил |
No description provided.