2016-10-17 16:33:59 +08:00
|
|
|
//===---------- ASTUtils.cpp - clang-tidy ---------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2016-10-17 16:33:59 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ASTUtils.h"
|
|
|
|
|
|
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
|
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
2017-07-13 01:43:36 +08:00
|
|
|
#include "clang/Lex/Lexer.h"
|
2016-10-17 16:33:59 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace tidy {
|
|
|
|
namespace utils {
|
|
|
|
using namespace ast_matchers;
|
|
|
|
|
|
|
|
const FunctionDecl *getSurroundingFunction(ASTContext &Context,
|
|
|
|
const Stmt &Statement) {
|
|
|
|
return selectFirst<const FunctionDecl>(
|
|
|
|
"function", match(stmt(hasAncestor(functionDecl().bind("function"))),
|
|
|
|
Statement, Context));
|
|
|
|
}
|
2017-04-24 22:57:09 +08:00
|
|
|
|
|
|
|
bool IsBinaryOrTernary(const Expr *E) {
|
2021-01-29 07:49:53 +08:00
|
|
|
const Expr *EBase = E->IgnoreImpCasts();
|
|
|
|
if (isa<BinaryOperator>(EBase) || isa<ConditionalOperator>(EBase)) {
|
2017-04-24 22:57:09 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-01-29 07:49:53 +08:00
|
|
|
if (const auto *Operator = dyn_cast<CXXOperatorCallExpr>(EBase)) {
|
2017-04-24 22:57:09 +08:00
|
|
|
return Operator->isInfixBinaryOp();
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-07-13 01:43:36 +08:00
|
|
|
bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM,
|
|
|
|
const LangOptions &LangOpts,
|
|
|
|
StringRef FlagName) {
|
|
|
|
// If the Flag is an integer constant, check it.
|
|
|
|
if (isa<IntegerLiteral>(Flags)) {
|
2018-08-10 06:42:26 +08:00
|
|
|
if (!SM.isMacroBodyExpansion(Flags->getBeginLoc()) &&
|
|
|
|
!SM.isMacroArgExpansion(Flags->getBeginLoc()))
|
2017-07-13 01:43:36 +08:00
|
|
|
return false;
|
|
|
|
|
2018-02-02 21:39:07 +08:00
|
|
|
// Get the macro name.
|
2017-07-13 01:43:36 +08:00
|
|
|
auto MacroName = Lexer::getSourceText(
|
|
|
|
CharSourceRange::getTokenRange(Flags->getSourceRange()), SM, LangOpts);
|
|
|
|
|
|
|
|
return MacroName == FlagName;
|
|
|
|
}
|
|
|
|
// If it's a binary OR operation.
|
|
|
|
if (const auto *BO = dyn_cast<BinaryOperator>(Flags))
|
2021-01-29 07:49:53 +08:00
|
|
|
if (BO->getOpcode() == BinaryOperatorKind::BO_Or)
|
2017-07-13 01:43:36 +08:00
|
|
|
return exprHasBitFlagWithSpelling(BO->getLHS()->IgnoreParenCasts(), SM,
|
|
|
|
LangOpts, FlagName) ||
|
|
|
|
exprHasBitFlagWithSpelling(BO->getRHS()->IgnoreParenCasts(), SM,
|
|
|
|
LangOpts, FlagName);
|
|
|
|
|
|
|
|
// Otherwise, assume it has the flag.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
[clang-tidy] Re-commit: Add new 'readability-uppercase-literal-suffix' check (CERT DCL16-C, MISRA C:2012, 7.3, MISRA C++:2008, 2-13-4)
Summary:
Detects when the integral literal or floating point (decimal or hexadecimal)
literal has non-uppercase suffix, and suggests to make the suffix uppercase,
with fix-it.
All valid combinations of suffixes are supported.
```
auto x = 1; // OK, no suffix.
auto x = 1u; // warning: integer literal suffix 'u' is not upper-case
auto x = 1U; // OK, suffix is uppercase.
...
```
This is a re-commit, the original was reverted by me in
rL345305 due to discovered bugs. (implicit code, template instantiation)
Tests were added, and the bugs were fixed.
I'm unable to find any further bugs, hopefully there aren't any..
References:
* [[ https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152241 | CERT DCL16-C ]]
* MISRA C:2012, 7.3 - The lowercase character "l" shall not be used in a literal suffix
* MISRA C++:2008, 2-13-4 - Literal suffixes shall be upper case
Reviewers: JonasToth, aaron.ballman, alexfh, hokein, xazax.hun
Reviewed By: aaron.ballman
Subscribers: Eugene.Zelenko, mgorny, rnkovacs, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D52670
llvm-svn: 345381
2018-10-26 21:09:27 +08:00
|
|
|
bool rangeIsEntirelyWithinMacroArgument(SourceRange Range,
|
|
|
|
const SourceManager *SM) {
|
|
|
|
// Check if the range is entirely contained within a macro argument.
|
|
|
|
SourceLocation MacroArgExpansionStartForRangeBegin;
|
|
|
|
SourceLocation MacroArgExpansionStartForRangeEnd;
|
|
|
|
bool RangeIsEntirelyWithinMacroArgument =
|
|
|
|
SM &&
|
|
|
|
SM->isMacroArgExpansion(Range.getBegin(),
|
|
|
|
&MacroArgExpansionStartForRangeBegin) &&
|
|
|
|
SM->isMacroArgExpansion(Range.getEnd(),
|
|
|
|
&MacroArgExpansionStartForRangeEnd) &&
|
|
|
|
MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd;
|
|
|
|
|
|
|
|
return RangeIsEntirelyWithinMacroArgument;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM) {
|
|
|
|
return rangeIsEntirelyWithinMacroArgument(Range, SM) ||
|
|
|
|
Range.getBegin().isMacroID() || Range.getEnd().isMacroID();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM) {
|
|
|
|
return utils::rangeIsEntirelyWithinMacroArgument(Range, SM) ||
|
|
|
|
!utils::rangeContainsMacroExpansion(Range, SM);
|
|
|
|
}
|
|
|
|
|
2016-10-17 16:33:59 +08:00
|
|
|
} // namespace utils
|
|
|
|
} // namespace tidy
|
|
|
|
} // namespace clang
|