brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.9 KiB · 2627813 Raw
141 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ASTUtils.h"10 11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/ASTMatchers/ASTMatchers.h"13#include "clang/Lex/Lexer.h"14 15namespace clang::tidy::utils {16using namespace ast_matchers;17 18const FunctionDecl *getSurroundingFunction(ASTContext &Context,19                                           const Stmt &Statement) {20  return selectFirst<const FunctionDecl>(21      "function", match(stmt(hasAncestor(functionDecl().bind("function"))),22                        Statement, Context));23}24 25bool isBinaryOrTernary(const Expr *E) {26  const Expr *EBase = E->IgnoreImpCasts();27  if (isa<BinaryOperator>(EBase) || isa<ConditionalOperator>(EBase)) {28    return true;29  }30 31  if (const auto *Operator = dyn_cast<CXXOperatorCallExpr>(EBase)) {32    return Operator->isInfixBinaryOp();33  }34 35  return false;36}37 38bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM,39                                const LangOptions &LangOpts,40                                StringRef FlagName) {41  // If the Flag is an integer constant, check it.42  if (isa<IntegerLiteral>(Flags)) {43    if (!SM.isMacroBodyExpansion(Flags->getBeginLoc()) &&44        !SM.isMacroArgExpansion(Flags->getBeginLoc()))45      return false;46 47    // Get the macro name.48    auto MacroName = Lexer::getSourceText(49        CharSourceRange::getTokenRange(Flags->getSourceRange()), SM, LangOpts);50 51    return MacroName == FlagName;52  }53  // If it's a binary OR operation.54  if (const auto *BO = dyn_cast<BinaryOperator>(Flags))55    if (BO->getOpcode() == BinaryOperatorKind::BO_Or)56      return exprHasBitFlagWithSpelling(BO->getLHS()->IgnoreParenCasts(), SM,57                                        LangOpts, FlagName) ||58             exprHasBitFlagWithSpelling(BO->getRHS()->IgnoreParenCasts(), SM,59                                        LangOpts, FlagName);60 61  // Otherwise, assume it has the flag.62  return true;63}64 65bool rangeIsEntirelyWithinMacroArgument(SourceRange Range,66                                        const SourceManager *SM) {67  // Check if the range is entirely contained within a macro argument.68  SourceLocation MacroArgExpansionStartForRangeBegin;69  SourceLocation MacroArgExpansionStartForRangeEnd;70  const bool RangeIsEntirelyWithinMacroArgument =71      SM &&72      SM->isMacroArgExpansion(Range.getBegin(),73                              &MacroArgExpansionStartForRangeBegin) &&74      SM->isMacroArgExpansion(Range.getEnd(),75                              &MacroArgExpansionStartForRangeEnd) &&76      MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd;77 78  return RangeIsEntirelyWithinMacroArgument;79}80 81bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM) {82  return rangeIsEntirelyWithinMacroArgument(Range, SM) ||83         Range.getBegin().isMacroID() || Range.getEnd().isMacroID();84}85 86bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM) {87  return utils::rangeIsEntirelyWithinMacroArgument(Range, SM) ||88         !utils::rangeContainsMacroExpansion(Range, SM);89}90 91bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt,92                            const ASTContext &Context, bool Canonical) {93  if (!FirstStmt || !SecondStmt)94    return false;95 96  if (FirstStmt == SecondStmt)97    return true;98 99  if (FirstStmt->getStmtClass() != SecondStmt->getStmtClass())100    return false;101 102  if (isa<Expr>(FirstStmt) && isa<Expr>(SecondStmt)) {103    // If we have errors in expressions, we will be unable104    // to accurately profile and compute hashes for each statements.105    if (llvm::cast<Expr>(FirstStmt)->containsErrors() ||106        llvm::cast<Expr>(SecondStmt)->containsErrors())107      return false;108  }109 110  llvm::FoldingSetNodeID DataFirst, DataSecond;111  FirstStmt->Profile(DataFirst, Context, Canonical);112  SecondStmt->Profile(DataSecond, Context, Canonical);113  return DataFirst == DataSecond;114}115 116const IndirectFieldDecl *117findOutermostIndirectFieldDeclForField(const FieldDecl *FD) {118  const RecordDecl *Record = FD->getParent();119  assert(Record->isAnonymousStructOrUnion() &&120         "FD must be a field in an anonymous record");121 122  const DeclContext *Context = Record;123  while (isa<RecordDecl>(Context) &&124         cast<RecordDecl>(Context)->isAnonymousStructOrUnion()) {125    Context = Context->getParent();126  }127 128  // Search for the target IndirectFieldDecl within the located context.129  for (const auto *D : Context->decls()) {130    const auto *IFD = dyn_cast<IndirectFieldDecl>(D);131    if (!IFD)132      continue;133    if (IFD->getAnonField() == FD)134      return IFD;135  }136 137  return nullptr;138}139 140} // namespace clang::tidy::utils141