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)) {
31 if (
const auto *Operator = dyn_cast<CXXOperatorCallExpr>(EBase)) {
32 return Operator->isInfixBinaryOp();
39 const LangOptions &LangOpts,
42 if (isa<IntegerLiteral>(
Flags)) {
43 if (!SM.isMacroBodyExpansion(
Flags->getBeginLoc()) &&
44 !SM.isMacroArgExpansion(
Flags->getBeginLoc()))
49 CharSourceRange::getTokenRange(
Flags->getSourceRange()), SM, LangOpts);
54 if (
const auto *BO = dyn_cast<BinaryOperator>(
Flags))
55 if (BO->getOpcode() == BinaryOperatorKind::BO_Or)
57 LangOpts, FlagName) ||
66 const SourceManager *SM) {
68 SourceLocation MacroArgExpansionStartForRangeBegin;
69 SourceLocation MacroArgExpansionStartForRangeEnd;
70 bool RangeIsEntirelyWithinMacroArgument =
72 SM->isMacroArgExpansion(
Range.getBegin(),
73 &MacroArgExpansionStartForRangeBegin) &&
74 SM->isMacroArgExpansion(
Range.getEnd(),
75 &MacroArgExpansionStartForRangeEnd) &&
76 MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd;
78 return RangeIsEntirelyWithinMacroArgument;
83 Range.getBegin().isMacroID() ||
Range.getEnd().isMacroID();
92 const ASTContext &Context,
bool Canonical) {
93 if (!FirstStmt || !SecondStmt)
96 if (FirstStmt == SecondStmt)
99 if (FirstStmt->getStmtClass() != SecondStmt->getStmtClass())
102 if (isa<Expr>(FirstStmt) && isa<Expr>(SecondStmt)) {
105 if (llvm::cast<Expr>(FirstStmt)->containsErrors() ||
106 llvm::cast<Expr>(SecondStmt)->containsErrors())
110 llvm::FoldingSetNodeID DataFirst, DataSecond;
111 FirstStmt->Profile(DataFirst, Context, Canonical);
112 SecondStmt->Profile(DataSecond, Context, Canonical);
113 return DataFirst == DataSecond;
116const IndirectFieldDecl *
118 const RecordDecl *Record = FD->getParent();
119 assert(Record->isAnonymousStructOrUnion() &&
120 "FD must be a field in an anonymous record");
122 const DeclContext *Context = Record;
123 while (isa<RecordDecl>(Context) &&
124 cast<RecordDecl>(Context)->isAnonymousStructOrUnion()) {
125 Context = Context->getParent();
129 for (
const auto *D : Context->decls()) {
130 const auto *IFD = dyn_cast<IndirectFieldDecl>(D);
133 if (IFD->getAnonField() == FD)
CharSourceRange Range
SourceRange for the file name.
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)