11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/ASTMatchers/ASTMatchers.h"
13#include "clang/Lex/Lexer.h"
16using namespace ast_matchers;
19 const Stmt &Statement) {
20 return selectFirst<const FunctionDecl>(
21 "function", match(stmt(hasAncestor(functionDecl().bind(
"function"))),
26 const Expr *EBase = E->IgnoreImpCasts();
27 if (isa<BinaryOperator>(EBase) || isa<ConditionalOperator>(EBase))
30 if (
const auto *Operator = dyn_cast<CXXOperatorCallExpr>(EBase))
31 return Operator->isInfixBinaryOp();
37 const LangOptions &LangOpts,
40 if (isa<IntegerLiteral>(Flags)) {
41 if (!SM.isMacroBodyExpansion(Flags->getBeginLoc()) &&
42 !SM.isMacroArgExpansion(Flags->getBeginLoc()))
46 auto MacroName = Lexer::getSourceText(
47 CharSourceRange::getTokenRange(Flags->getSourceRange()), SM, LangOpts);
49 return MacroName == FlagName;
52 if (
const auto *BO = dyn_cast<BinaryOperator>(Flags))
53 if (BO->getOpcode() == BinaryOperatorKind::BO_Or)
55 LangOpts, FlagName) ||
64 const SourceManager *SM) {
66 SourceLocation MacroArgExpansionStartForRangeBegin;
67 SourceLocation MacroArgExpansionStartForRangeEnd;
68 const bool RangeIsEntirelyWithinMacroArgument =
70 SM->isMacroArgExpansion(Range.getBegin(),
71 &MacroArgExpansionStartForRangeBegin) &&
72 SM->isMacroArgExpansion(Range.getEnd(),
73 &MacroArgExpansionStartForRangeEnd) &&
74 MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd;
76 return RangeIsEntirelyWithinMacroArgument;
81 Range.getBegin().isMacroID() || Range.getEnd().isMacroID();
90 const ASTContext &Context,
bool Canonical) {
91 if (!FirstStmt || !SecondStmt)
94 if (FirstStmt == SecondStmt)
97 if (FirstStmt->getStmtClass() != SecondStmt->getStmtClass())
100 if (isa<Expr>(FirstStmt) && isa<Expr>(SecondStmt)) {
103 if (llvm::cast<Expr>(FirstStmt)->containsErrors() ||
104 llvm::cast<Expr>(SecondStmt)->containsErrors())
108 llvm::FoldingSetNodeID DataFirst, DataSecond;
109 FirstStmt->Profile(DataFirst, Context, Canonical);
110 SecondStmt->Profile(DataSecond, Context, Canonical);
111 return DataFirst == DataSecond;
114const IndirectFieldDecl *
116 const RecordDecl *Record = FD->getParent();
117 assert(Record->isAnonymousStructOrUnion() &&
118 "FD must be a field in an anonymous record");
120 const DeclContext *Context = Record;
121 while (isa<RecordDecl>(Context) &&
122 cast<RecordDecl>(Context)->isAnonymousStructOrUnion()) {
123 Context = Context->getParent();
127 for (
const auto *D : Context->decls()) {
128 const auto *IFD = dyn_cast<IndirectFieldDecl>(D);
131 if (IFD->getAnonField() == FD)
bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM)
bool isBinaryOrTernary(const Expr *E)
bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM)
bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt, const ASTContext &Context, bool Canonical)
bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM, const LangOptions &LangOpts, StringRef FlagName)
Checks whether a macro flag is present in the given argument.
const IndirectFieldDecl * findOutermostIndirectFieldDeclForField(const FieldDecl *FD)
bool rangeIsEntirelyWithinMacroArgument(SourceRange Range, const SourceManager *SM)
const FunctionDecl * getSurroundingFunction(ASTContext &Context, const Stmt &Statement)