//===- SemaChecking.cpp - Extra Semantic Checking -------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//  This file implements extra semantic analysis beyond what is enforced
//  by the C type system.
//
//===----------------------------------------------------------------------===//

#include "CheckExprLifetime.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/Attr.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/FormatString.h"
#include "clang/AST/IgnoreExpr.h"
#include "clang/AST/NSAPI.h"
#include "clang/AST/NonTrivialTypeVisitor.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/SyncScope.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TypeTraits.h"
#include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Ownership.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Sema/SemaARM.h"
#include "clang/Sema/SemaBPF.h"
#include "clang/Sema/SemaDirectX.h"
#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaHexagon.h"
#include "clang/Sema/SemaLoongArch.h"
#include "clang/Sema/SemaMIPS.h"
#include "clang/Sema/SemaNVPTX.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenCL.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Locale.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <limits>
#include <optional>
#include <string>
#include <tuple>
#include <utility>

using namespace clang;
using namespace sema;

SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL,
                                                    unsigned ByteNo) const {
  return SL->getLocationOfByte(ByteNo, getSourceManager(), LangOpts,
                               Context.getTargetInfo());
}

static constexpr unsigned short combineFAPK(Sema::FormatArgumentPassingKind A,
                                            Sema::FormatArgumentPassingKind B) {
  return (A << 8) | B;
}

bool Sema::checkArgCountAtLeast(CallExpr *Call, unsigned MinArgCount) {
  unsigned ArgCount = Call->getNumArgs();
  if (ArgCount >= MinArgCount)
    return false;

  return Diag(Call->getEndLoc(), diag::err_typecheck_call_too_few_args)
         << 0 /*function call*/ << MinArgCount << ArgCount
         << /*is non object*/ 0 << Call->getSourceRange();
}

bool Sema::checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount) {
  unsigned ArgCount = Call->getNumArgs();
  if (ArgCount <= MaxArgCount)
    return false;
  return Diag(Call->getEndLoc(), diag::err_typecheck_call_too_many_args_at_most)
         << 0 /*function call*/ << MaxArgCount << ArgCount
         << /*is non object*/ 0 << Call->getSourceRange();
}

bool Sema::checkArgCountRange(CallExpr *Call, unsigned MinArgCount,
                              unsigned MaxArgCount) {
  return checkArgCountAtLeast(Call, MinArgCount) ||
         checkArgCountAtMost(Call, MaxArgCount);
}

bool Sema::checkArgCount(CallExpr *Call, unsigned DesiredArgCount) {
  unsigned ArgCount = Call->getNumArgs();
  if (ArgCount == DesiredArgCount)
    return false;

  if (checkArgCountAtLeast(Call, DesiredArgCount))
    return true;
  assert(ArgCount > DesiredArgCount && "should have diagnosed this");

  // Highlight all the excess arguments.
  SourceRange Range(Call->getArg(DesiredArgCount)->getBeginLoc(),
                    Call->getArg(ArgCount - 1)->getEndLoc());

  return Diag(Range.getBegin(), diag::err_typecheck_call_too_many_args)
         << 0 /*function call*/ << DesiredArgCount << ArgCount
         << /*is non object*/ 0 << Range;
}

static bool checkBuiltinVerboseTrap(CallExpr *Call, Sema &S) {
  bool HasError = false;

  for (unsigned I = 0; I < Call->getNumArgs(); ++I) {
    Expr *Arg = Call->getArg(I);

    if (Arg->isValueDependent())
      continue;

    std::optional<std::string> ArgString = Arg->tryEvaluateString(S.Context);
    int DiagMsgKind = -1;
    // Arguments must be pointers to constant strings and cannot use '$'.
    if (!ArgString.has_value())
      DiagMsgKind = 0;
    else if (ArgString->find('$') != std::string::npos)
      DiagMsgKind = 1;

    if (DiagMsgKind >= 0) {
      S.Diag(Arg->getBeginLoc(), diag::err_builtin_verbose_trap_arg)
          << DiagMsgKind << Arg->getSourceRange();
      HasError = true;
    }
  }

  return !HasError;
}

static bool convertArgumentToType(Sema &S, Expr *&Value, QualType Ty) {
  if (Value->isTypeDependent())
    return false;

  InitializedEntity Entity =
      InitializedEntity::InitializeParameter(S.Context, Ty, false);
  ExprResult Result =
      S.PerformCopyInitialization(Entity, SourceLocation(), Value);
  if (Result.isInvalid())
    return true;
  Value = Result.get();
  return false;
}

/// Check that the first argument to __builtin_annotation is an integer
/// and the second argument is a non-wide string literal.
static bool BuiltinAnnotation(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 2))
    return true;

  // First argument should be an integer.
  Expr *ValArg = TheCall->getArg(0);
  QualType Ty = ValArg->getType();
  if (!Ty->isIntegerType()) {
    S.Diag(ValArg->getBeginLoc(), diag::err_builtin_annotation_first_arg)
        << ValArg->getSourceRange();
    return true;
  }

  // Second argument should be a constant string.
  Expr *StrArg = TheCall->getArg(1)->IgnoreParenCasts();
  StringLiteral *Literal = dyn_cast<StringLiteral>(StrArg);
  if (!Literal || !Literal->isOrdinary()) {
    S.Diag(StrArg->getBeginLoc(), diag::err_builtin_annotation_second_arg)
        << StrArg->getSourceRange();
    return true;
  }

  TheCall->setType(Ty);
  return false;
}

static bool BuiltinMSVCAnnotation(Sema &S, CallExpr *TheCall) {
  // We need at least one argument.
  if (TheCall->getNumArgs() < 1) {
    S.Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
        << 0 << 1 << TheCall->getNumArgs() << /*is non object*/ 0
        << TheCall->getCallee()->getSourceRange();
    return true;
  }

  // All arguments should be wide string literals.
  for (Expr *Arg : TheCall->arguments()) {
    auto *Literal = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts());
    if (!Literal || !Literal->isWide()) {
      S.Diag(Arg->getBeginLoc(), diag::err_msvc_annotation_wide_str)
          << Arg->getSourceRange();
      return true;
    }
  }

  return false;
}

/// Check that the argument to __builtin_addressof is a glvalue, and set the
/// result type to the corresponding pointer type.
static bool BuiltinAddressof(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 1))
    return true;

  ExprResult Arg(TheCall->getArg(0));
  QualType ResultType = S.CheckAddressOfOperand(Arg, TheCall->getBeginLoc());
  if (ResultType.isNull())
    return true;

  TheCall->setArg(0, Arg.get());
  TheCall->setType(ResultType);
  return false;
}

/// Check that the argument to __builtin_function_start is a function.
static bool BuiltinFunctionStart(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 1))
    return true;

  ExprResult Arg = S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
  if (Arg.isInvalid())
    return true;

  TheCall->setArg(0, Arg.get());
  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(
      Arg.get()->getAsBuiltinConstantDeclRef(S.getASTContext()));

  if (!FD) {
    S.Diag(TheCall->getBeginLoc(), diag::err_function_start_invalid_type)
        << TheCall->getSourceRange();
    return true;
  }

  return !S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
                                              TheCall->getBeginLoc());
}

/// Check the number of arguments and set the result type to
/// the argument type.
static bool BuiltinPreserveAI(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 1))
    return true;

  TheCall->setType(TheCall->getArg(0)->getType());
  return false;
}

/// Check that the value argument for __builtin_is_aligned(value, alignment) and
/// __builtin_aligned_{up,down}(value, alignment) is an integer or a pointer
/// type (but not a function pointer) and that the alignment is a power-of-two.
static bool BuiltinAlignment(Sema &S, CallExpr *TheCall, unsigned ID) {
  if (S.checkArgCount(TheCall, 2))
    return true;

  clang::Expr *Source = TheCall->getArg(0);
  bool IsBooleanAlignBuiltin = ID == Builtin::BI__builtin_is_aligned;

  auto IsValidIntegerType = [](QualType Ty) {
    return Ty->isIntegerType() && !Ty->isEnumeralType() && !Ty->isBooleanType();
  };
  QualType SrcTy = Source->getType();
  // We should also be able to use it with arrays (but not functions!).
  if (SrcTy->canDecayToPointerType() && SrcTy->isArrayType()) {
    SrcTy = S.Context.getDecayedType(SrcTy);
  }
  if ((!SrcTy->isPointerType() && !IsValidIntegerType(SrcTy)) ||
      SrcTy->isFunctionPointerType()) {
    // FIXME: this is not quite the right error message since we don't allow
    // floating point types, or member pointers.
    S.Diag(Source->getExprLoc(), diag::err_typecheck_expect_scalar_operand)
        << SrcTy;
    return true;
  }

  clang::Expr *AlignOp = TheCall->getArg(1);
  if (!IsValidIntegerType(AlignOp->getType())) {
    S.Diag(AlignOp->getExprLoc(), diag::err_typecheck_expect_int)
        << AlignOp->getType();
    return true;
  }
  Expr::EvalResult AlignResult;
  unsigned MaxAlignmentBits = S.Context.getIntWidth(SrcTy) - 1;
  // We can't check validity of alignment if it is value dependent.
  if (!AlignOp->isValueDependent() &&
      AlignOp->EvaluateAsInt(AlignResult, S.Context,
                             Expr::SE_AllowSideEffects)) {
    llvm::APSInt AlignValue = AlignResult.Val.getInt();
    llvm::APSInt MaxValue(
        llvm::APInt::getOneBitSet(MaxAlignmentBits + 1, MaxAlignmentBits));
    if (AlignValue < 1) {
      S.Diag(AlignOp->getExprLoc(), diag::err_alignment_too_small) << 1;
      return true;
    }
    if (llvm::APSInt::compareValues(AlignValue, MaxValue) > 0) {
      S.Diag(AlignOp->getExprLoc(), diag::err_alignment_too_big)
          << toString(MaxValue, 10);
      return true;
    }
    if (!AlignValue.isPowerOf2()) {
      S.Diag(AlignOp->getExprLoc(), diag::err_alignment_not_power_of_two);
      return true;
    }
    if (AlignValue == 1) {
      S.Diag(AlignOp->getExprLoc(), diag::warn_alignment_builtin_useless)
          << IsBooleanAlignBuiltin;
    }
  }

  ExprResult SrcArg = S.PerformCopyInitialization(
      InitializedEntity::InitializeParameter(S.Context, SrcTy, false),
      SourceLocation(), Source);
  if (SrcArg.isInvalid())
    return true;
  TheCall->setArg(0, SrcArg.get());
  ExprResult AlignArg =
      S.PerformCopyInitialization(InitializedEntity::InitializeParameter(
                                      S.Context, AlignOp->getType(), false),
                                  SourceLocation(), AlignOp);
  if (AlignArg.isInvalid())
    return true;
  TheCall->setArg(1, AlignArg.get());
  // For align_up/align_down, the return type is the same as the (potentially
  // decayed) argument type including qualifiers. For is_aligned(), the result
  // is always bool.
  TheCall->setType(IsBooleanAlignBuiltin ? S.Context.BoolTy : SrcTy);
  return false;
}

static bool BuiltinOverflow(Sema &S, CallExpr *TheCall, unsigned BuiltinID) {
  if (S.checkArgCount(TheCall, 3))
    return true;

  std::pair<unsigned, const char *> Builtins[] = {
    { Builtin::BI__builtin_add_overflow, "ckd_add" },
    { Builtin::BI__builtin_sub_overflow, "ckd_sub" },
    { Builtin::BI__builtin_mul_overflow, "ckd_mul" },
  };

  bool CkdOperation = llvm::any_of(Builtins, [&](const std::pair<unsigned,
    const char *> &P) {
    return BuiltinID == P.first && TheCall->getExprLoc().isMacroID() &&
         Lexer::getImmediateMacroName(TheCall->getExprLoc(),
         S.getSourceManager(), S.getLangOpts()) == P.second;
  });

  auto ValidCkdIntType = [](QualType QT) {
    // A valid checked integer type is an integer type other than a plain char,
    // bool, a bit-precise type, or an enumeration type.
    if (const auto *BT = QT.getCanonicalType()->getAs<BuiltinType>())
      return (BT->getKind() >= BuiltinType::Short &&
           BT->getKind() <= BuiltinType::Int128) || (
           BT->getKind() >= BuiltinType::UShort &&
           BT->getKind() <= BuiltinType::UInt128) ||
           BT->getKind() == BuiltinType::UChar ||
           BT->getKind() == BuiltinType::SChar;
    return false;
  };

  // First two arguments should be integers.
  for (unsigned I = 0; I < 2; ++I) {
    ExprResult Arg = S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(I));
    if (Arg.isInvalid()) return true;
    TheCall->setArg(I, Arg.get());

    QualType Ty = Arg.get()->getType();
    bool IsValid = CkdOperation ? ValidCkdIntType(Ty) : Ty->isIntegerType();
    if (!IsValid) {
      S.Diag(Arg.get()->getBeginLoc(), diag::err_overflow_builtin_must_be_int)
          << CkdOperation << Ty << Arg.get()->getSourceRange();
      return true;
    }
  }

  // Third argument should be a pointer to a non-const integer.
  // IRGen correctly handles volatile, restrict, and address spaces, and
  // the other qualifiers aren't possible.
  {
    ExprResult Arg = S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(2));
    if (Arg.isInvalid()) return true;
    TheCall->setArg(2, Arg.get());

    QualType Ty = Arg.get()->getType();
    const auto *PtrTy = Ty->getAs<PointerType>();
    if (!PtrTy ||
        !PtrTy->getPointeeType()->isIntegerType() ||
        (!ValidCkdIntType(PtrTy->getPointeeType()) && CkdOperation) ||
        PtrTy->getPointeeType().isConstQualified()) {
      S.Diag(Arg.get()->getBeginLoc(),
             diag::err_overflow_builtin_must_be_ptr_int)
        << CkdOperation << Ty << Arg.get()->getSourceRange();
      return true;
    }
  }

  // Disallow signed bit-precise integer args larger than 128 bits to mul
  // function until we improve backend support.
  if (BuiltinID == Builtin::BI__builtin_mul_overflow) {
    for (unsigned I = 0; I < 3; ++I) {
      const auto Arg = TheCall->getArg(I);
      // Third argument will be a pointer.
      auto Ty = I < 2 ? Arg->getType() : Arg->getType()->getPointeeType();
      if (Ty->isBitIntType() && Ty->isSignedIntegerType() &&
          S.getASTContext().getIntWidth(Ty) > 128)
        return S.Diag(Arg->getBeginLoc(),
                      diag::err_overflow_builtin_bit_int_max_size)
               << 128;
    }
  }

  return false;
}

namespace {
struct BuiltinDumpStructGenerator {
  Sema &S;
  CallExpr *TheCall;
  SourceLocation Loc = TheCall->getBeginLoc();
  SmallVector<Expr *, 32> Actions;
  DiagnosticErrorTrap ErrorTracker;
  PrintingPolicy Policy;

  BuiltinDumpStructGenerator(Sema &S, CallExpr *TheCall)
      : S(S), TheCall(TheCall), ErrorTracker(S.getDiagnostics()),
        Policy(S.Context.getPrintingPolicy()) {
    Policy.AnonymousTagLocations = false;
  }

  Expr *makeOpaqueValueExpr(Expr *Inner) {
    auto *OVE = new (S.Context)
        OpaqueValueExpr(Loc, Inner->getType(), Inner->getValueKind(),
                        Inner->getObjectKind(), Inner);
    Actions.push_back(OVE);
    return OVE;
  }

  Expr *getStringLiteral(llvm::StringRef Str) {
    Expr *Lit = S.Context.getPredefinedStringLiteralFromCache(Str);
    // Wrap the literal in parentheses to attach a source location.
    return new (S.Context) ParenExpr(Loc, Loc, Lit);
  }

  bool callPrintFunction(llvm::StringRef Format,
                         llvm::ArrayRef<Expr *> Exprs = {}) {
    SmallVector<Expr *, 8> Args;
    assert(TheCall->getNumArgs() >= 2);
    Args.reserve((TheCall->getNumArgs() - 2) + /*Format*/ 1 + Exprs.size());
    Args.assign(TheCall->arg_begin() + 2, TheCall->arg_end());
    Args.push_back(getStringLiteral(Format));
    llvm::append_range(Args, Exprs);

    // Register a note to explain why we're performing the call.
    Sema::CodeSynthesisContext Ctx;
    Ctx.Kind = Sema::CodeSynthesisContext::BuildingBuiltinDumpStructCall;
    Ctx.PointOfInstantiation = Loc;
    Ctx.CallArgs = Args.data();
    Ctx.NumCallArgs = Args.size();
    S.pushCodeSynthesisContext(Ctx);

    ExprResult RealCall =
        S.BuildCallExpr(/*Scope=*/nullptr, TheCall->getArg(1),
                        TheCall->getBeginLoc(), Args, TheCall->getRParenLoc());

    S.popCodeSynthesisContext();
    if (!RealCall.isInvalid())
      Actions.push_back(RealCall.get());
    // Bail out if we've hit any errors, even if we managed to build the
    // call. We don't want to produce more than one error.
    return RealCall.isInvalid() || ErrorTracker.hasErrorOccurred();
  }

  Expr *getIndentString(unsigned Depth) {
    if (!Depth)
      return nullptr;

    llvm::SmallString<32> Indent;
    Indent.resize(Depth * Policy.Indentation, ' ');
    return getStringLiteral(Indent);
  }

  Expr *getTypeString(QualType T) {
    return getStringLiteral(T.getAsString(Policy));
  }

  bool appendFormatSpecifier(QualType T, llvm::SmallVectorImpl<char> &Str) {
    llvm::raw_svector_ostream OS(Str);

    // Format 'bool', 'char', 'signed char', 'unsigned char' as numbers, rather
    // than trying to print a single character.
    if (auto *BT = T->getAs<BuiltinType>()) {
      switch (BT->getKind()) {
      case BuiltinType::Bool:
        OS << "%d";
        return true;
      case BuiltinType::Char_U:
      case BuiltinType::UChar:
        OS << "%hhu";
        return true;
      case BuiltinType::Char_S:
      case BuiltinType::SChar:
        OS << "%hhd";
        return true;
      default:
        break;
      }
    }

    analyze_printf::PrintfSpecifier Specifier;
    if (Specifier.fixType(T, S.getLangOpts(), S.Context, /*IsObjCLiteral=*/false)) {
      // We were able to guess how to format this.
      if (Specifier.getConversionSpecifier().getKind() ==
          analyze_printf::PrintfConversionSpecifier::sArg) {
        // Wrap double-quotes around a '%s' specifier and limit its maximum
        // length. Ideally we'd also somehow escape special characters in the
        // contents but printf doesn't support that.
        // FIXME: '%s' formatting is not safe in general.
        OS << '"';
        Specifier.setPrecision(analyze_printf::OptionalAmount(32u));
        Specifier.toString(OS);
        OS << '"';
        // FIXME: It would be nice to include a '...' if the string doesn't fit
        // in the length limit.
      } else {
        Specifier.toString(OS);
      }
      return true;
    }

    if (T->isPointerType()) {
      // Format all pointers with '%p'.
      OS << "%p";
      return true;
    }

    return false;
  }

  bool dumpUnnamedRecord(const RecordDecl *RD, Expr *E, unsigned Depth) {
    Expr *IndentLit = getIndentString(Depth);
    Expr *TypeLit = getTypeString(S.Context.getRecordType(RD));
    if (IndentLit ? callPrintFunction("%s%s", {IndentLit, TypeLit})
                  : callPrintFunction("%s", {TypeLit}))
      return true;

    return dumpRecordValue(RD, E, IndentLit, Depth);
  }

  // Dump a record value. E should be a pointer or lvalue referring to an RD.
  bool dumpRecordValue(const RecordDecl *RD, Expr *E, Expr *RecordIndent,
                       unsigned Depth) {
    // FIXME: Decide what to do if RD is a union. At least we should probably
    // turn off printing `const char*` members with `%s`, because that is very
    // likely to crash if that's not the active member. Whatever we decide, we
    // should document it.

    // Build an OpaqueValueExpr so we can refer to E more than once without
    // triggering re-evaluation.
    Expr *RecordArg = makeOpaqueValueExpr(E);
    bool RecordArgIsPtr = RecordArg->getType()->isPointerType();

    if (callPrintFunction(" {\n"))
      return true;

    // Dump each base class, regardless of whether they're aggregates.
    if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
      for (const auto &Base : CXXRD->bases()) {
        QualType BaseType =
            RecordArgIsPtr ? S.Context.getPointerType(Base.getType())
                           : S.Context.getLValueReferenceType(Base.getType());
        ExprResult BasePtr = S.BuildCStyleCastExpr(
            Loc, S.Context.getTrivialTypeSourceInfo(BaseType, Loc), Loc,
            RecordArg);
        if (BasePtr.isInvalid() ||
            dumpUnnamedRecord(Base.getType()->getAsRecordDecl(), BasePtr.get(),
                              Depth + 1))
          return true;
      }
    }

    Expr *FieldIndentArg = getIndentString(Depth + 1);

    // Dump each field.
    for (auto *D : RD->decls()) {
      auto *IFD = dyn_cast<IndirectFieldDecl>(D);
      auto *FD = IFD ? IFD->getAnonField() : dyn_cast<FieldDecl>(D);
      if (!FD || FD->isUnnamedBitField() || FD->isAnonymousStructOrUnion())
        continue;

      llvm::SmallString<20> Format = llvm::StringRef("%s%s %s ");
      llvm::SmallVector<Expr *, 5> Args = {FieldIndentArg,
                                           getTypeString(FD->getType()),
                                           getStringLiteral(FD->getName())};

      if (FD->isBitField()) {
        Format += ": %zu ";
        QualType SizeT = S.Context.getSizeType();
        llvm::APInt BitWidth(S.Context.getIntWidth(SizeT),
                             FD->getBitWidthValue());
        Args.push_back(IntegerLiteral::Create(S.Context, BitWidth, SizeT, Loc));
      }

      Format += "=";

      ExprResult Field =
          IFD ? S.BuildAnonymousStructUnionMemberReference(
                    CXXScopeSpec(), Loc, IFD,
                    DeclAccessPair::make(IFD, AS_public), RecordArg, Loc)
              : S.BuildFieldReferenceExpr(
                    RecordArg, RecordArgIsPtr, Loc, CXXScopeSpec(), FD,
                    DeclAccessPair::make(FD, AS_public),
                    DeclarationNameInfo(FD->getDeclName(), Loc));
      if (Field.isInvalid())
        return true;

      auto *InnerRD = FD->getType()->getAsRecordDecl();
      auto *InnerCXXRD = dyn_cast_or_null<CXXRecordDecl>(InnerRD);
      if (InnerRD && (!InnerCXXRD || InnerCXXRD->isAggregate())) {
        // Recursively print the values of members of aggregate record type.
        if (callPrintFunction(Format, Args) ||
            dumpRecordValue(InnerRD, Field.get(), FieldIndentArg, Depth + 1))
          return true;
      } else {
        Format += " ";
        if (appendFormatSpecifier(FD->getType(), Format)) {
          // We know how to print this field.
          Args.push_back(Field.get());
        } else {
          // We don't know how to print this field. Print out its address
          // with a format specifier that a smart tool will be able to
          // recognize and treat specially.
          Format += "*%p";
          ExprResult FieldAddr =
              S.BuildUnaryOp(nullptr, Loc, UO_AddrOf, Field.get());
          if (FieldAddr.isInvalid())
            return true;
          Args.push_back(FieldAddr.get());
        }
        Format += "\n";
        if (callPrintFunction(Format, Args))
          return true;
      }
    }

    return RecordIndent ? callPrintFunction("%s}\n", RecordIndent)
                        : callPrintFunction("}\n");
  }

  Expr *buildWrapper() {
    auto *Wrapper = PseudoObjectExpr::Create(S.Context, TheCall, Actions,
                                             PseudoObjectExpr::NoResult);
    TheCall->setType(Wrapper->getType());
    TheCall->setValueKind(Wrapper->getValueKind());
    return Wrapper;
  }
};
} // namespace

static ExprResult BuiltinDumpStruct(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCountAtLeast(TheCall, 2))
    return ExprError();

  ExprResult PtrArgResult = S.DefaultLvalueConversion(TheCall->getArg(0));
  if (PtrArgResult.isInvalid())
    return ExprError();
  TheCall->setArg(0, PtrArgResult.get());

  // First argument should be a pointer to a struct.
  QualType PtrArgType = PtrArgResult.get()->getType();
  if (!PtrArgType->isPointerType() ||
      !PtrArgType->getPointeeType()->isRecordType()) {
    S.Diag(PtrArgResult.get()->getBeginLoc(),
           diag::err_expected_struct_pointer_argument)
        << 1 << TheCall->getDirectCallee() << PtrArgType;
    return ExprError();
  }
  QualType Pointee = PtrArgType->getPointeeType();
  const RecordDecl *RD = Pointee->getAsRecordDecl();
  // Try to instantiate the class template as appropriate; otherwise, access to
  // its data() may lead to a crash.
  if (S.RequireCompleteType(PtrArgResult.get()->getBeginLoc(), Pointee,
                            diag::err_incomplete_type))
    return ExprError();
  // Second argument is a callable, but we can't fully validate it until we try
  // calling it.
  QualType FnArgType = TheCall->getArg(1)->getType();
  if (!FnArgType->isFunctionType() && !FnArgType->isFunctionPointerType() &&
      !FnArgType->isBlockPointerType() &&
      !(S.getLangOpts().CPlusPlus && FnArgType->isRecordType())) {
    auto *BT = FnArgType->getAs<BuiltinType>();
    switch (BT ? BT->getKind() : BuiltinType::Void) {
    case BuiltinType::Dependent:
    case BuiltinType::Overload:
    case BuiltinType::BoundMember:
    case BuiltinType::PseudoObject:
    case BuiltinType::UnknownAny:
    case BuiltinType::BuiltinFn:
      // This might be a callable.
      break;

    default:
      S.Diag(TheCall->getArg(1)->getBeginLoc(),
             diag::err_expected_callable_argument)
          << 2 << TheCall->getDirectCallee() << FnArgType;
      return ExprError();
    }
  }

  BuiltinDumpStructGenerator Generator(S, TheCall);

  // Wrap parentheses around the given pointer. This is not necessary for
  // correct code generation, but it means that when we pretty-print the call
  // arguments in our diagnostics we will produce '(&s)->n' instead of the
  // incorrect '&s->n'.
  Expr *PtrArg = PtrArgResult.get();
  PtrArg = new (S.Context)
      ParenExpr(PtrArg->getBeginLoc(),
                S.getLocForEndOfToken(PtrArg->getEndLoc()), PtrArg);
  if (Generator.dumpUnnamedRecord(RD, PtrArg, 0))
    return ExprError();

  return Generator.buildWrapper();
}

static bool BuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) {
  if (S.checkArgCount(BuiltinCall, 2))
    return true;

  SourceLocation BuiltinLoc = BuiltinCall->getBeginLoc();
  Expr *Builtin = BuiltinCall->getCallee()->IgnoreImpCasts();
  Expr *Call = BuiltinCall->getArg(0);
  Expr *Chain = BuiltinCall->getArg(1);

  if (Call->getStmtClass() != Stmt::CallExprClass) {
    S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_not_call)
        << Call->getSourceRange();
    return true;
  }

  auto CE = cast<CallExpr>(Call);
  if (CE->getCallee()->getType()->isBlockPointerType()) {
    S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_block_call)
        << Call->getSourceRange();
    return true;
  }

  const Decl *TargetDecl = CE->getCalleeDecl();
  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl))
    if (FD->getBuiltinID()) {
      S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_builtin_call)
          << Call->getSourceRange();
      return true;
    }

  if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens())) {
    S.Diag(BuiltinLoc, diag::err_first_argument_to_cwsc_pdtor_call)
        << Call->getSourceRange();
    return true;
  }

  ExprResult ChainResult = S.UsualUnaryConversions(Chain);
  if (ChainResult.isInvalid())
    return true;
  if (!ChainResult.get()->getType()->isPointerType()) {
    S.Diag(BuiltinLoc, diag::err_second_argument_to_cwsc_not_pointer)
        << Chain->getSourceRange();
    return true;
  }

  QualType ReturnTy = CE->getCallReturnType(S.Context);
  QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() };
  QualType BuiltinTy = S.Context.getFunctionType(
      ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo());
  QualType BuiltinPtrTy = S.Context.getPointerType(BuiltinTy);

  Builtin =
      S.ImpCastExprToType(Builtin, BuiltinPtrTy, CK_BuiltinFnToFnPtr).get();

  BuiltinCall->setType(CE->getType());
  BuiltinCall->setValueKind(CE->getValueKind());
  BuiltinCall->setObjectKind(CE->getObjectKind());
  BuiltinCall->setCallee(Builtin);
  BuiltinCall->setArg(1, ChainResult.get());

  return false;
}

namespace {

class ScanfDiagnosticFormatHandler
    : public analyze_format_string::FormatStringHandler {
  // Accepts the argument index (relative to the first destination index) of the
  // argument whose size we want.
  using ComputeSizeFunction =
      llvm::function_ref<std::optional<llvm::APSInt>(unsigned)>;

  // Accepts the argument index (relative to the first destination index), the
  // destination size, and the source size).
  using DiagnoseFunction =
      llvm::function_ref<void(unsigned, unsigned, unsigned)>;

  ComputeSizeFunction ComputeSizeArgument;
  DiagnoseFunction Diagnose;

public:
  ScanfDiagnosticFormatHandler(ComputeSizeFunction ComputeSizeArgument,
                               DiagnoseFunction Diagnose)
      : ComputeSizeArgument(ComputeSizeArgument), Diagnose(Diagnose) {}

  bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
                            const char *StartSpecifier,
                            unsigned specifierLen) override {
    if (!FS.consumesDataArgument())
      return true;

    unsigned NulByte = 0;
    switch ((FS.getConversionSpecifier().getKind())) {
    default:
      return true;
    case analyze_format_string::ConversionSpecifier::sArg:
    case analyze_format_string::ConversionSpecifier::ScanListArg:
      NulByte = 1;
      break;
    case analyze_format_string::ConversionSpecifier::cArg:
      break;
    }

    analyze_format_string::OptionalAmount FW = FS.getFieldWidth();
    if (FW.getHowSpecified() !=
        analyze_format_string::OptionalAmount::HowSpecified::Constant)
      return true;

    unsigned SourceSize = FW.getConstantAmount() + NulByte;

    std::optional<llvm::APSInt> DestSizeAPS =
        ComputeSizeArgument(FS.getArgIndex());
    if (!DestSizeAPS)
      return true;

    unsigned DestSize = DestSizeAPS->getZExtValue();

    if (DestSize < SourceSize)
      Diagnose(FS.getArgIndex(), DestSize, SourceSize);

    return true;
  }
};

class EstimateSizeFormatHandler
    : public analyze_format_string::FormatStringHandler {
  size_t Size;
  /// Whether the format string contains Linux kernel's format specifier
  /// extension.
  bool IsKernelCompatible = true;

public:
  EstimateSizeFormatHandler(StringRef Format)
      : Size(std::min(Format.find(0), Format.size()) +
             1 /* null byte always written by sprintf */) {}

  bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
                             const char *, unsigned SpecifierLen,
                             const TargetInfo &) override {

    const size_t FieldWidth = computeFieldWidth(FS);
    const size_t Precision = computePrecision(FS);

    // The actual format.
    switch (FS.getConversionSpecifier().getKind()) {
    // Just a char.
    case analyze_format_string::ConversionSpecifier::cArg:
    case analyze_format_string::ConversionSpecifier::CArg:
      Size += std::max(FieldWidth, (size_t)1);
      break;
    // Just an integer.
    case analyze_format_string::ConversionSpecifier::dArg:
    case analyze_format_string::ConversionSpecifier::DArg:
    case analyze_format_string::ConversionSpecifier::iArg:
    case analyze_format_string::ConversionSpecifier::oArg:
    case analyze_format_string::ConversionSpecifier::OArg:
    case analyze_format_string::ConversionSpecifier::uArg:
    case analyze_format_string::ConversionSpecifier::UArg:
    case analyze_format_string::ConversionSpecifier::xArg:
    case analyze_format_string::ConversionSpecifier::XArg:
      Size += std::max(FieldWidth, Precision);
      break;

    // %g style conversion switches between %f or %e style dynamically.
    // %g removes trailing zeros, and does not print decimal point if there are
    // no digits that follow it. Thus %g can print a single digit.
    // FIXME: If it is alternative form:
    // For g and G conversions, trailing zeros are not removed from the result.
    case analyze_format_string::ConversionSpecifier::gArg:
    case analyze_format_string::ConversionSpecifier::GArg:
      Size += 1;
      break;

    // Floating point number in the form '[+]ddd.ddd'.
    case analyze_format_string::ConversionSpecifier::fArg:
    case analyze_format_string::ConversionSpecifier::FArg:
      Size += std::max(FieldWidth, 1 /* integer part */ +
                                       (Precision ? 1 + Precision
                                                  : 0) /* period + decimal */);
      break;

    // Floating point number in the form '[-]d.ddde[+-]dd'.
    case analyze_format_string::ConversionSpecifier::eArg:
    case analyze_format_string::ConversionSpecifier::EArg:
      Size +=
          std::max(FieldWidth,
                   1 /* integer part */ +
                       (Precision ? 1 + Precision : 0) /* period + decimal */ +
                       1 /* e or E letter */ + 2 /* exponent */);
      break;

    // Floating point number in the form '[-]0xh.hhhhp±dd'.
    case analyze_format_string::ConversionSpecifier::aArg:
    case analyze_format_string::ConversionSpecifier::AArg:
      Size +=
          std::max(FieldWidth,
                   2 /* 0x */ + 1 /* integer part */ +
                       (Precision ? 1 + Precision : 0) /* period + decimal */ +
                       1 /* p or P letter */ + 1 /* + or - */ + 1 /* value */);
      break;

    // Just a string.
    case analyze_format_string::ConversionSpecifier::sArg:
    case analyze_format_string::ConversionSpecifier::SArg:
      Size += FieldWidth;
      break;

    // Just a pointer in the form '0xddd'.
    case analyze_format_string::ConversionSpecifier::pArg:
      // Linux kernel has its own extesion for `%p` specifier.
      // Kernel Document:
      // https://docs.kernel.org/core-api/printk-formats.html#pointer-types
      IsKernelCompatible = false;
      Size += std::max(FieldWidth, 2 /* leading 0x */ + Precision);
      break;

    // A plain percent.
    case analyze_format_string::ConversionSpecifier::PercentArg:
      Size += 1;
      break;

    default:
      break;
    }

    Size += FS.hasPlusPrefix() || FS.hasSpacePrefix();

    if (FS.hasAlternativeForm()) {
      switch (FS.getConversionSpecifier().getKind()) {
      // For o conversion, it increases the precision, if and only if necessary,
      // to force the first digit of the result to be a zero
      // (if the value and precision are both 0, a single 0 is printed)
      case analyze_format_string::ConversionSpecifier::oArg:
      // For b conversion, a nonzero result has 0b prefixed to it.
      case analyze_format_string::ConversionSpecifier::bArg:
      // For x (or X) conversion, a nonzero result has 0x (or 0X) prefixed to
      // it.
      case analyze_format_string::ConversionSpecifier::xArg:
      case analyze_format_string::ConversionSpecifier::XArg:
        // Note: even when the prefix is added, if
        // (prefix_width <= FieldWidth - formatted_length) holds,
        // the prefix does not increase the format
        // size. e.g.(("%#3x", 0xf) is "0xf")

        // If the result is zero, o, b, x, X adds nothing.
        break;
      // For a, A, e, E, f, F, g, and G conversions,
      // the result of converting a floating-point number always contains a
      // decimal-point
      case analyze_format_string::ConversionSpecifier::aArg:
      case analyze_format_string::ConversionSpecifier::AArg:
      case analyze_format_string::ConversionSpecifier::eArg:
      case analyze_format_string::ConversionSpecifier::EArg:
      case analyze_format_string::ConversionSpecifier::fArg:
      case analyze_format_string::ConversionSpecifier::FArg:
      case analyze_format_string::ConversionSpecifier::gArg:
      case analyze_format_string::ConversionSpecifier::GArg:
        Size += (Precision ? 0 : 1);
        break;
      // For other conversions, the behavior is undefined.
      default:
        break;
      }
    }
    assert(SpecifierLen <= Size && "no underflow");
    Size -= SpecifierLen;
    return true;
  }

  size_t getSizeLowerBound() const { return Size; }
  bool isKernelCompatible() const { return IsKernelCompatible; }

private:
  static size_t computeFieldWidth(const analyze_printf::PrintfSpecifier &FS) {
    const analyze_format_string::OptionalAmount &FW = FS.getFieldWidth();
    size_t FieldWidth = 0;
    if (FW.getHowSpecified() == analyze_format_string::OptionalAmount::Constant)
      FieldWidth = FW.getConstantAmount();
    return FieldWidth;
  }

  static size_t computePrecision(const analyze_printf::PrintfSpecifier &FS) {
    const analyze_format_string::OptionalAmount &FW = FS.getPrecision();
    size_t Precision = 0;

    // See man 3 printf for default precision value based on the specifier.
    switch (FW.getHowSpecified()) {
    case analyze_format_string::OptionalAmount::NotSpecified:
      switch (FS.getConversionSpecifier().getKind()) {
      default:
        break;
      case analyze_format_string::ConversionSpecifier::dArg: // %d
      case analyze_format_string::ConversionSpecifier::DArg: // %D
      case analyze_format_string::ConversionSpecifier::iArg: // %i
        Precision = 1;
        break;
      case analyze_format_string::ConversionSpecifier::oArg: // %d
      case analyze_format_string::ConversionSpecifier::OArg: // %D
      case analyze_format_string::ConversionSpecifier::uArg: // %d
      case analyze_format_string::ConversionSpecifier::UArg: // %D
      case analyze_format_string::ConversionSpecifier::xArg: // %d
      case analyze_format_string::ConversionSpecifier::XArg: // %D
        Precision = 1;
        break;
      case analyze_format_string::ConversionSpecifier::fArg: // %f
      case analyze_format_string::ConversionSpecifier::FArg: // %F
      case analyze_format_string::ConversionSpecifier::eArg: // %e
      case analyze_format_string::ConversionSpecifier::EArg: // %E
      case analyze_format_string::ConversionSpecifier::gArg: // %g
      case analyze_format_string::ConversionSpecifier::GArg: // %G
        Precision = 6;
        break;
      case analyze_format_string::ConversionSpecifier::pArg: // %d
        Precision = 1;
        break;
      }
      break;
    case analyze_format_string::OptionalAmount::Constant:
      Precision = FW.getConstantAmount();
      break;
    default:
      break;
    }
    return Precision;
  }
};

} // namespace

static bool ProcessFormatStringLiteral(const Expr *FormatExpr,
                                       StringRef &FormatStrRef, size_t &StrLen,
                                       ASTContext &Context) {
  if (const auto *Format = dyn_cast<StringLiteral>(FormatExpr);
      Format && (Format->isOrdinary() || Format->isUTF8())) {
    FormatStrRef = Format->getString();
    const ConstantArrayType *T =
        Context.getAsConstantArrayType(Format->getType());
    assert(T && "String literal not of constant array type!");
    size_t TypeSize = T->getZExtSize();
    // In case there's a null byte somewhere.
    StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, FormatStrRef.find(0));
    return true;
  }
  return false;
}

void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
                                               CallExpr *TheCall) {
  if (TheCall->isValueDependent() || TheCall->isTypeDependent() ||
      isConstantEvaluatedContext())
    return;

  bool UseDABAttr = false;
  const FunctionDecl *UseDecl = FD;

  const auto *DABAttr = FD->getAttr<DiagnoseAsBuiltinAttr>();
  if (DABAttr) {
    UseDecl = DABAttr->getFunction();
    assert(UseDecl && "Missing FunctionDecl in DiagnoseAsBuiltin attribute!");
    UseDABAttr = true;
  }

  unsigned BuiltinID = UseDecl->getBuiltinID(/*ConsiderWrappers=*/true);

  if (!BuiltinID)
    return;

  const TargetInfo &TI = getASTContext().getTargetInfo();
  unsigned SizeTypeWidth = TI.getTypeWidth(TI.getSizeType());

  auto TranslateIndex = [&](unsigned Index) -> std::optional<unsigned> {
    // If we refer to a diagnose_as_builtin attribute, we need to change the
    // argument index to refer to the arguments of the called function. Unless
    // the index is out of bounds, which presumably means it's a variadic
    // function.
    if (!UseDABAttr)
      return Index;
    unsigned DABIndices = DABAttr->argIndices_size();
    unsigned NewIndex = Index < DABIndices
                            ? DABAttr->argIndices_begin()[Index]
                            : Index - DABIndices + FD->getNumParams();
    if (NewIndex >= TheCall->getNumArgs())
      return std::nullopt;
    return NewIndex;
  };

  auto ComputeExplicitObjectSizeArgument =
      [&](unsigned Index) -> std::optional<llvm::APSInt> {
    std::optional<unsigned> IndexOptional = TranslateIndex(Index);
    if (!IndexOptional)
      return std::nullopt;
    unsigned NewIndex = *IndexOptional;
    Expr::EvalResult Result;
    Expr *SizeArg = TheCall->getArg(NewIndex);
    if (!SizeArg->EvaluateAsInt(Result, getASTContext()))
      return std::nullopt;
    llvm::APSInt Integer = Result.Val.getInt();
    Integer.setIsUnsigned(true);
    return Integer;
  };

  auto ComputeSizeArgument =
      [&](unsigned Index) -> std::optional<llvm::APSInt> {
    // If the parameter has a pass_object_size attribute, then we should use its
    // (potentially) more strict checking mode. Otherwise, conservatively assume
    // type 0.
    int BOSType = 0;
    // This check can fail for variadic functions.
    if (Index < FD->getNumParams()) {
      if (const auto *POS =
              FD->getParamDecl(Index)->getAttr<PassObjectSizeAttr>())
        BOSType = POS->getType();
    }

    std::optional<unsigned> IndexOptional = TranslateIndex(Index);
    if (!IndexOptional)
      return std::nullopt;
    unsigned NewIndex = *IndexOptional;

    if (NewIndex >= TheCall->getNumArgs())
      return std::nullopt;

    const Expr *ObjArg = TheCall->getArg(NewIndex);
    uint64_t Result;
    if (!ObjArg->tryEvaluateObjectSize(Result, getASTContext(), BOSType))
      return std::nullopt;

    // Get the object size in the target's size_t width.
    return llvm::APSInt::getUnsigned(Result).extOrTrunc(SizeTypeWidth);
  };

  auto ComputeStrLenArgument =
      [&](unsigned Index) -> std::optional<llvm::APSInt> {
    std::optional<unsigned> IndexOptional = TranslateIndex(Index);
    if (!IndexOptional)
      return std::nullopt;
    unsigned NewIndex = *IndexOptional;

    const Expr *ObjArg = TheCall->getArg(NewIndex);
    uint64_t Result;
    if (!ObjArg->tryEvaluateStrLen(Result, getASTContext()))
      return std::nullopt;
    // Add 1 for null byte.
    return llvm::APSInt::getUnsigned(Result + 1).extOrTrunc(SizeTypeWidth);
  };

  std::optional<llvm::APSInt> SourceSize;
  std::optional<llvm::APSInt> DestinationSize;
  unsigned DiagID = 0;
  bool IsChkVariant = false;

  auto GetFunctionName = [&]() {
    std::string FunctionNameStr =
        getASTContext().BuiltinInfo.getName(BuiltinID);
    llvm::StringRef FunctionName = FunctionNameStr;
    // Skim off the details of whichever builtin was called to produce a better
    // diagnostic, as it's unlikely that the user wrote the __builtin
    // explicitly.
    if (IsChkVariant) {
      FunctionName = FunctionName.drop_front(std::strlen("__builtin___"));
      FunctionName = FunctionName.drop_back(std::strlen("_chk"));
    } else {
      FunctionName.consume_front("__builtin_");
    }
    return FunctionName.str();
  };

  switch (BuiltinID) {
  default:
    return;
  case Builtin::BI__builtin_strcpy:
  case Builtin::BIstrcpy: {
    DiagID = diag::warn_fortify_strlen_overflow;
    SourceSize = ComputeStrLenArgument(1);
    DestinationSize = ComputeSizeArgument(0);
    break;
  }

  case Builtin::BI__builtin___strcpy_chk: {
    DiagID = diag::warn_fortify_strlen_overflow;
    SourceSize = ComputeStrLenArgument(1);
    DestinationSize = ComputeExplicitObjectSizeArgument(2);
    IsChkVariant = true;
    break;
  }

  case Builtin::BIscanf:
  case Builtin::BIfscanf:
  case Builtin::BIsscanf: {
    unsigned FormatIndex = 1;
    unsigned DataIndex = 2;
    if (BuiltinID == Builtin::BIscanf) {
      FormatIndex = 0;
      DataIndex = 1;
    }

    const auto *FormatExpr =
        TheCall->getArg(FormatIndex)->IgnoreParenImpCasts();

    StringRef FormatStrRef;
    size_t StrLen;
    if (!ProcessFormatStringLiteral(FormatExpr, FormatStrRef, StrLen, Context))
      return;

    auto Diagnose = [&](unsigned ArgIndex, unsigned DestSize,
                        unsigned SourceSize) {
      DiagID = diag::warn_fortify_scanf_overflow;
      unsigned Index = ArgIndex + DataIndex;
      std::string FunctionName = GetFunctionName();
      DiagRuntimeBehavior(TheCall->getArg(Index)->getBeginLoc(), TheCall,
                          PDiag(DiagID) << FunctionName << (Index + 1)
                                        << DestSize << SourceSize);
    };

    auto ShiftedComputeSizeArgument = [&](unsigned Index) {
      return ComputeSizeArgument(Index + DataIndex);
    };
    ScanfDiagnosticFormatHandler H(ShiftedComputeSizeArgument, Diagnose);
    const char *FormatBytes = FormatStrRef.data();
    analyze_format_string::ParseScanfString(H, FormatBytes,
                                            FormatBytes + StrLen, getLangOpts(),
                                            Context.getTargetInfo());

    // Unlike the other cases, in this one we have already issued the diagnostic
    // here, so no need to continue (because unlike the other cases, here the
    // diagnostic refers to the argument number).
    return;
  }

  case Builtin::BIsprintf:
  case Builtin::BI__builtin___sprintf_chk: {
    size_t FormatIndex = BuiltinID == Builtin::BIsprintf ? 1 : 3;
    auto *FormatExpr = TheCall->getArg(FormatIndex)->IgnoreParenImpCasts();

    StringRef FormatStrRef;
    size_t StrLen;
    if (ProcessFormatStringLiteral(FormatExpr, FormatStrRef, StrLen, Context)) {
      EstimateSizeFormatHandler H(FormatStrRef);
      const char *FormatBytes = FormatStrRef.data();
      if (!analyze_format_string::ParsePrintfString(
              H, FormatBytes, FormatBytes + StrLen, getLangOpts(),
              Context.getTargetInfo(), false)) {
        DiagID = H.isKernelCompatible()
                     ? diag::warn_format_overflow
                     : diag::warn_format_overflow_non_kprintf;
        SourceSize = llvm::APSInt::getUnsigned(H.getSizeLowerBound())
                         .extOrTrunc(SizeTypeWidth);
        if (BuiltinID == Builtin::BI__builtin___sprintf_chk) {
          DestinationSize = ComputeExplicitObjectSizeArgument(2);
          IsChkVariant = true;
        } else {
          DestinationSize = ComputeSizeArgument(0);
        }
        break;
      }
    }
    return;
  }
  case Builtin::BI__builtin___memcpy_chk:
  case Builtin::BI__builtin___memmove_chk:
  case Builtin::BI__builtin___memset_chk:
  case Builtin::BI__builtin___strlcat_chk:
  case Builtin::BI__builtin___strlcpy_chk:
  case Builtin::BI__builtin___strncat_chk:
  case Builtin::BI__builtin___strncpy_chk:
  case Builtin::BI__builtin___stpncpy_chk:
  case Builtin::BI__builtin___memccpy_chk:
  case Builtin::BI__builtin___mempcpy_chk: {
    DiagID = diag::warn_builtin_chk_overflow;
    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
    DestinationSize =
        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
    IsChkVariant = true;
    break;
  }

  case Builtin::BI__builtin___snprintf_chk:
  case Builtin::BI__builtin___vsnprintf_chk: {
    DiagID = diag::warn_builtin_chk_overflow;
    SourceSize = ComputeExplicitObjectSizeArgument(1);
    DestinationSize = ComputeExplicitObjectSizeArgument(3);
    IsChkVariant = true;
    break;
  }

  case Builtin::BIstrncat:
  case Builtin::BI__builtin_strncat:
  case Builtin::BIstrncpy:
  case Builtin::BI__builtin_strncpy:
  case Builtin::BIstpncpy:
  case Builtin::BI__builtin_stpncpy: {
    // Whether these functions overflow depends on the runtime strlen of the
    // string, not just the buffer size, so emitting the "always overflow"
    // diagnostic isn't quite right. We should still diagnose passing a buffer
    // size larger than the destination buffer though; this is a runtime abort
    // in _FORTIFY_SOURCE mode, and is quite suspicious otherwise.
    DiagID = diag::warn_fortify_source_size_mismatch;
    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
    DestinationSize = ComputeSizeArgument(0);
    break;
  }

  case Builtin::BImemcpy:
  case Builtin::BI__builtin_memcpy:
  case Builtin::BImemmove:
  case Builtin::BI__builtin_memmove:
  case Builtin::BImemset:
  case Builtin::BI__builtin_memset:
  case Builtin::BImempcpy:
  case Builtin::BI__builtin_mempcpy: {
    DiagID = diag::warn_fortify_source_overflow;
    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
    DestinationSize = ComputeSizeArgument(0);
    break;
  }
  case Builtin::BIsnprintf:
  case Builtin::BI__builtin_snprintf:
  case Builtin::BIvsnprintf:
  case Builtin::BI__builtin_vsnprintf: {
    DiagID = diag::warn_fortify_source_size_mismatch;
    SourceSize = ComputeExplicitObjectSizeArgument(1);
    const auto *FormatExpr = TheCall->getArg(2)->IgnoreParenImpCasts();
    StringRef FormatStrRef;
    size_t StrLen;
    if (SourceSize &&
        ProcessFormatStringLiteral(FormatExpr, FormatStrRef, StrLen, Context)) {
      EstimateSizeFormatHandler H(FormatStrRef);
      const char *FormatBytes = FormatStrRef.data();
      if (!analyze_format_string::ParsePrintfString(
              H, FormatBytes, FormatBytes + StrLen, getLangOpts(),
              Context.getTargetInfo(), /*isFreeBSDKPrintf=*/false)) {
        llvm::APSInt FormatSize =
            llvm::APSInt::getUnsigned(H.getSizeLowerBound())
                .extOrTrunc(SizeTypeWidth);
        if (FormatSize > *SourceSize && *SourceSize != 0) {
          unsigned TruncationDiagID =
              H.isKernelCompatible() ? diag::warn_format_truncation
                                     : diag::warn_format_truncation_non_kprintf;
          SmallString<16> SpecifiedSizeStr;
          SmallString<16> FormatSizeStr;
          SourceSize->toString(SpecifiedSizeStr, /*Radix=*/10);
          FormatSize.toString(FormatSizeStr, /*Radix=*/10);
          DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
                              PDiag(TruncationDiagID)
                                  << GetFunctionName() << SpecifiedSizeStr
                                  << FormatSizeStr);
        }
      }
    }
    DestinationSize = ComputeSizeArgument(0);
  }
  }

  if (!SourceSize || !DestinationSize ||
      llvm::APSInt::compareValues(*SourceSize, *DestinationSize) <= 0)
    return;

  std::string FunctionName = GetFunctionName();

  SmallString<16> DestinationStr;
  SmallString<16> SourceStr;
  DestinationSize->toString(DestinationStr, /*Radix=*/10);
  SourceSize->toString(SourceStr, /*Radix=*/10);
  DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
                      PDiag(DiagID)
                          << FunctionName << DestinationStr << SourceStr);
}

static bool BuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
                                 Scope::ScopeFlags NeededScopeFlags,
                                 unsigned DiagID) {
  // Scopes aren't available during instantiation. Fortunately, builtin
  // functions cannot be template args so they cannot be formed through template
  // instantiation. Therefore checking once during the parse is sufficient.
  if (SemaRef.inTemplateInstantiation())
    return false;

  Scope *S = SemaRef.getCurScope();
  while (S && !S->isSEHExceptScope())
    S = S->getParent();
  if (!S || !(S->getFlags() & NeededScopeFlags)) {
    auto *DRE = cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
    SemaRef.Diag(TheCall->getExprLoc(), DiagID)
        << DRE->getDecl()->getIdentifier();
    return true;
  }

  return false;
}

// In OpenCL, __builtin_alloca_* should return a pointer to address space
// that corresponds to the stack address space i.e private address space.
static void builtinAllocaAddrSpace(Sema &S, CallExpr *TheCall) {
  QualType RT = TheCall->getType();
  assert((RT->isPointerType() && !(RT->getPointeeType().hasAddressSpace())) &&
         "__builtin_alloca has invalid address space");

  RT = RT->getPointeeType();
  RT = S.Context.getAddrSpaceQualType(RT, LangAS::opencl_private);
  TheCall->setType(S.Context.getPointerType(RT));
}

namespace {
enum PointerAuthOpKind {
  PAO_Strip,
  PAO_Sign,
  PAO_Auth,
  PAO_SignGeneric,
  PAO_Discriminator,
  PAO_BlendPointer,
  PAO_BlendInteger
};
}

bool Sema::checkPointerAuthEnabled(SourceLocation Loc, SourceRange Range) {
  if (getLangOpts().PointerAuthIntrinsics)
    return false;

  Diag(Loc, diag::err_ptrauth_disabled) << Range;
  return true;
}

static bool checkPointerAuthEnabled(Sema &S, Expr *E) {
  return S.checkPointerAuthEnabled(E->getExprLoc(), E->getSourceRange());
}

static bool checkPointerAuthKey(Sema &S, Expr *&Arg) {
  // Convert it to type 'int'.
  if (convertArgumentToType(S, Arg, S.Context.IntTy))
    return true;

  // Value-dependent expressions are okay; wait for template instantiation.
  if (Arg->isValueDependent())
    return false;

  unsigned KeyValue;
  return S.checkConstantPointerAuthKey(Arg, KeyValue);
}

bool Sema::checkConstantPointerAuthKey(Expr *Arg, unsigned &Result) {
  // Attempt to constant-evaluate the expression.
  std::optional<llvm::APSInt> KeyValue = Arg->getIntegerConstantExpr(Context);
  if (!KeyValue) {
    Diag(Arg->getExprLoc(), diag::err_expr_not_ice)
        << 0 << Arg->getSourceRange();
    return true;
  }

  // Ask the target to validate the key parameter.
  if (!Context.getTargetInfo().validatePointerAuthKey(*KeyValue)) {
    llvm::SmallString<32> Value;
    {
      llvm::raw_svector_ostream Str(Value);
      Str << *KeyValue;
    }

    Diag(Arg->getExprLoc(), diag::err_ptrauth_invalid_key)
        << Value << Arg->getSourceRange();
    return true;
  }

  Result = KeyValue->getZExtValue();
  return false;
}

bool Sema::checkPointerAuthDiscriminatorArg(Expr *Arg,
                                            PointerAuthDiscArgKind Kind,
                                            unsigned &IntVal) {
  if (!Arg) {
    IntVal = 0;
    return true;
  }

  std::optional<llvm::APSInt> Result = Arg->getIntegerConstantExpr(Context);
  if (!Result) {
    Diag(Arg->getExprLoc(), diag::err_ptrauth_arg_not_ice);
    return false;
  }

  unsigned Max;
  bool IsAddrDiscArg = false;

  switch (Kind) {
  case PointerAuthDiscArgKind::Addr:
    Max = 1;
    IsAddrDiscArg = true;
    break;
  case PointerAuthDiscArgKind::Extra:
    Max = PointerAuthQualifier::MaxDiscriminator;
    break;
  };

  if (*Result < 0 || *Result > Max) {
    if (IsAddrDiscArg)
      Diag(Arg->getExprLoc(), diag::err_ptrauth_address_discrimination_invalid)
          << Result->getExtValue();
    else
      Diag(Arg->getExprLoc(), diag::err_ptrauth_extra_discriminator_invalid)
          << Result->getExtValue() << Max;

    return false;
  };

  IntVal = Result->getZExtValue();
  return true;
}

static std::pair<const ValueDecl *, CharUnits>
findConstantBaseAndOffset(Sema &S, Expr *E) {
  // Must evaluate as a pointer.
  Expr::EvalResult Result;
  if (!E->EvaluateAsRValue(Result, S.Context) || !Result.Val.isLValue())
    return {nullptr, CharUnits()};

  const auto *BaseDecl =
      Result.Val.getLValueBase().dyn_cast<const ValueDecl *>();
  if (!BaseDecl)
    return {nullptr, CharUnits()};

  return {BaseDecl, Result.Val.getLValueOffset()};
}

static bool checkPointerAuthValue(Sema &S, Expr *&Arg, PointerAuthOpKind OpKind,
                                  bool RequireConstant = false) {
  if (Arg->hasPlaceholderType()) {
    ExprResult R = S.CheckPlaceholderExpr(Arg);
    if (R.isInvalid())
      return true;
    Arg = R.get();
  }

  auto AllowsPointer = [](PointerAuthOpKind OpKind) {
    return OpKind != PAO_BlendInteger;
  };
  auto AllowsInteger = [](PointerAuthOpKind OpKind) {
    return OpKind == PAO_Discriminator || OpKind == PAO_BlendInteger ||
           OpKind == PAO_SignGeneric;
  };

  // Require the value to have the right range of type.
  QualType ExpectedTy;
  if (AllowsPointer(OpKind) && Arg->getType()->isPointerType()) {
    ExpectedTy = Arg->getType().getUnqualifiedType();
  } else if (AllowsPointer(OpKind) && Arg->getType()->isNullPtrType()) {
    ExpectedTy = S.Context.VoidPtrTy;
  } else if (AllowsInteger(OpKind) &&
             Arg->getType()->isIntegralOrUnscopedEnumerationType()) {
    ExpectedTy = S.Context.getUIntPtrType();

  } else {
    // Diagnose the failures.
    S.Diag(Arg->getExprLoc(), diag::err_ptrauth_value_bad_type)
        << unsigned(OpKind == PAO_Discriminator  ? 1
                    : OpKind == PAO_BlendPointer ? 2
                    : OpKind == PAO_BlendInteger ? 3
                                                 : 0)
        << unsigned(AllowsInteger(OpKind) ? (AllowsPointer(OpKind) ? 2 : 1) : 0)
        << Arg->getType() << Arg->getSourceRange();
    return true;
  }

  // Convert to that type.  This should just be an lvalue-to-rvalue
  // conversion.
  if (convertArgumentToType(S, Arg, ExpectedTy))
    return true;

  if (!RequireConstant) {
    // Warn about null pointers for non-generic sign and auth operations.
    if ((OpKind == PAO_Sign || OpKind == PAO_Auth) &&
        Arg->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) {
      S.Diag(Arg->getExprLoc(), OpKind == PAO_Sign
                                    ? diag::warn_ptrauth_sign_null_pointer
                                    : diag::warn_ptrauth_auth_null_pointer)
          << Arg->getSourceRange();
    }

    return false;
  }

  // Perform special checking on the arguments to ptrauth_sign_constant.

  // The main argument.
  if (OpKind == PAO_Sign) {
    // Require the value we're signing to have a special form.
    auto [BaseDecl, Offset] = findConstantBaseAndOffset(S, Arg);
    bool Invalid;

    // Must be rooted in a declaration reference.
    if (!BaseDecl)
      Invalid = true;

    // If it's a function declaration, we can't have an offset.
    else if (isa<FunctionDecl>(BaseDecl))
      Invalid = !Offset.isZero();

    // Otherwise we're fine.
    else
      Invalid = false;

    if (Invalid)
      S.Diag(Arg->getExprLoc(), diag::err_ptrauth_bad_constant_pointer);
    return Invalid;
  }

  // The discriminator argument.
  assert(OpKind == PAO_Discriminator);

  // Must be a pointer or integer or blend thereof.
  Expr *Pointer = nullptr;
  Expr *Integer = nullptr;
  if (auto *Call = dyn_cast<CallExpr>(Arg->IgnoreParens())) {
    if (Call->getBuiltinCallee() ==
        Builtin::BI__builtin_ptrauth_blend_discriminator) {
      Pointer = Call->getArg(0);
      Integer = Call->getArg(1);
    }
  }
  if (!Pointer && !Integer) {
    if (Arg->getType()->isPointerType())
      Pointer = Arg;
    else
      Integer = Arg;
  }

  // Check the pointer.
  bool Invalid = false;
  if (Pointer) {
    assert(Pointer->getType()->isPointerType());

    // TODO: if we're initializing a global, check that the address is
    // somehow related to what we're initializing.  This probably will
    // never really be feasible and we'll have to catch it at link-time.
    auto [BaseDecl, Offset] = findConstantBaseAndOffset(S, Pointer);
    if (!BaseDecl || !isa<VarDecl>(BaseDecl))
      Invalid = true;
  }

  // Check the integer.
  if (Integer) {
    assert(Integer->getType()->isIntegerType());
    if (!Integer->isEvaluatable(S.Context))
      Invalid = true;
  }

  if (Invalid)
    S.Diag(Arg->getExprLoc(), diag::err_ptrauth_bad_constant_discriminator);
  return Invalid;
}

static ExprResult PointerAuthStrip(Sema &S, CallExpr *Call) {
  if (S.checkArgCount(Call, 2))
    return ExprError();
  if (checkPointerAuthEnabled(S, Call))
    return ExprError();
  if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_Strip) ||
      checkPointerAuthKey(S, Call->getArgs()[1]))
    return ExprError();

  Call->setType(Call->getArgs()[0]->getType());
  return Call;
}

static ExprResult PointerAuthBlendDiscriminator(Sema &S, CallExpr *Call) {
  if (S.checkArgCount(Call, 2))
    return ExprError();
  if (checkPointerAuthEnabled(S, Call))
    return ExprError();
  if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_BlendPointer) ||
      checkPointerAuthValue(S, Call->getArgs()[1], PAO_BlendInteger))
    return ExprError();

  Call->setType(S.Context.getUIntPtrType());
  return Call;
}

static ExprResult PointerAuthSignGenericData(Sema &S, CallExpr *Call) {
  if (S.checkArgCount(Call, 2))
    return ExprError();
  if (checkPointerAuthEnabled(S, Call))
    return ExprError();
  if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_SignGeneric) ||
      checkPointerAuthValue(S, Call->getArgs()[1], PAO_Discriminator))
    return ExprError();

  Call->setType(S.Context.getUIntPtrType());
  return Call;
}

static ExprResult PointerAuthSignOrAuth(Sema &S, CallExpr *Call,
                                        PointerAuthOpKind OpKind,
                                        bool RequireConstant) {
  if (S.checkArgCount(Call, 3))
    return ExprError();
  if (checkPointerAuthEnabled(S, Call))
    return ExprError();
  if (checkPointerAuthValue(S, Call->getArgs()[0], OpKind, RequireConstant) ||
      checkPointerAuthKey(S, Call->getArgs()[1]) ||
      checkPointerAuthValue(S, Call->getArgs()[2], PAO_Discriminator,
                            RequireConstant))
    return ExprError();

  Call->setType(Call->getArgs()[0]->getType());
  return Call;
}

static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) {
  if (S.checkArgCount(Call, 5))
    return ExprError();
  if (checkPointerAuthEnabled(S, Call))
    return ExprError();
  if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_Auth) ||
      checkPointerAuthKey(S, Call->getArgs()[1]) ||
      checkPointerAuthValue(S, Call->getArgs()[2], PAO_Discriminator) ||
      checkPointerAuthKey(S, Call->getArgs()[3]) ||
      checkPointerAuthValue(S, Call->getArgs()[4], PAO_Discriminator))
    return ExprError();

  Call->setType(Call->getArgs()[0]->getType());
  return Call;
}

static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call) {
  if (checkPointerAuthEnabled(S, Call))
    return ExprError();

  // We've already performed normal call type-checking.
  const Expr *Arg = Call->getArg(0)->IgnoreParenImpCasts();

  // Operand must be an ordinary or UTF-8 string literal.
  const auto *Literal = dyn_cast<StringLiteral>(Arg);
  if (!Literal || Literal->getCharByteWidth() != 1) {
    S.Diag(Arg->getExprLoc(), diag::err_ptrauth_string_not_literal)
        << (Literal ? 1 : 0) << Arg->getSourceRange();
    return ExprError();
  }

  return Call;
}

static ExprResult BuiltinLaunder(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 1))
    return ExprError();

  // Compute __builtin_launder's parameter type from the argument.
  // The parameter type is:
  //  * The type of the argument if it's not an array or function type,
  //  Otherwise,
  //  * The decayed argument type.
  QualType ParamTy = [&]() {
    QualType ArgTy = TheCall->getArg(0)->getType();
    if (const ArrayType *Ty = ArgTy->getAsArrayTypeUnsafe())
      return S.Context.getPointerType(Ty->getElementType());
    if (ArgTy->isFunctionType()) {
      return S.Context.getPointerType(ArgTy);
    }
    return ArgTy;
  }();

  TheCall->setType(ParamTy);

  auto DiagSelect = [&]() -> std::optional<unsigned> {
    if (!ParamTy->isPointerType())
      return 0;
    if (ParamTy->isFunctionPointerType())
      return 1;
    if (ParamTy->isVoidPointerType())
      return 2;
    return std::optional<unsigned>{};
  }();
  if (DiagSelect) {
    S.Diag(TheCall->getBeginLoc(), diag::err_builtin_launder_invalid_arg)
        << *DiagSelect << TheCall->getSourceRange();
    return ExprError();
  }

  // We either have an incomplete class type, or we have a class template
  // whose instantiation has not been forced. Example:
  //
  //   template <class T> struct Foo { T value; };
  //   Foo<int> *p = nullptr;
  //   auto *d = __builtin_launder(p);
  if (S.RequireCompleteType(TheCall->getBeginLoc(), ParamTy->getPointeeType(),
                            diag::err_incomplete_type))
    return ExprError();

  assert(ParamTy->getPointeeType()->isObjectType() &&
         "Unhandled non-object pointer case");

  InitializedEntity Entity =
      InitializedEntity::InitializeParameter(S.Context, ParamTy, false);
  ExprResult Arg =
      S.PerformCopyInitialization(Entity, SourceLocation(), TheCall->getArg(0));
  if (Arg.isInvalid())
    return ExprError();
  TheCall->setArg(0, Arg.get());

  return TheCall;
}

static ExprResult BuiltinIsWithinLifetime(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 1))
    return ExprError();

  ExprResult Arg = S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
  if (Arg.isInvalid())
    return ExprError();
  QualType ParamTy = Arg.get()->getType();
  TheCall->setArg(0, Arg.get());
  TheCall->setType(S.Context.BoolTy);

  // Only accept pointers to objects as arguments, which should have object
  // pointer or void pointer types.
  if (const auto *PT = ParamTy->getAs<PointerType>()) {
    // LWG4138: Function pointer types not allowed
    if (PT->getPointeeType()->isFunctionType()) {
      S.Diag(TheCall->getArg(0)->getExprLoc(),
             diag::err_builtin_is_within_lifetime_invalid_arg)
          << 1;
      return ExprError();
    }
    // Disallow VLAs too since those shouldn't be able to
    // be a template parameter for `std::is_within_lifetime`
    if (PT->getPointeeType()->isVariableArrayType()) {
      S.Diag(TheCall->getArg(0)->getExprLoc(), diag::err_vla_unsupported)
          << 1 << "__builtin_is_within_lifetime";
      return ExprError();
    }
  } else {
    S.Diag(TheCall->getArg(0)->getExprLoc(),
           diag::err_builtin_is_within_lifetime_invalid_arg)
        << 0;
    return ExprError();
  }
  return TheCall;
}

static ExprResult BuiltinTriviallyRelocate(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 3))
    return ExprError();

  QualType Dest = TheCall->getArg(0)->getType();
  if (!Dest->isPointerType() || Dest.getCVRQualifiers() != 0) {
    S.Diag(TheCall->getArg(0)->getExprLoc(),
           diag::err_builtin_trivially_relocate_invalid_arg_type)
        << /*a pointer*/ 0;
    return ExprError();
  }

  QualType T = Dest->getPointeeType();
  if (S.RequireCompleteType(TheCall->getBeginLoc(), T,
                            diag::err_incomplete_type))
    return ExprError();

  if (T.isConstQualified() || !S.IsCXXTriviallyRelocatableType(T) ||
      T->isIncompleteArrayType()) {
    S.Diag(TheCall->getArg(0)->getExprLoc(),
           diag::err_builtin_trivially_relocate_invalid_arg_type)
        << (T.isConstQualified() ? /*non-const*/ 1 : /*relocatable*/ 2);
    return ExprError();
  }

  TheCall->setType(Dest);

  QualType Src = TheCall->getArg(1)->getType();
  if (Src.getCanonicalType() != Dest.getCanonicalType()) {
    S.Diag(TheCall->getArg(1)->getExprLoc(),
           diag::err_builtin_trivially_relocate_invalid_arg_type)
        << /*the same*/ 3;
    return ExprError();
  }

  Expr *SizeExpr = TheCall->getArg(2);
  ExprResult Size = S.DefaultLvalueConversion(SizeExpr);
  if (Size.isInvalid())
    return ExprError();

  Size = S.tryConvertExprToType(Size.get(), S.getASTContext().getSizeType());
  if (Size.isInvalid())
    return ExprError();
  SizeExpr = Size.get();
  TheCall->setArg(2, SizeExpr);

  return TheCall;
}

// Emit an error and return true if the current object format type is in the
// list of unsupported types.
static bool CheckBuiltinTargetNotInUnsupported(
    Sema &S, unsigned BuiltinID, CallExpr *TheCall,
    ArrayRef<llvm::Triple::ObjectFormatType> UnsupportedObjectFormatTypes) {
  llvm::Triple::ObjectFormatType CurObjFormat =
      S.getASTContext().getTargetInfo().getTriple().getObjectFormat();
  if (llvm::is_contained(UnsupportedObjectFormatTypes, CurObjFormat)) {
    S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
        << TheCall->getSourceRange();
    return true;
  }
  return false;
}

// Emit an error and return true if the current architecture is not in the list
// of supported architectures.
static bool
CheckBuiltinTargetInSupported(Sema &S, CallExpr *TheCall,
                              ArrayRef<llvm::Triple::ArchType> SupportedArchs) {
  llvm::Triple::ArchType CurArch =
      S.getASTContext().getTargetInfo().getTriple().getArch();
  if (llvm::is_contained(SupportedArchs, CurArch))
    return false;
  S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
      << TheCall->getSourceRange();
  return true;
}

static void CheckNonNullArgument(Sema &S, const Expr *ArgExpr,
                                 SourceLocation CallSiteLoc);

bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
                                      CallExpr *TheCall) {
  switch (TI.getTriple().getArch()) {
  default:
    // Some builtins don't require additional checking, so just consider these
    // acceptable.
    return false;
  case llvm::Triple::arm:
  case llvm::Triple::armeb:
  case llvm::Triple::thumb:
  case llvm::Triple::thumbeb:
    return ARM().CheckARMBuiltinFunctionCall(TI, BuiltinID, TheCall);
  case llvm::Triple::aarch64:
  case llvm::Triple::aarch64_32:
  case llvm::Triple::aarch64_be:
    return ARM().CheckAArch64BuiltinFunctionCall(TI, BuiltinID, TheCall);
  case llvm::Triple::bpfeb:
  case llvm::Triple::bpfel:
    return BPF().CheckBPFBuiltinFunctionCall(BuiltinID, TheCall);
  case llvm::Triple::dxil:
    return DirectX().CheckDirectXBuiltinFunctionCall(BuiltinID, TheCall);
  case llvm::Triple::hexagon:
    return Hexagon().CheckHexagonBuiltinFunctionCall(BuiltinID, TheCall);
  case llvm::Triple::mips:
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64:
  case llvm::Triple::mips64el:
    return MIPS().CheckMipsBuiltinFunctionCall(TI, BuiltinID, TheCall);
  case llvm::Triple::spirv:
  case llvm::Triple::spirv32:
  case llvm::Triple::spirv64:
    if (TI.getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
      return SPIRV().CheckSPIRVBuiltinFunctionCall(TI, BuiltinID, TheCall);
    return false;
  case llvm::Triple::systemz:
    return SystemZ().CheckSystemZBuiltinFunctionCall(BuiltinID, TheCall);
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    return X86().CheckBuiltinFunctionCall(TI, BuiltinID, TheCall);
  case llvm::Triple::ppc:
  case llvm::Triple::ppcle:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    return PPC().CheckPPCBuiltinFunctionCall(TI, BuiltinID, TheCall);
  case llvm::Triple::amdgcn:
    return AMDGPU().CheckAMDGCNBuiltinFunctionCall(BuiltinID, TheCall);
  case llvm::Triple::riscv32:
  case llvm::Triple::riscv64:
    return RISCV().CheckBuiltinFunctionCall(TI, BuiltinID, TheCall);
  case llvm::Triple::loongarch32:
  case llvm::Triple::loongarch64:
    return LoongArch().CheckLoongArchBuiltinFunctionCall(TI, BuiltinID,
                                                         TheCall);
  case llvm::Triple::wasm32:
  case llvm::Triple::wasm64:
    return Wasm().CheckWebAssemblyBuiltinFunctionCall(TI, BuiltinID, TheCall);
  case llvm::Triple::nvptx:
  case llvm::Triple::nvptx64:
    return NVPTX().CheckNVPTXBuiltinFunctionCall(TI, BuiltinID, TheCall);
  }
}

// Check if \p Ty is a valid type for the elementwise math builtins. If it is
// not a valid type, emit an error message and return true. Otherwise return
// false.
static bool
checkMathBuiltinElementType(Sema &S, SourceLocation Loc, QualType ArgTy,
                            Sema::EltwiseBuiltinArgTyRestriction ArgTyRestr,
                            int ArgOrdinal) {
  QualType EltTy = ArgTy;
  if (auto *VecTy = EltTy->getAs<VectorType>())
    EltTy = VecTy->getElementType();

  switch (ArgTyRestr) {
  case Sema::EltwiseBuiltinArgTyRestriction::None:
    if (!ArgTy->getAs<VectorType>() &&
        !ConstantMatrixType::isValidElementType(ArgTy)) {
      return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
             << ArgOrdinal << /* vector */ 2 << /* integer */ 1 << /* fp */ 1
             << ArgTy;
    }
    break;
  case Sema::EltwiseBuiltinArgTyRestriction::FloatTy:
    if (!EltTy->isRealFloatingType()) {
      return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
             << ArgOrdinal << /* scalar or vector */ 5 << /* no int */ 0
             << /* floating-point */ 1 << ArgTy;
    }
    break;
  case Sema::EltwiseBuiltinArgTyRestriction::IntegerTy:
    if (!EltTy->isIntegerType()) {
      return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
             << ArgOrdinal << /* scalar or vector */ 5 << /* integer */ 1
             << /* no fp */ 0 << ArgTy;
    }
    break;
  case Sema::EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy:
    if (EltTy->isUnsignedIntegerType()) {
      return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
             << 1 << /* scalar or vector */ 5 << /* signed int */ 2
             << /* or fp */ 1 << ArgTy;
    }
    break;
  }

  return false;
}

/// BuiltinCpu{Supports|Is} - Handle __builtin_cpu_{supports|is}(char *).
/// This checks that the target supports the builtin and that the string
/// argument is constant and valid.
static bool BuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
                       const TargetInfo *AuxTI, unsigned BuiltinID) {
  assert((BuiltinID == Builtin::BI__builtin_cpu_supports ||
          BuiltinID == Builtin::BI__builtin_cpu_is) &&
         "Expecting __builtin_cpu_...");

  bool IsCPUSupports = BuiltinID == Builtin::BI__builtin_cpu_supports;
  const TargetInfo *TheTI = &TI;
  auto SupportsBI = [=](const TargetInfo *TInfo) {
    return TInfo && ((IsCPUSupports && TInfo->supportsCpuSupports()) ||
                     (!IsCPUSupports && TInfo->supportsCpuIs()));
  };
  if (!SupportsBI(&TI) && SupportsBI(AuxTI))
    TheTI = AuxTI;

  if ((!IsCPUSupports && !TheTI->supportsCpuIs()) ||
      (IsCPUSupports && !TheTI->supportsCpuSupports()))
    return S.Diag(TheCall->getBeginLoc(),
                  TI.getTriple().isOSAIX()
                      ? diag::err_builtin_aix_os_unsupported
                      : diag::err_builtin_target_unsupported)
           << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());

  Expr *Arg = TheCall->getArg(0)->IgnoreParenImpCasts();
  // Check if the argument is a string literal.
  if (!isa<StringLiteral>(Arg))
    return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
           << Arg->getSourceRange();

  // Check the contents of the string.
  StringRef Feature = cast<StringLiteral>(Arg)->getString();
  if (IsCPUSupports && !TheTI->validateCpuSupports(Feature)) {
    S.Diag(TheCall->getBeginLoc(), diag::warn_invalid_cpu_supports)
        << Arg->getSourceRange();
    return false;
  }
  if (!IsCPUSupports && !TheTI->validateCpuIs(Feature))
    return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is)
           << Arg->getSourceRange();
  return false;
}

/// Checks that __builtin_popcountg was called with a single argument, which is
/// an unsigned integer.
static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCount(TheCall, 1))
    return true;

  ExprResult ArgRes = S.DefaultLvalueConversion(TheCall->getArg(0));
  if (ArgRes.isInvalid())
    return true;

  Expr *Arg = ArgRes.get();
  TheCall->setArg(0, Arg);

  QualType ArgTy = Arg->getType();

  if (!ArgTy->isUnsignedIntegerType()) {
    S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
        << 1 << /* scalar */ 1 << /* unsigned integer ty */ 3 << /* no fp */ 0
        << ArgTy;
    return true;
  }
  return false;
}

/// Checks that __builtin_{clzg,ctzg} was called with a first argument, which is
/// an unsigned integer, and an optional second argument, which is promoted to
/// an 'int'.
static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) {
  if (S.checkArgCountRange(TheCall, 1, 2))
    return true;

  ExprResult Arg0Res = S.DefaultLvalueConversion(TheCall->getArg(0));
  if (Arg0Res.isInvalid())
    return true;

  Expr *Arg0 = Arg0Res.get();
  TheCall->setArg(0, Arg0);

  QualType Arg0Ty = Arg0->getType();

  if (!Arg0Ty->isUnsignedIntegerType()) {
    S.Diag(Arg0->getBeginLoc(), diag::err_builtin_invalid_arg_type)
        << 1 << /* scalar */ 1 << /* unsigned integer ty */ 3 << /* no fp */ 0
        << Arg0Ty;
    return true;
  }

  if (TheCall->getNumArgs() > 1) {
    ExprResult Arg1Res = S.UsualUnaryConversions(TheCall->getArg(1));
    if (Arg1Res.isInvalid())
      return true;

    Expr *Arg1 = Arg1Res.get();
    TheCall->setArg(1, Arg1);

    QualType Arg1Ty = Arg1->getType();

    if (!Arg1Ty->isSpecificBuiltinType(BuiltinType::Int)) {
      S.Diag(Arg1->getBeginLoc(), diag::err_builtin_invalid_arg_type)
          << 2 << /* scalar */ 1 << /* 'int' ty */ 4 << /* no fp */ 0 << Arg1Ty;
      return true;
    }
  }

  return false;
}

ExprResult
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
                               CallExpr *TheCall) {
  ExprResult TheCallResult(TheCall);

  // Find out if any arguments are required to be integer constant expressions.
  unsigned ICEArguments = 0;
  ASTContext::GetBuiltinTypeError Error;
  Context.GetBuiltinType(BuiltinID, Error, &ICEArguments);
  if (Error != ASTContext::GE_None)
    ICEArguments = 0;  // Don't diagnose previously diagnosed errors.

  // If any arguments are required to be ICE's, check and diagnose.
  for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) {
    // Skip arguments not required to be ICE's.
    if ((ICEArguments & (1 << ArgNo)) == 0) continue;

    llvm::APSInt Result;
    // If we don't have enough arguments, continue so we can issue better
    // diagnostic in checkArgCount(...)
    if (ArgNo < TheCall->getNumArgs() &&
        BuiltinConstantArg(TheCall, ArgNo, Result))
      return true;
    ICEArguments &= ~(1 << ArgNo);
  }

  FPOptions FPO;
  switch (BuiltinID) {
  case Builtin::BI__builtin_cpu_supports:
  case Builtin::BI__builtin_cpu_is:
    if (BuiltinCpu(*this, Context.getTargetInfo(), TheCall,
                   Context.getAuxTargetInfo(), BuiltinID))
      return ExprError();
    break;
  case Builtin::BI__builtin_cpu_init:
    if (!Context.getTargetInfo().supportsCpuInit()) {
      Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
          << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
      return ExprError();
    }
    break;
  case Builtin::BI__builtin___CFStringMakeConstantString:
    // CFStringMakeConstantString is currently not implemented for GOFF (i.e.,
    // on z/OS) and for XCOFF (i.e., on AIX). Emit unsupported
    if (CheckBuiltinTargetNotInUnsupported(
            *this, BuiltinID, TheCall,
            {llvm::Triple::GOFF, llvm::Triple::XCOFF}))
      return ExprError();
    assert(TheCall->getNumArgs() == 1 &&
           "Wrong # arguments to builtin CFStringMakeConstantString");
    if (ObjC().CheckObjCString(TheCall->getArg(0)))
      return ExprError();
    break;
  case Builtin::BI__builtin_ms_va_start:
  case Builtin::BI__builtin_stdarg_start:
  case Builtin::BI__builtin_va_start:
  case Builtin::BI__builtin_c23_va_start:
    if (BuiltinVAStart(BuiltinID, TheCall))
      return ExprError();
    break;
  case Builtin::BI__va_start: {
    switch (Context.getTargetInfo().getTriple().getArch()) {
    case llvm::Triple::aarch64:
    case llvm::Triple::arm:
    case llvm::Triple::thumb:
      if (BuiltinVAStartARMMicrosoft(TheCall))
        return ExprError();
      break;
    default:
      if (BuiltinVAStart(BuiltinID, TheCall))
        return ExprError();
      break;
    }
    break;
  }

  // The acquire, release, and no fence variants are ARM and AArch64 only.
  case Builtin::BI_interlockedbittestandset_acq:
  case Builtin::BI_interlockedbittestandset_rel:
  case Builtin::BI_interlockedbittestandset_nf:
  case Builtin::BI_interlockedbittestandreset_acq:
  case Builtin::BI_interlockedbittestandreset_rel:
  case Builtin::BI_interlockedbittestandreset_nf:
    if (CheckBuiltinTargetInSupported(
            *this, TheCall,
            {llvm::Triple::arm, llvm::Triple::thumb, llvm::Triple::aarch64}))
      return ExprError();
    break;

  // The 64-bit bittest variants are x64, ARM, and AArch64 only.
  case Builtin::BI_bittest64:
  case Builtin::BI_bittestandcomplement64:
  case Builtin::BI_bittestandreset64:
  case Builtin::BI_bittestandset64:
  case Builtin::BI_interlockedbittestandreset64:
  case Builtin::BI_interlockedbittestandset64:
    if (CheckBuiltinTargetInSupported(
            *this, TheCall,
            {llvm::Triple::x86_64, llvm::Triple::arm, llvm::Triple::thumb,
             llvm::Triple::aarch64, llvm::Triple::amdgcn}))
      return ExprError();
    break;

  case Builtin::BI__builtin_set_flt_rounds:
    if (CheckBuiltinTargetInSupported(
            *this, TheCall,
            {llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::arm,
             llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn,
             llvm::Triple::ppc, llvm::Triple::ppc64, llvm::Triple::ppcle,
             llvm::Triple::ppc64le}))
      return ExprError();
    break;

  case Builtin::BI__builtin_isgreater:
  case Builtin::BI__builtin_isgreaterequal:
  case Builtin::BI__builtin_isless:
  case Builtin::BI__builtin_islessequal:
  case Builtin::BI__builtin_islessgreater:
  case Builtin::BI__builtin_isunordered:
    if (BuiltinUnorderedCompare(TheCall, BuiltinID))
      return ExprError();
    break;
  case Builtin::BI__builtin_fpclassify:
    if (BuiltinFPClassification(TheCall, 6, BuiltinID))
      return ExprError();
    break;
  case Builtin::BI__builtin_isfpclass:
    if (BuiltinFPClassification(TheCall, 2, BuiltinID))
      return ExprError();
    break;
  case Builtin::BI__builtin_isfinite:
  case Builtin::BI__builtin_isinf:
  case Builtin::BI__builtin_isinf_sign:
  case Builtin::BI__builtin_isnan:
  case Builtin::BI__builtin_issignaling:
  case Builtin::BI__builtin_isnormal:
  case Builtin::BI__builtin_issubnormal:
  case Builtin::BI__builtin_iszero:
  case Builtin::BI__builtin_signbit:
  case Builtin::BI__builtin_signbitf:
  case Builtin::BI__builtin_signbitl:
    if (BuiltinFPClassification(TheCall, 1, BuiltinID))
      return ExprError();
    break;
  case Builtin::BI__builtin_shufflevector:
    return BuiltinShuffleVector(TheCall);
    // TheCall will be freed by the smart pointer here, but that's fine, since
    // BuiltinShuffleVector guts it, but then doesn't release it.
  case Builtin::BI__builtin_prefetch:
    if (BuiltinPrefetch(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_alloca_with_align:
  case Builtin::BI__builtin_alloca_with_align_uninitialized:
    if (BuiltinAllocaWithAlign(TheCall))
      return ExprError();
    [[fallthrough]];
  case Builtin::BI__builtin_alloca:
  case Builtin::BI__builtin_alloca_uninitialized:
    Diag(TheCall->getBeginLoc(), diag::warn_alloca)
        << TheCall->getDirectCallee();
    if (getLangOpts().OpenCL) {
      builtinAllocaAddrSpace(*this, TheCall);
    }
    break;
  case Builtin::BI__arithmetic_fence:
    if (BuiltinArithmeticFence(TheCall))
      return ExprError();
    break;
  case Builtin::BI__assume:
  case Builtin::BI__builtin_assume:
    if (BuiltinAssume(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_assume_aligned:
    if (BuiltinAssumeAligned(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_dynamic_object_size:
  case Builtin::BI__builtin_object_size:
    if (BuiltinConstantArgRange(TheCall, 1, 0, 3))
      return ExprError();
    break;
  case Builtin::BI__builtin_longjmp:
    if (BuiltinLongjmp(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_setjmp:
    if (BuiltinSetjmp(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_classify_type:
    if (checkArgCount(TheCall, 1))
      return true;
    TheCall->setType(Context.IntTy);
    break;
  case Builtin::BI__builtin_complex:
    if (BuiltinComplex(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_constant_p: {
    if (checkArgCount(TheCall, 1))
      return true;
    ExprResult Arg = DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
    if (Arg.isInvalid()) return true;
    TheCall->setArg(0, Arg.get());
    TheCall->setType(Context.IntTy);
    break;
  }
  case Builtin::BI__builtin_launder:
    return BuiltinLaunder(*this, TheCall);
  case Builtin::BI__builtin_is_within_lifetime:
    return BuiltinIsWithinLifetime(*this, TheCall);
  case Builtin::BI__builtin_trivially_relocate:
    return BuiltinTriviallyRelocate(*this, TheCall);

  case Builtin::BI__sync_fetch_and_add:
  case Builtin::BI__sync_fetch_and_add_1:
  case Builtin::BI__sync_fetch_and_add_2:
  case Builtin::BI__sync_fetch_and_add_4:
  case Builtin::BI__sync_fetch_and_add_8:
  case Builtin::BI__sync_fetch_and_add_16:
  case Builtin::BI__sync_fetch_and_sub:
  case Builtin::BI__sync_fetch_and_sub_1:
  case Builtin::BI__sync_fetch_and_sub_2:
  case Builtin::BI__sync_fetch_and_sub_4:
  case Builtin::BI__sync_fetch_and_sub_8:
  case Builtin::BI__sync_fetch_and_sub_16:
  case Builtin::BI__sync_fetch_and_or:
  case Builtin::BI__sync_fetch_and_or_1:
  case Builtin::BI__sync_fetch_and_or_2:
  case Builtin::BI__sync_fetch_and_or_4:
  case Builtin::BI__sync_fetch_and_or_8:
  case Builtin::BI__sync_fetch_and_or_16:
  case Builtin::BI__sync_fetch_and_and:
  case Builtin::BI__sync_fetch_and_and_1:
  case Builtin::BI__sync_fetch_and_and_2:
  case Builtin::BI__sync_fetch_and_and_4:
  case Builtin::BI__sync_fetch_and_and_8:
  case Builtin::BI__sync_fetch_and_and_16:
  case Builtin::BI__sync_fetch_and_xor:
  case Builtin::BI__sync_fetch_and_xor_1:
  case Builtin::BI__sync_fetch_and_xor_2:
  case Builtin::BI__sync_fetch_and_xor_4:
  case Builtin::BI__sync_fetch_and_xor_8:
  case Builtin::BI__sync_fetch_and_xor_16:
  case Builtin::BI__sync_fetch_and_nand:
  case Builtin::BI__sync_fetch_and_nand_1:
  case Builtin::BI__sync_fetch_and_nand_2:
  case Builtin::BI__sync_fetch_and_nand_4:
  case Builtin::BI__sync_fetch_and_nand_8:
  case Builtin::BI__sync_fetch_and_nand_16:
  case Builtin::BI__sync_add_and_fetch:
  case Builtin::BI__sync_add_and_fetch_1:
  case Builtin::BI__sync_add_and_fetch_2:
  case Builtin::BI__sync_add_and_fetch_4:
  case Builtin::BI__sync_add_and_fetch_8:
  case Builtin::BI__sync_add_and_fetch_16:
  case Builtin::BI__sync_sub_and_fetch:
  case Builtin::BI__sync_sub_and_fetch_1:
  case Builtin::BI__sync_sub_and_fetch_2:
  case Builtin::BI__sync_sub_and_fetch_4:
  case Builtin::BI__sync_sub_and_fetch_8:
  case Builtin::BI__sync_sub_and_fetch_16:
  case Builtin::BI__sync_and_and_fetch:
  case Builtin::BI__sync_and_and_fetch_1:
  case Builtin::BI__sync_and_and_fetch_2:
  case Builtin::BI__sync_and_and_fetch_4:
  case Builtin::BI__sync_and_and_fetch_8:
  case Builtin::BI__sync_and_and_fetch_16:
  case Builtin::BI__sync_or_and_fetch:
  case Builtin::BI__sync_or_and_fetch_1:
  case Builtin::BI__sync_or_and_fetch_2:
  case Builtin::BI__sync_or_and_fetch_4:
  case Builtin::BI__sync_or_and_fetch_8:
  case Builtin::BI__sync_or_and_fetch_16:
  case Builtin::BI__sync_xor_and_fetch:
  case Builtin::BI__sync_xor_and_fetch_1:
  case Builtin::BI__sync_xor_and_fetch_2:
  case Builtin::BI__sync_xor_and_fetch_4:
  case Builtin::BI__sync_xor_and_fetch_8:
  case Builtin::BI__sync_xor_and_fetch_16:
  case Builtin::BI__sync_nand_and_fetch:
  case Builtin::BI__sync_nand_and_fetch_1:
  case Builtin::BI__sync_nand_and_fetch_2:
  case Builtin::BI__sync_nand_and_fetch_4:
  case Builtin::BI__sync_nand_and_fetch_8:
  case Builtin::BI__sync_nand_and_fetch_16:
  case Builtin::BI__sync_val_compare_and_swap:
  case Builtin::BI__sync_val_compare_and_swap_1:
  case Builtin::BI__sync_val_compare_and_swap_2:
  case Builtin::BI__sync_val_compare_and_swap_4:
  case Builtin::BI__sync_val_compare_and_swap_8:
  case Builtin::BI__sync_val_compare_and_swap_16:
  case Builtin::BI__sync_bool_compare_and_swap:
  case Builtin::BI__sync_bool_compare_and_swap_1:
  case Builtin::BI__sync_bool_compare_and_swap_2:
  case Builtin::BI__sync_bool_compare_and_swap_4:
  case Builtin::BI__sync_bool_compare_and_swap_8:
  case Builtin::BI__sync_bool_compare_and_swap_16:
  case Builtin::BI__sync_lock_test_and_set:
  case Builtin::BI__sync_lock_test_and_set_1:
  case Builtin::BI__sync_lock_test_and_set_2:
  case Builtin::BI__sync_lock_test_and_set_4:
  case Builtin::BI__sync_lock_test_and_set_8:
  case Builtin::BI__sync_lock_test_and_set_16:
  case Builtin::BI__sync_lock_release:
  case Builtin::BI__sync_lock_release_1:
  case Builtin::BI__sync_lock_release_2:
  case Builtin::BI__sync_lock_release_4:
  case Builtin::BI__sync_lock_release_8:
  case Builtin::BI__sync_lock_release_16:
  case Builtin::BI__sync_swap:
  case Builtin::BI__sync_swap_1:
  case Builtin::BI__sync_swap_2:
  case Builtin::BI__sync_swap_4:
  case Builtin::BI__sync_swap_8:
  case Builtin::BI__sync_swap_16:
    return BuiltinAtomicOverloaded(TheCallResult);
  case Builtin::BI__sync_synchronize:
    Diag(TheCall->getBeginLoc(), diag::warn_atomic_implicit_seq_cst)
        << TheCall->getCallee()->getSourceRange();
    break;
  case Builtin::BI__builtin_nontemporal_load:
  case Builtin::BI__builtin_nontemporal_store:
    return BuiltinNontemporalOverloaded(TheCallResult);
  case Builtin::BI__builtin_memcpy_inline: {
    clang::Expr *SizeOp = TheCall->getArg(2);
    // We warn about copying to or from `nullptr` pointers when `size` is
    // greater than 0. When `size` is value dependent we cannot evaluate its
    // value so we bail out.
    if (SizeOp->isValueDependent())
      break;
    if (!SizeOp->EvaluateKnownConstInt(Context).isZero()) {
      CheckNonNullArgument(*this, TheCall->getArg(0), TheCall->getExprLoc());
      CheckNonNullArgument(*this, TheCall->getArg(1), TheCall->getExprLoc());
    }
    break;
  }
  case Builtin::BI__builtin_memset_inline: {
    clang::Expr *SizeOp = TheCall->getArg(2);
    // We warn about filling to `nullptr` pointers when `size` is greater than
    // 0. When `size` is value dependent we cannot evaluate its value so we bail
    // out.
    if (SizeOp->isValueDependent())
      break;
    if (!SizeOp->EvaluateKnownConstInt(Context).isZero())
      CheckNonNullArgument(*this, TheCall->getArg(0), TheCall->getExprLoc());
    break;
  }
#define ATOMIC_BUILTIN(ID, TYPE, ATTRS)                                        \
  case Builtin::BI##ID:                                                        \
    return AtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID);
#include "clang/Basic/Builtins.inc"
  case Builtin::BI__annotation:
    if (BuiltinMSVCAnnotation(*this, TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_annotation:
    if (BuiltinAnnotation(*this, TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_addressof:
    if (BuiltinAddressof(*this, TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_function_start:
    if (BuiltinFunctionStart(*this, TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_is_aligned:
  case Builtin::BI__builtin_align_up:
  case Builtin::BI__builtin_align_down:
    if (BuiltinAlignment(*this, TheCall, BuiltinID))
      return ExprError();
    break;
  case Builtin::BI__builtin_add_overflow:
  case Builtin::BI__builtin_sub_overflow:
  case Builtin::BI__builtin_mul_overflow:
    if (BuiltinOverflow(*this, TheCall, BuiltinID))
      return ExprError();
    break;
  case Builtin::BI__builtin_operator_new:
  case Builtin::BI__builtin_operator_delete: {
    bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete;
    ExprResult Res =
        BuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete);
    if (Res.isInvalid())
      CorrectDelayedTyposInExpr(TheCallResult.get());
    return Res;
  }
  case Builtin::BI__builtin_dump_struct:
    return BuiltinDumpStruct(*this, TheCall);
  case Builtin::BI__builtin_expect_with_probability: {
    // We first want to ensure we are called with 3 arguments
    if (checkArgCount(TheCall, 3))
      return ExprError();
    // then check probability is constant float in range [0.0, 1.0]
    const Expr *ProbArg = TheCall->getArg(2);
    SmallVector<PartialDiagnosticAt, 8> Notes;
    Expr::EvalResult Eval;
    Eval.Diag = &Notes;
    if ((!ProbArg->EvaluateAsConstantExpr(Eval, Context)) ||
        !Eval.Val.isFloat()) {
      Diag(ProbArg->getBeginLoc(), diag::err_probability_not_constant_float)
          << ProbArg->getSourceRange();
      for (const PartialDiagnosticAt &PDiag : Notes)
        Diag(PDiag.first, PDiag.second);
      return ExprError();
    }
    llvm::APFloat Probability = Eval.Val.getFloat();
    bool LoseInfo = false;
    Probability.convert(llvm::APFloat::IEEEdouble(),
                        llvm::RoundingMode::Dynamic, &LoseInfo);
    if (!(Probability >= llvm::APFloat(0.0) &&
          Probability <= llvm::APFloat(1.0))) {
      Diag(ProbArg->getBeginLoc(), diag::err_probability_out_of_range)
          << ProbArg->getSourceRange();
      return ExprError();
    }
    break;
  }
  case Builtin::BI__builtin_preserve_access_index:
    if (BuiltinPreserveAI(*this, TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_call_with_static_chain:
    if (BuiltinCallWithStaticChain(*this, TheCall))
      return ExprError();
    break;
  case Builtin::BI__exception_code:
  case Builtin::BI_exception_code:
    if (BuiltinSEHScopeCheck(*this, TheCall, Scope::SEHExceptScope,
                             diag::err_seh___except_block))
      return ExprError();
    break;
  case Builtin::BI__exception_info:
  case Builtin::BI_exception_info:
    if (BuiltinSEHScopeCheck(*this, TheCall, Scope::SEHFilterScope,
                             diag::err_seh___except_filter))
      return ExprError();
    break;
  case Builtin::BI__GetExceptionInfo:
    if (checkArgCount(TheCall, 1))
      return ExprError();

    if (CheckCXXThrowOperand(
            TheCall->getBeginLoc(),
            Context.getExceptionObjectType(FDecl->getParamDecl(0)->getType()),
            TheCall))
      return ExprError();

    TheCall->setType(Context.VoidPtrTy);
    break;
  case Builtin::BIaddressof:
  case Builtin::BI__addressof:
  case Builtin::BIforward:
  case Builtin::BIforward_like:
  case Builtin::BImove:
  case Builtin::BImove_if_noexcept:
  case Builtin::BIas_const: {
    // These are all expected to be of the form
    //   T &/&&/* f(U &/&&)
    // where T and U only differ in qualification.
    if (checkArgCount(TheCall, 1))
      return ExprError();
    QualType Param = FDecl->getParamDecl(0)->getType();
    QualType Result = FDecl->getReturnType();
    bool ReturnsPointer = BuiltinID == Builtin::BIaddressof ||
                          BuiltinID == Builtin::BI__addressof;
    if (!(Param->isReferenceType() &&
          (ReturnsPointer ? Result->isAnyPointerType()
                          : Result->isReferenceType()) &&
          Context.hasSameUnqualifiedType(Param->getPointeeType(),
                                         Result->getPointeeType()))) {
      Diag(TheCall->getBeginLoc(), diag::err_builtin_move_forward_unsupported)
          << FDecl;
      return ExprError();
    }
    break;
  }
  case Builtin::BI__builtin_ptrauth_strip:
    return PointerAuthStrip(*this, TheCall);
  case Builtin::BI__builtin_ptrauth_blend_discriminator:
    return PointerAuthBlendDiscriminator(*this, TheCall);
  case Builtin::BI__builtin_ptrauth_sign_constant:
    return PointerAuthSignOrAuth(*this, TheCall, PAO_Sign,
                                 /*RequireConstant=*/true);
  case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
    return PointerAuthSignOrAuth(*this, TheCall, PAO_Sign,
                                 /*RequireConstant=*/false);
  case Builtin::BI__builtin_ptrauth_auth:
    return PointerAuthSignOrAuth(*this, TheCall, PAO_Auth,
                                 /*RequireConstant=*/false);
  case Builtin::BI__builtin_ptrauth_sign_generic_data:
    return PointerAuthSignGenericData(*this, TheCall);
  case Builtin::BI__builtin_ptrauth_auth_and_resign:
    return PointerAuthAuthAndResign(*this, TheCall);
  case Builtin::BI__builtin_ptrauth_string_discriminator:
    return PointerAuthStringDiscriminator(*this, TheCall);
  // OpenCL v2.0, s6.13.16 - Pipe functions
  case Builtin::BIread_pipe:
  case Builtin::BIwrite_pipe:
    // Since those two functions are declared with var args, we need a semantic
    // check for the argument.
    if (OpenCL().checkBuiltinRWPipe(TheCall))
      return ExprError();
    break;
  case Builtin::BIreserve_read_pipe:
  case Builtin::BIreserve_write_pipe:
  case Builtin::BIwork_group_reserve_read_pipe:
  case Builtin::BIwork_group_reserve_write_pipe:
    if (OpenCL().checkBuiltinReserveRWPipe(TheCall))
      return ExprError();
    break;
  case Builtin::BIsub_group_reserve_read_pipe:
  case Builtin::BIsub_group_reserve_write_pipe:
    if (OpenCL().checkSubgroupExt(TheCall) ||
        OpenCL().checkBuiltinReserveRWPipe(TheCall))
      return ExprError();
    break;
  case Builtin::BIcommit_read_pipe:
  case Builtin::BIcommit_write_pipe:
  case Builtin::BIwork_group_commit_read_pipe:
  case Builtin::BIwork_group_commit_write_pipe:
    if (OpenCL().checkBuiltinCommitRWPipe(TheCall))
      return ExprError();
    break;
  case Builtin::BIsub_group_commit_read_pipe:
  case Builtin::BIsub_group_commit_write_pipe:
    if (OpenCL().checkSubgroupExt(TheCall) ||
        OpenCL().checkBuiltinCommitRWPipe(TheCall))
      return ExprError();
    break;
  case Builtin::BIget_pipe_num_packets:
  case Builtin::BIget_pipe_max_packets:
    if (OpenCL().checkBuiltinPipePackets(TheCall))
      return ExprError();
    break;
  case Builtin::BIto_global:
  case Builtin::BIto_local:
  case Builtin::BIto_private:
    if (OpenCL().checkBuiltinToAddr(BuiltinID, TheCall))
      return ExprError();
    break;
  // OpenCL v2.0, s6.13.17 - Enqueue kernel functions.
  case Builtin::BIenqueue_kernel:
    if (OpenCL().checkBuiltinEnqueueKernel(TheCall))
      return ExprError();
    break;
  case Builtin::BIget_kernel_work_group_size:
  case Builtin::BIget_kernel_preferred_work_group_size_multiple:
    if (OpenCL().checkBuiltinKernelWorkGroupSize(TheCall))
      return ExprError();
    break;
  case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
  case Builtin::BIget_kernel_sub_group_count_for_ndrange:
    if (OpenCL().checkBuiltinNDRangeAndBlock(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_os_log_format:
    Cleanup.setExprNeedsCleanups(true);
    [[fallthrough]];
  case Builtin::BI__builtin_os_log_format_buffer_size:
    if (BuiltinOSLogFormat(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_frame_address:
  case Builtin::BI__builtin_return_address: {
    if (BuiltinConstantArgRange(TheCall, 0, 0, 0xFFFF))
      return ExprError();

    // -Wframe-address warning if non-zero passed to builtin
    // return/frame address.
    Expr::EvalResult Result;
    if (!TheCall->getArg(0)->isValueDependent() &&
        TheCall->getArg(0)->EvaluateAsInt(Result, getASTContext()) &&
        Result.Val.getInt() != 0)
      Diag(TheCall->getBeginLoc(), diag::warn_frame_address)
          << ((BuiltinID == Builtin::BI__builtin_return_address)
                  ? "__builtin_return_address"
                  : "__builtin_frame_address")
          << TheCall->getSourceRange();
    break;
  }

  case Builtin::BI__builtin_nondeterministic_value: {
    if (BuiltinNonDeterministicValue(TheCall))
      return ExprError();
    break;
  }

  // __builtin_elementwise_abs restricts the element type to signed integers or
  // floating point types only.
  case Builtin::BI__builtin_elementwise_abs:
    if (PrepareBuiltinElementwiseMathOneArgCall(
            TheCall, EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy))
      return ExprError();
    break;

  // These builtins restrict the element type to floating point
  // types only.
  case Builtin::BI__builtin_elementwise_acos:
  case Builtin::BI__builtin_elementwise_asin:
  case Builtin::BI__builtin_elementwise_atan:
  case Builtin::BI__builtin_elementwise_ceil:
  case Builtin::BI__builtin_elementwise_cos:
  case Builtin::BI__builtin_elementwise_cosh:
  case Builtin::BI__builtin_elementwise_exp:
  case Builtin::BI__builtin_elementwise_exp2:
  case Builtin::BI__builtin_elementwise_exp10:
  case Builtin::BI__builtin_elementwise_floor:
  case Builtin::BI__builtin_elementwise_log:
  case Builtin::BI__builtin_elementwise_log2:
  case Builtin::BI__builtin_elementwise_log10:
  case Builtin::BI__builtin_elementwise_roundeven:
  case Builtin::BI__builtin_elementwise_round:
  case Builtin::BI__builtin_elementwise_rint:
  case Builtin::BI__builtin_elementwise_nearbyint:
  case Builtin::BI__builtin_elementwise_sin:
  case Builtin::BI__builtin_elementwise_sinh:
  case Builtin::BI__builtin_elementwise_sqrt:
  case Builtin::BI__builtin_elementwise_tan:
  case Builtin::BI__builtin_elementwise_tanh:
  case Builtin::BI__builtin_elementwise_trunc:
  case Builtin::BI__builtin_elementwise_canonicalize:
    if (PrepareBuiltinElementwiseMathOneArgCall(
            TheCall, EltwiseBuiltinArgTyRestriction::FloatTy))
      return ExprError();
    break;
  case Builtin::BI__builtin_elementwise_fma:
    if (BuiltinElementwiseTernaryMath(TheCall))
      return ExprError();
    break;

  // These builtins restrict the element type to floating point
  // types only, and take in two arguments.
  case Builtin::BI__builtin_elementwise_minnum:
  case Builtin::BI__builtin_elementwise_maxnum:
  case Builtin::BI__builtin_elementwise_minimum:
  case Builtin::BI__builtin_elementwise_maximum:
  case Builtin::BI__builtin_elementwise_atan2:
  case Builtin::BI__builtin_elementwise_fmod:
  case Builtin::BI__builtin_elementwise_pow:
    if (BuiltinElementwiseMath(TheCall,
                               EltwiseBuiltinArgTyRestriction::FloatTy))
      return ExprError();
    break;
  // These builtins restrict the element type to integer
  // types only.
  case Builtin::BI__builtin_elementwise_add_sat:
  case Builtin::BI__builtin_elementwise_sub_sat:
    if (BuiltinElementwiseMath(TheCall,
                               EltwiseBuiltinArgTyRestriction::IntegerTy))
      return ExprError();
    break;
  case Builtin::BI__builtin_elementwise_min:
  case Builtin::BI__builtin_elementwise_max:
    if (BuiltinElementwiseMath(TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_elementwise_popcount:
  case Builtin::BI__builtin_elementwise_bitreverse:
    if (PrepareBuiltinElementwiseMathOneArgCall(
            TheCall, EltwiseBuiltinArgTyRestriction::IntegerTy))
      return ExprError();
    break;
  case Builtin::BI__builtin_elementwise_copysign: {
    if (checkArgCount(TheCall, 2))
      return ExprError();

    ExprResult Magnitude = UsualUnaryConversions(TheCall->getArg(0));
    ExprResult Sign = UsualUnaryConversions(TheCall->getArg(1));
    if (Magnitude.isInvalid() || Sign.isInvalid())
      return ExprError();

    QualType MagnitudeTy = Magnitude.get()->getType();
    QualType SignTy = Sign.get()->getType();
    if (checkMathBuiltinElementType(
            *this, TheCall->getArg(0)->getBeginLoc(), MagnitudeTy,
            EltwiseBuiltinArgTyRestriction::FloatTy, 1) ||
        checkMathBuiltinElementType(
            *this, TheCall->getArg(1)->getBeginLoc(), SignTy,
            EltwiseBuiltinArgTyRestriction::FloatTy, 2)) {
      return ExprError();
    }

    if (MagnitudeTy.getCanonicalType() != SignTy.getCanonicalType()) {
      return Diag(Sign.get()->getBeginLoc(),
                  diag::err_typecheck_call_different_arg_types)
             << MagnitudeTy << SignTy;
    }

    TheCall->setArg(0, Magnitude.get());
    TheCall->setArg(1, Sign.get());
    TheCall->setType(Magnitude.get()->getType());
    break;
  }
  case Builtin::BI__builtin_reduce_max:
  case Builtin::BI__builtin_reduce_min: {
    if (PrepareBuiltinReduceMathOneArgCall(TheCall))
      return ExprError();

    const Expr *Arg = TheCall->getArg(0);
    const auto *TyA = Arg->getType()->getAs<VectorType>();

    QualType ElTy;
    if (TyA)
      ElTy = TyA->getElementType();
    else if (Arg->getType()->isSizelessVectorType())
      ElTy = Arg->getType()->getSizelessVectorEltType(Context);

    if (ElTy.isNull()) {
      Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
          << 1 << /* vector ty */ 2 << /* no int */ 0 << /* no fp */ 0
          << Arg->getType();
      return ExprError();
    }

    TheCall->setType(ElTy);
    break;
  }
  case Builtin::BI__builtin_reduce_maximum:
  case Builtin::BI__builtin_reduce_minimum: {
    if (PrepareBuiltinReduceMathOneArgCall(TheCall))
      return ExprError();

    const Expr *Arg = TheCall->getArg(0);
    const auto *TyA = Arg->getType()->getAs<VectorType>();

    QualType ElTy;
    if (TyA)
      ElTy = TyA->getElementType();
    else if (Arg->getType()->isSizelessVectorType())
      ElTy = Arg->getType()->getSizelessVectorEltType(Context);

    if (ElTy.isNull() || !ElTy->isFloatingType()) {
      Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
          << 1 << /* vector of */ 4 << /* no int */ 0 << /* fp */ 1
          << Arg->getType();
      return ExprError();
    }

    TheCall->setType(ElTy);
    break;
  }

  // These builtins support vectors of integers only.
  // TODO: ADD/MUL should support floating-point types.
  case Builtin::BI__builtin_reduce_add:
  case Builtin::BI__builtin_reduce_mul:
  case Builtin::BI__builtin_reduce_xor:
  case Builtin::BI__builtin_reduce_or:
  case Builtin::BI__builtin_reduce_and: {
    if (PrepareBuiltinReduceMathOneArgCall(TheCall))
      return ExprError();

    const Expr *Arg = TheCall->getArg(0);
    const auto *TyA = Arg->getType()->getAs<VectorType>();

    QualType ElTy;
    if (TyA)
      ElTy = TyA->getElementType();
    else if (Arg->getType()->isSizelessVectorType())
      ElTy = Arg->getType()->getSizelessVectorEltType(Context);

    if (ElTy.isNull() || !ElTy->isIntegerType()) {
      Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
          << 1 << /* vector of */ 4 << /* int */ 1 << /* no fp */ 0
          << Arg->getType();
      return ExprError();
    }

    TheCall->setType(ElTy);
    break;
  }

  case Builtin::BI__builtin_matrix_transpose:
    return BuiltinMatrixTranspose(TheCall, TheCallResult);

  case Builtin::BI__builtin_matrix_column_major_load:
    return BuiltinMatrixColumnMajorLoad(TheCall, TheCallResult);

  case Builtin::BI__builtin_matrix_column_major_store:
    return BuiltinMatrixColumnMajorStore(TheCall, TheCallResult);

  case Builtin::BI__builtin_verbose_trap:
    if (!checkBuiltinVerboseTrap(TheCall, *this))
      return ExprError();
    break;

  case Builtin::BI__builtin_get_device_side_mangled_name: {
    auto Check = [](CallExpr *TheCall) {
      if (TheCall->getNumArgs() != 1)
        return false;
      auto *DRE = dyn_cast<DeclRefExpr>(TheCall->getArg(0)->IgnoreImpCasts());
      if (!DRE)
        return false;
      auto *D = DRE->getDecl();
      if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D))
        return false;
      return D->hasAttr<CUDAGlobalAttr>() || D->hasAttr<CUDADeviceAttr>() ||
             D->hasAttr<CUDAConstantAttr>() || D->hasAttr<HIPManagedAttr>();
    };
    if (!Check(TheCall)) {
      Diag(TheCall->getBeginLoc(),
           diag::err_hip_invalid_args_builtin_mangled_name);
      return ExprError();
    }
    break;
  }
  case Builtin::BI__builtin_popcountg:
    if (BuiltinPopcountg(*this, TheCall))
      return ExprError();
    break;
  case Builtin::BI__builtin_clzg:
  case Builtin::BI__builtin_ctzg:
    if (BuiltinCountZeroBitsGeneric(*this, TheCall))
      return ExprError();
    break;

  case Builtin::BI__builtin_allow_runtime_check: {
    Expr *Arg = TheCall->getArg(0);
    // Check if the argument is a string literal.
    if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts())) {
      Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
          << Arg->getSourceRange();
      return ExprError();
    }
    break;
  }
  case Builtin::BI__builtin_counted_by_ref:
    if (BuiltinCountedByRef(TheCall))
      return ExprError();
    break;
  }

  if (getLangOpts().HLSL && HLSL().CheckBuiltinFunctionCall(BuiltinID, TheCall))
    return ExprError();

  // Since the target specific builtins for each arch overlap, only check those
  // of the arch we are compiling for.
  if (Context.BuiltinInfo.isTSBuiltin(BuiltinID)) {
    if (Context.BuiltinInfo.isAuxBuiltinID(BuiltinID)) {
      assert(Context.getAuxTargetInfo() &&
             "Aux Target Builtin, but not an aux target?");

      if (CheckTSBuiltinFunctionCall(
              *Context.getAuxTargetInfo(),
              Context.BuiltinInfo.getAuxBuiltinID(BuiltinID), TheCall))
        return ExprError();
    } else {
      if (CheckTSBuiltinFunctionCall(Context.getTargetInfo(), BuiltinID,
                                     TheCall))
        return ExprError();
    }
  }

  return TheCallResult;
}

bool Sema::ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum) {
  llvm::APSInt Result;
  // We can't check the value of a dependent argument.
  Expr *Arg = TheCall->getArg(ArgNum);
  if (Arg->isTypeDependent() || Arg->isValueDependent())
    return false;

  // Check constant-ness first.
  if (BuiltinConstantArg(TheCall, ArgNum, Result))
    return true;

  // Check contiguous run of 1s, 0xFF0000FF is also a run of 1s.
  if (Result.isShiftedMask() || (~Result).isShiftedMask())
    return false;

  return Diag(TheCall->getBeginLoc(),
              diag::err_argument_not_contiguous_bit_field)
         << ArgNum << Arg->getSourceRange();
}

bool Sema::getFormatStringInfo(const Decl *D, unsigned FormatIdx,
                               unsigned FirstArg, FormatStringInfo *FSI) {
  bool IsCXXMember = false;
  if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
    IsCXXMember = MD->isInstance();
  bool IsVariadic = false;
  if (const FunctionType *FnTy = D->getFunctionType())
    IsVariadic = cast<FunctionProtoType>(FnTy)->isVariadic();
  else if (const auto *BD = dyn_cast<BlockDecl>(D))
    IsVariadic = BD->isVariadic();
  else if (const auto *OMD = dyn_cast<ObjCMethodDecl>(D))
    IsVariadic = OMD->isVariadic();

  return getFormatStringInfo(FormatIdx, FirstArg, IsCXXMember, IsVariadic, FSI);
}

bool Sema::getFormatStringInfo(unsigned FormatIdx, unsigned FirstArg,
                               bool IsCXXMember, bool IsVariadic,
                               FormatStringInfo *FSI) {
  if (FirstArg == 0)
    FSI->ArgPassingKind = FAPK_VAList;
  else if (IsVariadic)
    FSI->ArgPassingKind = FAPK_Variadic;
  else
    FSI->ArgPassingKind = FAPK_Fixed;
  FSI->FormatIdx = FormatIdx - 1;
  FSI->FirstDataArg = FSI->ArgPassingKind == FAPK_VAList ? 0 : FirstArg - 1;

  // The way the format attribute works in GCC, the implicit this argument
  // of member functions is counted. However, it doesn't appear in our own
  // lists, so decrement format_idx in that case.
  if (IsCXXMember) {
    if(FSI->FormatIdx == 0)
      return false;
    --FSI->FormatIdx;
    if (FSI->FirstDataArg != 0)
      --FSI->FirstDataArg;
  }
  return true;
}

/// Checks if a the given expression evaluates to null.
///
/// Returns true if the value evaluates to null.
static bool CheckNonNullExpr(Sema &S, const Expr *Expr) {
  // Treat (smart) pointers constructed from nullptr as null, whether we can
  // const-evaluate them or not.
  // This must happen first: the smart pointer expr might have _Nonnull type!
  if (isa<CXXNullPtrLiteralExpr>(
          IgnoreExprNodes(Expr, IgnoreImplicitAsWrittenSingleStep,
                          IgnoreElidableImplicitConstructorSingleStep)))
    return true;

  // If the expression has non-null type, it doesn't evaluate to null.
  if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability()) {
    if (*nullability == NullabilityKind::NonNull)
      return false;
  }

  // As a special case, transparent unions initialized with zero are
  // considered null for the purposes of the nonnull attribute.
  if (const RecordType *UT = Expr->getType()->getAsUnionType();
      UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) {
    if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(Expr))
      if (const auto *ILE = dyn_cast<InitListExpr>(CLE->getInitializer()))
        Expr = ILE->getInit(0);
  }

  bool Result;
  return (!Expr->isValueDependent() &&
          Expr->EvaluateAsBooleanCondition(Result, S.Context) &&
          !Result);
}

static void CheckNonNullArgument(Sema &S,
                                 const Expr *ArgExpr,
                                 SourceLocation CallSiteLoc) {
  if (CheckNonNullExpr(S, ArgExpr))
    S.DiagRuntimeBehavior(CallSiteLoc, ArgExpr,
                          S.PDiag(diag::warn_null_arg)
                              << ArgExpr->getSourceRange());
}

/// Determine whether the given type has a non-null nullability annotation.
static bool isNonNullType(QualType type) {
  if (auto nullability = type->getNullability())
    return *nullability == NullabilityKind::NonNull;

  return false;
}

static void CheckNonNullArguments(Sema &S,
                                  const NamedDecl *FDecl,
                                  const FunctionProtoType *Proto,
                                  ArrayRef<const Expr *> Args,
                                  SourceLocation CallSiteLoc) {
  assert((FDecl || Proto) && "Need a function declaration or prototype");

  // Already checked by constant evaluator.
  if (S.isConstantEvaluatedContext())
    return;
  // Check the attributes attached to the method/function itself.
  llvm::SmallBitVector NonNullArgs;
  if (FDecl) {
    // Handle the nonnull attribute on the function/method declaration itself.
    for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
      if (!NonNull->args_size()) {
        // Easy case: all pointer arguments are nonnull.
        for (const auto *Arg : Args)
          if (S.isValidPointerAttrType(Arg->getType()))
            CheckNonNullArgument(S, Arg, CallSiteLoc);
        return;
      }

      for (const ParamIdx &Idx : NonNull->args()) {
        unsigned IdxAST = Idx.getASTIndex();
        if (IdxAST >= Args.size())
          continue;
        if (NonNullArgs.empty())
          NonNullArgs.resize(Args.size());
        NonNullArgs.set(IdxAST);
      }
    }
  }

  if (FDecl && (isa<FunctionDecl>(FDecl) || isa<ObjCMethodDecl>(FDecl))) {
    // Handle the nonnull attribute on the parameters of the
    // function/method.
    ArrayRef<ParmVarDecl*> parms;
    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl))
      parms = FD->parameters();
    else
      parms = cast<ObjCMethodDecl>(FDecl)->parameters();

    unsigned ParamIndex = 0;
    for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end();
         I != E; ++I, ++ParamIndex) {
      const ParmVarDecl *PVD = *I;
      if (PVD->hasAttr<NonNullAttr>() || isNonNullType(PVD->getType())) {
        if (NonNullArgs.empty())
          NonNullArgs.resize(Args.size());

        NonNullArgs.set(ParamIndex);
      }
    }
  } else {
    // If we have a non-function, non-method declaration but no
    // function prototype, try to dig out the function prototype.
    if (!Proto) {
      if (const ValueDecl *VD = dyn_cast<ValueDecl>(FDecl)) {
        QualType type = VD->getType().getNonReferenceType();
        if (auto pointerType = type->getAs<PointerType>())
          type = pointerType->getPointeeType();
        else if (auto blockType = type->getAs<BlockPointerType>())
          type = blockType->getPointeeType();
        // FIXME: data member pointers?

        // Dig out the function prototype, if there is one.
        Proto = type->getAs<FunctionProtoType>();
      }
    }

    // Fill in non-null argument information from the nullability
    // information on the parameter types (if we have them).
    if (Proto) {
      unsigned Index = 0;
      for (auto paramType : Proto->getParamTypes()) {
        if (isNonNullType(paramType)) {
          if (NonNullArgs.empty())
            NonNullArgs.resize(Args.size());

          NonNullArgs.set(Index);
        }

        ++Index;
      }
    }
  }

  // Check for non-null arguments.
  for (unsigned ArgIndex = 0, ArgIndexEnd = NonNullArgs.size();
       ArgIndex != ArgIndexEnd; ++ArgIndex) {
    if (NonNullArgs[ArgIndex])
      CheckNonNullArgument(S, Args[ArgIndex], Args[ArgIndex]->getExprLoc());
  }
}

void Sema::CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
                             StringRef ParamName, QualType ArgTy,
                             QualType ParamTy) {

  // If a function accepts a pointer or reference type
  if (!ParamTy->isPointerType() && !ParamTy->isReferenceType())
    return;

  // If the parameter is a pointer type, get the pointee type for the
  // argument too. If the parameter is a reference type, don't try to get
  // the pointee type for the argument.
  if (ParamTy->isPointerType())
    ArgTy = ArgTy->getPointeeType();

  // Remove reference or pointer
  ParamTy = ParamTy->getPointeeType();

  // Find expected alignment, and the actual alignment of the passed object.
  // getTypeAlignInChars requires complete types
  if (ArgTy.isNull() || ParamTy->isDependentType() ||
      ParamTy->isIncompleteType() || ArgTy->isIncompleteType() ||
      ParamTy->isUndeducedType() || ArgTy->isUndeducedType())
    return;

  CharUnits ParamAlign = Context.getTypeAlignInChars(ParamTy);
  CharUnits ArgAlign = Context.getTypeAlignInChars(ArgTy);

  // If the argument is less aligned than the parameter, there is a
  // potential alignment issue.
  if (ArgAlign < ParamAlign)
    Diag(Loc, diag::warn_param_mismatched_alignment)
        << (int)ArgAlign.getQuantity() << (int)ParamAlign.getQuantity()
        << ParamName << (FDecl != nullptr) << FDecl;
}

void Sema::checkLifetimeCaptureBy(FunctionDecl *FD, bool IsMemberFunction,
                                  const Expr *ThisArg,
                                  ArrayRef<const Expr *> Args) {
  if (!FD || Args.empty())
    return;
  auto GetArgAt = [&](int Idx) -> const Expr * {
    if (Idx == LifetimeCaptureByAttr::Global ||
        Idx == LifetimeCaptureByAttr::Unknown)
      return nullptr;
    if (IsMemberFunction && Idx == 0)
      return ThisArg;
    return Args[Idx - IsMemberFunction];
  };
  auto HandleCaptureByAttr = [&](const LifetimeCaptureByAttr *Attr,
                                 unsigned ArgIdx) {
    if (!Attr)
      return;

    Expr *Captured = const_cast<Expr *>(GetArgAt(ArgIdx));
    for (int CapturingParamIdx : Attr->params()) {
      // lifetime_capture_by(this) case is handled in the lifetimebound expr
      // initialization codepath.
      if (CapturingParamIdx == LifetimeCaptureByAttr::This &&
          isa<CXXConstructorDecl>(FD))
        continue;
      Expr *Capturing = const_cast<Expr *>(GetArgAt(CapturingParamIdx));
      CapturingEntity CE{Capturing};
      // Ensure that 'Captured' outlives the 'Capturing' entity.
      checkCaptureByLifetime(*this, CE, Captured);
    }
  };
  for (unsigned I = 0; I < FD->getNumParams(); ++I)
    HandleCaptureByAttr(FD->getParamDecl(I)->getAttr<LifetimeCaptureByAttr>(),
                        I + IsMemberFunction);
  // Check when the implicit object param is captured.
  if (IsMemberFunction) {
    TypeSourceInfo *TSI = FD->getTypeSourceInfo();
    if (!TSI)
      return;
    AttributedTypeLoc ATL;
    for (TypeLoc TL = TSI->getTypeLoc();
         (ATL = TL.getAsAdjusted<AttributedTypeLoc>());
         TL = ATL.getModifiedLoc())
      HandleCaptureByAttr(ATL.getAttrAs<LifetimeCaptureByAttr>(), 0);
  }
}

void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
                     const Expr *ThisArg, ArrayRef<const Expr *> Args,
                     bool IsMemberFunction, SourceLocation Loc,
                     SourceRange Range, VariadicCallType CallType) {
  // FIXME: We should check as much as we can in the template definition.
  if (CurContext->isDependentContext())
    return;

  // Printf and scanf checking.
  llvm::SmallBitVector CheckedVarArgs;
  if (FDecl) {
    for (const auto *I : FDecl->specific_attrs<FormatMatchesAttr>()) {
      // Only create vector if there are format attributes.
      CheckedVarArgs.resize(Args.size());
      CheckFormatString(I, Args, IsMemberFunction, CallType, Loc, Range,
                        CheckedVarArgs);
    }

    for (const auto *I : FDecl->specific_attrs<FormatAttr>()) {
      CheckedVarArgs.resize(Args.size());
      CheckFormatArguments(I, Args, IsMemberFunction, CallType, Loc, Range,
                           CheckedVarArgs);
    }
  }

  // Refuse POD arguments that weren't caught by the format string
  // checks above.
  auto *FD = dyn_cast_or_null<FunctionDecl>(FDecl);
  if (CallType != VariadicCallType::DoesNotApply &&
      (!FD || FD->getBuiltinID() != Builtin::BI__noop)) {
    unsigned NumParams = Proto ? Proto->getNumParams()
                         : isa_and_nonnull<FunctionDecl>(FDecl)
                             ? cast<FunctionDecl>(FDecl)->getNumParams()
                         : isa_and_nonnull<ObjCMethodDecl>(FDecl)
                             ? cast<ObjCMethodDecl>(FDecl)->param_size()
                             : 0;

    for (unsigned ArgIdx = NumParams; ArgIdx < Args.size(); ++ArgIdx) {
      // Args[ArgIdx] can be null in malformed code.
      if (const Expr *Arg = Args[ArgIdx]) {
        if (CheckedVarArgs.empty() || !CheckedVarArgs[ArgIdx])
          checkVariadicArgument(Arg, CallType);
      }
    }
  }
  if (FD)
    checkLifetimeCaptureBy(FD, IsMemberFunction, ThisArg, Args);
  if (FDecl || Proto) {
    CheckNonNullArguments(*this, FDecl, Proto, Args, Loc);

    // Type safety checking.
    if (FDecl) {
      for (const auto *I : FDecl->specific_attrs<ArgumentWithTypeTagAttr>())
        CheckArgumentWithTypeTag(I, Args, Loc);
    }
  }

  // Check that passed arguments match the alignment of original arguments.
  // Try to get the missing prototype from the declaration.
  if (!Proto && FDecl) {
    const auto *FT = FDecl->getFunctionType();
    if (isa_and_nonnull<FunctionProtoType>(FT))
      Proto = cast<FunctionProtoType>(FDecl->getFunctionType());
  }
  if (Proto) {
    // For variadic functions, we may have more args than parameters.
    // For some K&R functions, we may have less args than parameters.
    const auto N = std::min<unsigned>(Proto->getNumParams(), Args.size());
    bool IsScalableRet = Proto->getReturnType()->isSizelessVectorType();
    bool IsScalableArg = false;
    for (unsigned ArgIdx = 0; ArgIdx < N; ++ArgIdx) {
      // Args[ArgIdx] can be null in malformed code.
      if (const Expr *Arg = Args[ArgIdx]) {
        if (Arg->containsErrors())
          continue;

        if (Context.getTargetInfo().getTriple().isOSAIX() && FDecl && Arg &&
            FDecl->hasLinkage() &&
            FDecl->getFormalLinkage() != Linkage::Internal &&
            CallType == VariadicCallType::DoesNotApply)
          PPC().checkAIXMemberAlignment((Arg->getExprLoc()), Arg);

        QualType ParamTy = Proto->getParamType(ArgIdx);
        if (ParamTy->isSizelessVectorType())
          IsScalableArg = true;
        QualType ArgTy = Arg->getType();
        CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1),
                          ArgTy, ParamTy);
      }
    }

    // If the callee has an AArch64 SME attribute to indicate that it is an
    // __arm_streaming function, then the caller requires SME to be available.
    FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo();
    if (ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask) {
      if (auto *CallerFD = dyn_cast<FunctionDecl>(CurContext)) {
        llvm::StringMap<bool> CallerFeatureMap;
        Context.getFunctionFeatureMap(CallerFeatureMap, CallerFD);
        if (!CallerFeatureMap.contains("sme"))
          Diag(Loc, diag::err_sme_call_in_non_sme_target);
      } else if (!Context.getTargetInfo().hasFeature("sme")) {
        Diag(Loc, diag::err_sme_call_in_non_sme_target);
      }
    }

    // If the call requires a streaming-mode change and has scalable vector
    // arguments or return values, then warn the user that the streaming and
    // non-streaming vector lengths may be different.
    const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext);
    if (CallerFD && (!FD || !FD->getBuiltinID()) &&
        (IsScalableArg || IsScalableRet)) {
      bool IsCalleeStreaming =
          ExtInfo.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask;
      bool IsCalleeStreamingCompatible =
          ExtInfo.AArch64SMEAttributes &
          FunctionType::SME_PStateSMCompatibleMask;
      SemaARM::ArmStreamingType CallerFnType = getArmStreamingFnType(CallerFD);
      if (!IsCalleeStreamingCompatible &&
          (CallerFnType == SemaARM::ArmStreamingCompatible ||
           ((CallerFnType == SemaARM::ArmStreaming) ^ IsCalleeStreaming))) {
        if (IsScalableArg)
          Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
              << /*IsArg=*/true;
        if (IsScalableRet)
          Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
              << /*IsArg=*/false;
      }
    }

    FunctionType::ArmStateValue CalleeArmZAState =
        FunctionType::getArmZAState(ExtInfo.AArch64SMEAttributes);
    FunctionType::ArmStateValue CalleeArmZT0State =
        FunctionType::getArmZT0State(ExtInfo.AArch64SMEAttributes);
    if (CalleeArmZAState != FunctionType::ARM_None ||
        CalleeArmZT0State != FunctionType::ARM_None) {
      bool CallerHasZAState = false;
      bool CallerHasZT0State = false;
      if (CallerFD) {
        auto *Attr = CallerFD->getAttr<ArmNewAttr>();
        if (Attr && Attr->isNewZA())
          CallerHasZAState = true;
        if (Attr && Attr->isNewZT0())
          CallerHasZT0State = true;
        if (const auto *FPT = CallerFD->getType()->getAs<FunctionProtoType>()) {
          CallerHasZAState |=
              FunctionType::getArmZAState(
                  FPT->getExtProtoInfo().AArch64SMEAttributes) !=
              FunctionType::ARM_None;
          CallerHasZT0State |=
              FunctionType::getArmZT0State(
                  FPT->getExtProtoInfo().AArch64SMEAttributes) !=
              FunctionType::ARM_None;
        }
      }

      if (CalleeArmZAState != FunctionType::ARM_None && !CallerHasZAState)
        Diag(Loc, diag::err_sme_za_call_no_za_state);

      if (CalleeArmZT0State != FunctionType::ARM_None && !CallerHasZT0State)
        Diag(Loc, diag::err_sme_zt0_call_no_zt0_state);

      if (CallerHasZAState && CalleeArmZAState == FunctionType::ARM_None &&
          CalleeArmZT0State != FunctionType::ARM_None) {
        Diag(Loc, diag::err_sme_unimplemented_za_save_restore);
        Diag(Loc, diag::note_sme_use_preserves_za);
      }
    }
  }

  if (FDecl && FDecl->hasAttr<AllocAlignAttr>()) {
    auto *AA = FDecl->getAttr<AllocAlignAttr>();
    const Expr *Arg = Args[AA->getParamIndex().getASTIndex()];
    if (!Arg->isValueDependent()) {
      Expr::EvalResult Align;
      if (Arg->EvaluateAsInt(Align, Context)) {
        const llvm::APSInt &I = Align.Val.getInt();
        if (!I.isPowerOf2())
          Diag(Arg->getExprLoc(), diag::warn_alignment_not_power_of_two)
              << Arg->getSourceRange();

        if (I > Sema::MaximumAlignment)
          Diag(Arg->getExprLoc(), diag::warn_assume_aligned_too_great)
              << Arg->getSourceRange() << Sema::MaximumAlignment;
      }
    }
  }

  if (FD)
    diagnoseArgDependentDiagnoseIfAttrs(FD, ThisArg, Args, Loc);
}

void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) {
  if (ConceptDecl *Decl = AutoT->getTypeConstraintConcept()) {
    DiagnoseUseOfDecl(Decl, Loc);
  }
}

void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
                                ArrayRef<const Expr *> Args,
                                const FunctionProtoType *Proto,
                                SourceLocation Loc) {
  VariadicCallType CallType = Proto->isVariadic()
                                  ? VariadicCallType::Constructor
                                  : VariadicCallType::DoesNotApply;

  auto *Ctor = cast<CXXConstructorDecl>(FDecl);
  CheckArgAlignment(
      Loc, FDecl, "'this'", Context.getPointerType(ThisType),
      Context.getPointerType(Ctor->getFunctionObjectParameterType()));

  checkCall(FDecl, Proto, /*ThisArg=*/nullptr, Args, /*IsMemberFunction=*/true,
            Loc, SourceRange(), CallType);
}

bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
                             const FunctionProtoType *Proto) {
  bool IsMemberOperatorCall = isa<CXXOperatorCallExpr>(TheCall) &&
                              isa<CXXMethodDecl>(FDecl);
  bool IsMemberFunction = isa<CXXMemberCallExpr>(TheCall) ||
                          IsMemberOperatorCall;
  VariadicCallType CallType = getVariadicCallType(FDecl, Proto,
                                                  TheCall->getCallee());
  Expr** Args = TheCall->getArgs();
  unsigned NumArgs = TheCall->getNumArgs();

  Expr *ImplicitThis = nullptr;
  if (IsMemberOperatorCall && !FDecl->hasCXXExplicitFunctionObjectParameter()) {
    // If this is a call to a member operator, hide the first
    // argument from checkCall.
    // FIXME: Our choice of AST representation here is less than ideal.
    ImplicitThis = Args[0];
    ++Args;
    --NumArgs;
  } else if (IsMemberFunction && !FDecl->isStatic() &&
             !FDecl->hasCXXExplicitFunctionObjectParameter())
    ImplicitThis =
        cast<CXXMemberCallExpr>(TheCall)->getImplicitObjectArgument();

  if (ImplicitThis) {
    // ImplicitThis may or may not be a pointer, depending on whether . or -> is
    // used.
    QualType ThisType = ImplicitThis->getType();
    if (!ThisType->isPointerType()) {
      assert(!ThisType->isReferenceType());
      ThisType = Context.getPointerType(ThisType);
    }

    QualType ThisTypeFromDecl = Context.getPointerType(
        cast<CXXMethodDecl>(FDecl)->getFunctionObjectParameterType());

    CheckArgAlignment(TheCall->getRParenLoc(), FDecl, "'this'", ThisType,
                      ThisTypeFromDecl);
  }

  checkCall(FDecl, Proto, ImplicitThis, llvm::ArrayRef(Args, NumArgs),
            IsMemberFunction, TheCall->getRParenLoc(),
            TheCall->getCallee()->getSourceRange(), CallType);

  IdentifierInfo *FnInfo = FDecl->getIdentifier();
  // None of the checks below are needed for functions that don't have
  // simple names (e.g., C++ conversion functions).
  if (!FnInfo)
    return false;

  // Enforce TCB except for builtin calls, which are always allowed.
  if (FDecl->getBuiltinID() == 0)
    CheckTCBEnforcement(TheCall->getExprLoc(), FDecl);

  CheckAbsoluteValueFunction(TheCall, FDecl);
  CheckMaxUnsignedZero(TheCall, FDecl);
  CheckInfNaNFunction(TheCall, FDecl);

  if (getLangOpts().ObjC)
    ObjC().DiagnoseCStringFormatDirectiveInCFAPI(FDecl, Args, NumArgs);

  unsigned CMId = FDecl->getMemoryFunctionKind();

  // Handle memory setting and copying functions.
  switch (CMId) {
  case 0:
    return false;
  case Builtin::BIstrlcpy: // fallthrough
  case Builtin::BIstrlcat:
    CheckStrlcpycatArguments(TheCall, FnInfo);
    break;
  case Builtin::BIstrncat:
    CheckStrncatArguments(TheCall, FnInfo);
    break;
  case Builtin::BIfree:
    CheckFreeArguments(TheCall);
    break;
  default:
    CheckMemaccessArguments(TheCall, CMId, FnInfo);
  }

  return false;
}

bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
                            const FunctionProtoType *Proto) {
  QualType Ty;
  if (const auto *V = dyn_cast<VarDecl>(NDecl))
    Ty = V->getType().getNonReferenceType();
  else if (const auto *F = dyn_cast<FieldDecl>(NDecl))
    Ty = F->getType().getNonReferenceType();
  else
    return false;

  if (!Ty->isBlockPointerType() && !Ty->isFunctionPointerType() &&
      !Ty->isFunctionProtoType())
    return false;

  VariadicCallType CallType;
  if (!Proto || !Proto->isVariadic()) {
    CallType = VariadicCallType::DoesNotApply;
  } else if (Ty->isBlockPointerType()) {
    CallType = VariadicCallType::Block;
  } else { // Ty->isFunctionPointerType()
    CallType = VariadicCallType::Function;
  }

  checkCall(NDecl, Proto, /*ThisArg=*/nullptr,
            llvm::ArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
            /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
            TheCall->getCallee()->getSourceRange(), CallType);

  return false;
}

bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) {
  VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto,
                                                  TheCall->getCallee());
  checkCall(/*FDecl=*/nullptr, Proto, /*ThisArg=*/nullptr,
            llvm::ArrayRef(TheCall->getArgs(), TheCall->getNumArgs()),
            /*IsMemberFunction=*/false, TheCall->getRParenLoc(),
            TheCall->getCallee()->getSourceRange(), CallType);

  return false;
}

static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) {
  if (!llvm::isValidAtomicOrderingCABI(Ordering))
    return false;

  auto OrderingCABI = (llvm::AtomicOrderingCABI)Ordering;
  switch (Op) {
  case AtomicExpr::AO__c11_atomic_init:
  case AtomicExpr::AO__opencl_atomic_init:
    llvm_unreachable("There is no ordering argument for an init");

  case AtomicExpr::AO__c11_atomic_load:
  case AtomicExpr::AO__opencl_atomic_load:
  case AtomicExpr::AO__hip_atomic_load:
  case AtomicExpr::AO__atomic_load_n:
  case AtomicExpr::AO__atomic_load:
  case AtomicExpr::AO__scoped_atomic_load_n:
  case AtomicExpr::AO__scoped_atomic_load:
    return OrderingCABI != llvm::AtomicOrderingCABI::release &&
           OrderingCABI != llvm::AtomicOrderingCABI::acq_rel;

  case AtomicExpr::AO__c11_atomic_store:
  case AtomicExpr::AO__opencl_atomic_store:
  case AtomicExpr::AO__hip_atomic_store:
  case AtomicExpr::AO__atomic_store:
  case AtomicExpr::AO__atomic_store_n:
  case AtomicExpr::AO__scoped_atomic_store:
  case AtomicExpr::AO__scoped_atomic_store_n:
  case AtomicExpr::AO__atomic_clear:
    return OrderingCABI != llvm::AtomicOrderingCABI::consume &&
           OrderingCABI != llvm::AtomicOrderingCABI::acquire &&
           OrderingCABI != llvm::AtomicOrderingCABI::acq_rel;

  default:
    return true;
  }
}

ExprResult Sema::AtomicOpsOverloaded(ExprResult TheCallResult,
                                     AtomicExpr::AtomicOp Op) {
  CallExpr *TheCall = cast<CallExpr>(TheCallResult.get());
  DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
  MultiExprArg Args{TheCall->getArgs(), TheCall->getNumArgs()};
  return BuildAtomicExpr({TheCall->getBeginLoc(), TheCall->getEndLoc()},
                         DRE->getSourceRange(), TheCall->getRParenLoc(), Args,
                         Op);
}

ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
                                 SourceLocation RParenLoc, MultiExprArg Args,
                                 AtomicExpr::AtomicOp Op,
                                 AtomicArgumentOrder ArgOrder) {
  // All the non-OpenCL operations take one of the following forms.
  // The OpenCL operations take the __c11 forms with one extra argument for
  // synchronization scope.
  enum {
    // C    __c11_atomic_init(A *, C)
    Init,

    // C    __c11_atomic_load(A *, int)
    Load,

    // void __atomic_load(A *, CP, int)
    LoadCopy,

    // void __atomic_store(A *, CP, int)
    Copy,

    // C    __c11_atomic_add(A *, M, int)
    Arithmetic,

    // C    __atomic_exchange_n(A *, CP, int)
    Xchg,

    // void __atomic_exchange(A *, C *, CP, int)
    GNUXchg,

    // bool __c11_atomic_compare_exchange_strong(A *, C *, CP, int, int)
    C11CmpXchg,

    // bool __atomic_compare_exchange(A *, C *, CP, bool, int, int)
    GNUCmpXchg,

    // bool __atomic_test_and_set(A *, int)
    TestAndSetByte,

    // void __atomic_clear(A *, int)
    ClearByte,
  } Form = Init;

  const unsigned NumForm = ClearByte + 1;
  const unsigned NumArgs[] = {2, 2, 3, 3, 3, 3, 4, 5, 6, 2, 2};
  const unsigned NumVals[] = {1, 0, 1, 1, 1, 1, 2, 2, 3, 0, 0};
  // where:
  //   C is an appropriate type,
  //   A is volatile _Atomic(C) for __c11 builtins and is C for GNU builtins,
  //   CP is C for __c11 builtins and GNU _n builtins and is C * otherwise,
  //   M is C if C is an integer, and ptrdiff_t if C is a pointer, and
  //   the int parameters are for orderings.

  static_assert(sizeof(NumArgs)/sizeof(NumArgs[0]) == NumForm
      && sizeof(NumVals)/sizeof(NumVals[0]) == NumForm,
      "need to update code for modified forms");
  static_assert(AtomicExpr::AO__atomic_add_fetch == 0 &&
                    AtomicExpr::AO__atomic_xor_fetch + 1 ==
                        AtomicExpr::AO__c11_atomic_compare_exchange_strong,
                "need to update code for modified C11 atomics");
  bool IsOpenCL = Op >= AtomicExpr::AO__opencl_atomic_compare_exchange_strong &&
                  Op <= AtomicExpr::AO__opencl_atomic_store;
  bool IsHIP = Op >= AtomicExpr::AO__hip_atomic_compare_exchange_strong &&
               Op <= AtomicExpr::AO__hip_atomic_store;
  bool IsScoped = Op >= AtomicExpr::AO__scoped_atomic_add_fetch &&
                  Op <= AtomicExpr::AO__scoped_atomic_xor_fetch;
  bool IsC11 = (Op >= AtomicExpr::AO__c11_atomic_compare_exchange_strong &&
                Op <= AtomicExpr::AO__c11_atomic_store) ||
               IsOpenCL;
  bool IsN = Op == AtomicExpr::AO__atomic_load_n ||
             Op == AtomicExpr::AO__atomic_store_n ||
             Op == AtomicExpr::AO__atomic_exchange_n ||
             Op == AtomicExpr::AO__atomic_compare_exchange_n ||
             Op == AtomicExpr::AO__scoped_atomic_load_n ||
             Op == AtomicExpr::AO__scoped_atomic_store_n ||
             Op == AtomicExpr::AO__scoped_atomic_exchange_n ||
             Op == AtomicExpr::AO__scoped_atomic_compare_exchange_n;
  // Bit mask for extra allowed value types other than integers for atomic
  // arithmetic operations. Add/sub allow pointer and floating point. Min/max
  // allow floating point.
  enum ArithOpExtraValueType {
    AOEVT_None = 0,
    AOEVT_Pointer = 1,
    AOEVT_FP = 2,
  };
  unsigned ArithAllows = AOEVT_None;

  switch (Op) {
  case AtomicExpr::AO__c11_atomic_init:
  case AtomicExpr::AO__opencl_atomic_init:
    Form = Init;
    break;

  case AtomicExpr::AO__c11_atomic_load:
  case AtomicExpr::AO__opencl_atomic_load:
  case AtomicExpr::AO__hip_atomic_load:
  case AtomicExpr::AO__atomic_load_n:
  case AtomicExpr::AO__scoped_atomic_load_n:
    Form = Load;
    break;

  case AtomicExpr::AO__atomic_load:
  case AtomicExpr::AO__scoped_atomic_load:
    Form = LoadCopy;
    break;

  case AtomicExpr::AO__c11_atomic_store:
  case AtomicExpr::AO__opencl_atomic_store:
  case AtomicExpr::AO__hip_atomic_store:
  case AtomicExpr::AO__atomic_store:
  case AtomicExpr::AO__atomic_store_n:
  case AtomicExpr::AO__scoped_atomic_store:
  case AtomicExpr::AO__scoped_atomic_store_n:
    Form = Copy;
    break;
  case AtomicExpr::AO__atomic_fetch_add:
  case AtomicExpr::AO__atomic_fetch_sub:
  case AtomicExpr::AO__atomic_add_fetch:
  case AtomicExpr::AO__atomic_sub_fetch:
  case AtomicExpr::AO__scoped_atomic_fetch_add:
  case AtomicExpr::AO__scoped_atomic_fetch_sub:
  case AtomicExpr::AO__scoped_atomic_add_fetch:
  case AtomicExpr::AO__scoped_atomic_sub_fetch:
  case AtomicExpr::AO__c11_atomic_fetch_add:
  case AtomicExpr::AO__c11_atomic_fetch_sub:
  case AtomicExpr::AO__opencl_atomic_fetch_add:
  case AtomicExpr::AO__opencl_atomic_fetch_sub:
  case AtomicExpr::AO__hip_atomic_fetch_add:
  case AtomicExpr::AO__hip_atomic_fetch_sub:
    ArithAllows = AOEVT_Pointer | AOEVT_FP;
    Form = Arithmetic;
    break;
  case AtomicExpr::AO__atomic_fetch_max:
  case AtomicExpr::AO__atomic_fetch_min:
  case AtomicExpr::AO__atomic_max_fetch:
  case AtomicExpr::AO__atomic_min_fetch:
  case AtomicExpr::AO__scoped_atomic_fetch_max:
  case AtomicExpr::AO__scoped_atomic_fetch_min:
  case AtomicExpr::AO__scoped_atomic_max_fetch:
  case AtomicExpr::AO__scoped_atomic_min_fetch:
  case AtomicExpr::AO__c11_atomic_fetch_max:
  case AtomicExpr::AO__c11_atomic_fetch_min:
  case AtomicExpr::AO__opencl_atomic_fetch_max:
  case AtomicExpr::AO__opencl_atomic_fetch_min:
  case AtomicExpr::AO__hip_atomic_fetch_max:
  case AtomicExpr::AO__hip_atomic_fetch_min:
    ArithAllows = AOEVT_FP;
    Form = Arithmetic;
    break;
  case AtomicExpr::AO__c11_atomic_fetch_and:
  case AtomicExpr::AO__c11_atomic_fetch_or:
  case AtomicExpr::AO__c11_atomic_fetch_xor:
  case AtomicExpr::AO__hip_atomic_fetch_and:
  case AtomicExpr::AO__hip_atomic_fetch_or:
  case AtomicExpr::AO__hip_atomic_fetch_xor:
  case AtomicExpr::AO__c11_atomic_fetch_nand:
  case AtomicExpr::AO__opencl_atomic_fetch_and:
  case AtomicExpr::AO__opencl_atomic_fetch_or:
  case AtomicExpr::AO__opencl_atomic_fetch_xor:
  case AtomicExpr::AO__atomic_fetch_and:
  case AtomicExpr::AO__atomic_fetch_or:
  case AtomicExpr::AO__atomic_fetch_xor:
  case AtomicExpr::AO__atomic_fetch_nand:
  case AtomicExpr::AO__atomic_and_fetch:
  case AtomicExpr::AO__atomic_or_fetch:
  case AtomicExpr::AO__atomic_xor_fetch:
  case AtomicExpr::AO__atomic_nand_fetch:
  case AtomicExpr::AO__scoped_atomic_fetch_and:
  case AtomicExpr::AO__scoped_atomic_fetch_or:
  case AtomicExpr::AO__scoped_atomic_fetch_xor:
  case AtomicExpr::AO__scoped_atomic_fetch_nand:
  case AtomicExpr::AO__scoped_atomic_and_fetch:
  case AtomicExpr::AO__scoped_atomic_or_fetch:
  case AtomicExpr::AO__scoped_atomic_xor_fetch:
  case AtomicExpr::AO__scoped_atomic_nand_fetch:
    Form = Arithmetic;
    break;

  case AtomicExpr::AO__c11_atomic_exchange:
  case AtomicExpr::AO__hip_atomic_exchange:
  case AtomicExpr::AO__opencl_atomic_exchange:
  case AtomicExpr::AO__atomic_exchange_n:
  case AtomicExpr::AO__scoped_atomic_exchange_n:
    Form = Xchg;
    break;

  case AtomicExpr::AO__atomic_exchange:
  case AtomicExpr::AO__scoped_atomic_exchange:
    Form = GNUXchg;
    break;

  case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
  case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
  case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
  case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
  case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
  case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
    Form = C11CmpXchg;
    break;

  case AtomicExpr::AO__atomic_compare_exchange:
  case AtomicExpr::AO__atomic_compare_exchange_n:
  case AtomicExpr::AO__scoped_atomic_compare_exchange:
  case AtomicExpr::AO__scoped_atomic_compare_exchange_n:
    Form = GNUCmpXchg;
    break;

  case AtomicExpr::AO__atomic_test_and_set:
    Form = TestAndSetByte;
    break;

  case AtomicExpr::AO__atomic_clear:
    Form = ClearByte;
    break;
  }

  unsigned AdjustedNumArgs = NumArgs[Form];
  if ((IsOpenCL || IsHIP || IsScoped) &&
      Op != AtomicExpr::AO__opencl_atomic_init)
    ++AdjustedNumArgs;
  // Check we have the right number of arguments.
  if (Args.size() < AdjustedNumArgs) {
    Diag(CallRange.getEnd(), diag::err_typecheck_call_too_few_args)
        << 0 << AdjustedNumArgs << static_cast<unsigned>(Args.size())
        << /*is non object*/ 0 << ExprRange;
    return ExprError();
  } else if (Args.size() > AdjustedNumArgs) {
    Diag(Args[AdjustedNumArgs]->getBeginLoc(),
         diag::err_typecheck_call_too_many_args)
        << 0 << AdjustedNumArgs << static_cast<unsigned>(Args.size())
        << /*is non object*/ 0 << ExprRange;
    return ExprError();
  }

  // Inspect the first argument of the atomic operation.
  Expr *Ptr = Args[0];
  ExprResult ConvertedPtr = DefaultFunctionArrayLvalueConversion(Ptr);
  if (ConvertedPtr.isInvalid())
    return ExprError();

  Ptr = ConvertedPtr.get();
  const PointerType *pointerType = Ptr->getType()->getAs<PointerType>();
  if (!pointerType) {
    Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer)
        << Ptr->getType() << 0 << Ptr->getSourceRange();
    return ExprError();
  }

  // For a __c11 builtin, this should be a pointer to an _Atomic type.
  QualType AtomTy = pointerType->getPointeeType(); // 'A'
  QualType ValType = AtomTy; // 'C'
  if (IsC11) {
    if (!AtomTy->isAtomicType()) {
      Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic)
          << Ptr->getType() << Ptr->getSourceRange();
      return ExprError();
    }
    if ((Form != Load && Form != LoadCopy && AtomTy.isConstQualified()) ||
        AtomTy.getAddressSpace() == LangAS::opencl_constant) {
      Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_non_const_atomic)
          << (AtomTy.isConstQualified() ? 0 : 1) << Ptr->getType()
          << Ptr->getSourceRange();
      return ExprError();
    }
    ValType = AtomTy->castAs<AtomicType>()->getValueType();
  } else if (Form != Load && Form != LoadCopy) {
    if (ValType.isConstQualified()) {
      Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_non_const_pointer)
          << Ptr->getType() << Ptr->getSourceRange();
      return ExprError();
    }
  }

  if (Form != TestAndSetByte && Form != ClearByte) {
    // Pointer to object of size zero is not allowed.
    if (RequireCompleteType(Ptr->getBeginLoc(), AtomTy,
                            diag::err_incomplete_type))
      return ExprError();

    if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) {
      Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer)
          << Ptr->getType() << 1 << Ptr->getSourceRange();
      return ExprError();
    }
  } else {
    // The __atomic_clear and __atomic_test_and_set intrinsics accept any
    // non-const pointer type, including void* and pointers to incomplete
    // structs, but only access the first byte.
    AtomTy = Context.CharTy;
    AtomTy = AtomTy.withCVRQualifiers(
        pointerType->getPointeeType().getCVRQualifiers());
    QualType PointerQT = Context.getPointerType(AtomTy);
    pointerType = PointerQT->getAs<PointerType>();
    Ptr = ImpCastExprToType(Ptr, PointerQT, CK_BitCast).get();
    ValType = AtomTy;
  }

  PointerAuthQualifier PointerAuth = AtomTy.getPointerAuth();
  if (PointerAuth && PointerAuth.isAddressDiscriminated()) {
    Diag(ExprRange.getBegin(),
         diag::err_atomic_op_needs_non_address_discriminated_pointer)
        << 0 << Ptr->getType() << Ptr->getSourceRange();
    return ExprError();
  }

  // For an arithmetic operation, the implied arithmetic must be well-formed.
  if (Form == Arithmetic) {
    // GCC does not enforce these rules for GNU atomics, but we do to help catch
    // trivial type errors.
    auto IsAllowedValueType = [&](QualType ValType,
                                  unsigned AllowedType) -> bool {
      if (ValType->isIntegerType())
        return true;
      if (ValType->isPointerType())
        return AllowedType & AOEVT_Pointer;
      if (!(ValType->isFloatingType() && (AllowedType & AOEVT_FP)))
        return false;
      // LLVM Parser does not allow atomicrmw with x86_fp80 type.
      if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
          &Context.getTargetInfo().getLongDoubleFormat() ==
              &llvm::APFloat::x87DoubleExtended())
        return false;
      return true;
    };
    if (!IsAllowedValueType(ValType, ArithAllows)) {
      auto DID = ArithAllows & AOEVT_FP
                     ? (ArithAllows & AOEVT_Pointer
                            ? diag::err_atomic_op_needs_atomic_int_ptr_or_fp
                            : diag::err_atomic_op_needs_atomic_int_or_fp)
                     : diag::err_atomic_op_needs_atomic_int;
      Diag(ExprRange.getBegin(), DID)
          << IsC11 << Ptr->getType() << Ptr->getSourceRange();
      return ExprError();
    }
    if (IsC11 && ValType->isPointerType() &&
        RequireCompleteType(Ptr->getBeginLoc(), ValType->getPointeeType(),
                            diag::err_incomplete_type)) {
      return ExprError();
    }
  } else if (IsN && !ValType->isIntegerType() && !ValType->isPointerType()) {
    // For __atomic_*_n operations, the value type must be a scalar integral or
    // pointer type which is 1, 2, 4, 8 or 16 bytes in length.
    Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_atomic_int_or_ptr)
        << IsC11 << Ptr->getType() << Ptr->getSourceRange();
    return ExprError();
  }

  if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context) &&
      !AtomTy->isScalarType()) {
    // For GNU atomics, require a trivially-copyable type. This is not part of
    // the GNU atomics specification but we enforce it for consistency with
    // other atomics which generally all require a trivially-copyable type. This
    // is because atomics just copy bits.
    Diag(ExprRange.getBegin(), diag::err_atomic_op_needs_trivial_copy)
        << Ptr->getType() << Ptr->getSourceRange();
    return ExprError();
  }

  switch (ValType.getObjCLifetime()) {
  case Qualifiers::OCL_None:
  case Qualifiers::OCL_ExplicitNone:
    // okay
    break;

  case Qualifiers::OCL_Weak:
  case Qualifiers::OCL_Strong:
  case Qualifiers::OCL_Autoreleasing:
    // FIXME: Can this happen? By this point, ValType should be known
    // to be trivially copyable.
    Diag(ExprRange.getBegin(), diag::err_arc_atomic_ownership)
        << ValType << Ptr->getSourceRange();
    return ExprError();
  }

  // All atomic operations have an overload which takes a pointer to a volatile
  // 'A'.  We shouldn't let the volatile-ness of the pointee-type inject itself
  // into the result or the other operands. Similarly atomic_load takes a
  // pointer to a const 'A'.
  ValType.removeLocalVolatile();
  ValType.removeLocalConst();
  QualType ResultType = ValType;
  if (Form == Copy || Form == LoadCopy || Form == GNUXchg || Form == Init ||
      Form == ClearByte)
    ResultType = Context.VoidTy;
  else if (Form == C11CmpXchg || Form == GNUCmpXchg || Form == TestAndSetByte)
    ResultType = Context.BoolTy;

  // The type of a parameter passed 'by value'. In the GNU atomics, such
  // arguments are actually passed as pointers.
  QualType ByValType = ValType; // 'CP'
  bool IsPassedByAddress = false;
  if (!IsC11 && !IsHIP && !IsN) {
    ByValType = Ptr->getType();
    IsPassedByAddress = true;
  }

  SmallVector<Expr *, 5> APIOrderedArgs;
  if (ArgOrder == Sema::AtomicArgumentOrder::AST) {
    APIOrderedArgs.push_back(Args[0]);
    switch (Form) {
    case Init:
    case Load:
      APIOrderedArgs.push_back(Args[1]); // Val1/Order
      break;
    case LoadCopy:
    case Copy:
    case Arithmetic:
    case Xchg:
      APIOrderedArgs.push_back(Args[2]); // Val1
      APIOrderedArgs.push_back(Args[1]); // Order
      break;
    case GNUXchg:
      APIOrderedArgs.push_back(Args[2]); // Val1
      APIOrderedArgs.push_back(Args[3]); // Val2
      APIOrderedArgs.push_back(Args[1]); // Order
      break;
    case C11CmpXchg:
      APIOrderedArgs.push_back(Args[2]); // Val1
      APIOrderedArgs.push_back(Args[4]); // Val2
      APIOrderedArgs.push_back(Args[1]); // Order
      APIOrderedArgs.push_back(Args[3]); // OrderFail
      break;
    case GNUCmpXchg:
      APIOrderedArgs.push_back(Args[2]); // Val1
      APIOrderedArgs.push_back(Args[4]); // Val2
      APIOrderedArgs.push_back(Args[5]); // Weak
      APIOrderedArgs.push_back(Args[1]); // Order
      APIOrderedArgs.push_back(Args[3]); // OrderFail
      break;
    case TestAndSetByte:
    case ClearByte:
      APIOrderedArgs.push_back(Args[1]); // Order
      break;
    }
  } else
    APIOrderedArgs.append(Args.begin(), Args.end());

  // The first argument's non-CV pointer type is used to deduce the type of
  // subsequent arguments, except for:
  //  - weak flag (always converted to bool)
  //  - memory order (always converted to int)
  //  - scope  (always converted to int)
  for (unsigned i = 0; i != APIOrderedArgs.size(); ++i) {
    QualType Ty;
    if (i < NumVals[Form] + 1) {
      switch (i) {
      case 0:
        // The first argument is always a pointer. It has a fixed type.
        // It is always dereferenced, a nullptr is undefined.
        CheckNonNullArgument(*this, APIOrderedArgs[i], ExprRange.getBegin());
        // Nothing else to do: we already know all we want about this pointer.
        continue;
      case 1:
        // The second argument is the non-atomic operand. For arithmetic, this
        // is always passed by value, and for a compare_exchange it is always
        // passed by address. For the rest, GNU uses by-address and C11 uses
        // by-value.
        assert(Form != Load);
        if (Form == Arithmetic && ValType->isPointerType())
          Ty = Context.getPointerDiffType();
        else if (Form == Init || Form == Arithmetic)
          Ty = ValType;
        else if (Form == Copy || Form == Xchg) {
          if (IsPassedByAddress) {
            // The value pointer is always dereferenced, a nullptr is undefined.
            CheckNonNullArgument(*this, APIOrderedArgs[i],
                                 ExprRange.getBegin());
          }
          Ty = ByValType;
        } else {
          Expr *ValArg = APIOrderedArgs[i];
          // The value pointer is always dereferenced, a nullptr is undefined.
          CheckNonNullArgument(*this, ValArg, ExprRange.getBegin());
          LangAS AS = LangAS::Default;
          // Keep address space of non-atomic pointer type.
          if (const PointerType *PtrTy =
                  ValArg->getType()->getAs<PointerType>()) {
            AS = PtrTy->getPointeeType().getAddressSpace();
          }
          Ty = Context.getPointerType(
              Context.getAddrSpaceQualType(ValType.getUnqualifiedType(), AS));
        }
        break;
      case 2:
        // The third argument to compare_exchange / GNU exchange is the desired
        // value, either by-value (for the C11 and *_n variant) or as a pointer.
        if (IsPassedByAddress)
          CheckNonNullArgument(*this, APIOrderedArgs[i], ExprRange.getBegin());
        Ty = ByValType;
        break;
      case 3:
        // The fourth argument to GNU compare_exchange is a 'weak' flag.
        Ty = Context.BoolTy;
        break;
      }
    } else {
      // The order(s) and scope are always converted to int.
      Ty = Context.IntTy;
    }

    InitializedEntity Entity =
        InitializedEntity::InitializeParameter(Context, Ty, false);
    ExprResult Arg = APIOrderedArgs[i];
    Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
    if (Arg.isInvalid())
      return true;
    APIOrderedArgs[i] = Arg.get();
  }

  // Permute the arguments into a 'consistent' order.
  SmallVector<Expr*, 5> SubExprs;
  SubExprs.push_back(Ptr);
  switch (Form) {
  case Init:
    // Note, AtomicExpr::getVal1() has a special case for this atomic.
    SubExprs.push_back(APIOrderedArgs[1]); // Val1
    break;
  case Load:
  case TestAndSetByte:
  case ClearByte:
    SubExprs.push_back(APIOrderedArgs[1]); // Order
    break;
  case LoadCopy:
  case Copy:
  case Arithmetic:
  case Xchg:
    SubExprs.push_back(APIOrderedArgs[2]); // Order
    SubExprs.push_back(APIOrderedArgs[1]); // Val1
    break;
  case GNUXchg:
    // Note, AtomicExpr::getVal2() has a special case for this atomic.
    SubExprs.push_back(APIOrderedArgs[3]); // Order
    SubExprs.push_back(APIOrderedArgs[1]); // Val1
    SubExprs.push_back(APIOrderedArgs[2]); // Val2
    break;
  case C11CmpXchg:
    SubExprs.push_back(APIOrderedArgs[3]); // Order
    SubExprs.push_back(APIOrderedArgs[1]); // Val1
    SubExprs.push_back(APIOrderedArgs[4]); // OrderFail
    SubExprs.push_back(APIOrderedArgs[2]); // Val2
    break;
  case GNUCmpXchg:
    SubExprs.push_back(APIOrderedArgs[4]); // Order
    SubExprs.push_back(APIOrderedArgs[1]); // Val1
    SubExprs.push_back(APIOrderedArgs[5]); // OrderFail
    SubExprs.push_back(APIOrderedArgs[2]); // Val2
    SubExprs.push_back(APIOrderedArgs[3]); // Weak
    break;
  }

  // If the memory orders are constants, check they are valid.
  if (SubExprs.size() >= 2 && Form != Init) {
    std::optional<llvm::APSInt> Success =
        SubExprs[1]->getIntegerConstantExpr(Context);
    if (Success && !isValidOrderingForOp(Success->getSExtValue(), Op)) {
      Diag(SubExprs[1]->getBeginLoc(),
           diag::warn_atomic_op_has_invalid_memory_order)
          << /*success=*/(Form == C11CmpXchg || Form == GNUCmpXchg)
          << SubExprs[1]->getSourceRange();
    }
    if (SubExprs.size() >= 5) {
      if (std::optional<llvm::APSInt> Failure =
              SubExprs[3]->getIntegerConstantExpr(Context)) {
        if (!llvm::is_contained(
                {llvm::AtomicOrderingCABI::relaxed,
                 llvm::AtomicOrderingCABI::consume,
                 llvm::AtomicOrderingCABI::acquire,
                 llvm::AtomicOrderingCABI::seq_cst},
                (llvm::AtomicOrderingCABI)Failure->getSExtValue())) {
          Diag(SubExprs[3]->getBeginLoc(),
               diag::warn_atomic_op_has_invalid_memory_order)
              << /*failure=*/2 << SubExprs[3]->getSourceRange();
        }
      }
    }
  }

  if (auto ScopeModel = AtomicExpr::getScopeModel(Op)) {
    auto *Scope = Args[Args.size() - 1];
    if (std::optional<llvm::APSInt> Result =
            Scope->getIntegerConstantExpr(Context)) {
      if (!ScopeModel->isValid(Result->getZExtValue()))
        Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_sync_scope)
            << Scope->getSourceRange();
    }
    SubExprs.push_back(Scope);
  }

  AtomicExpr *AE = new (Context)
      AtomicExpr(ExprRange.getBegin(), SubExprs, ResultType, Op, RParenLoc);

  if ((Op == AtomicExpr::AO__c11_atomic_load ||
       Op == AtomicExpr::AO__c11_atomic_store ||
       Op == AtomicExpr::AO__opencl_atomic_load ||
       Op == AtomicExpr::AO__hip_atomic_load ||
       Op == AtomicExpr::AO__opencl_atomic_store ||
       Op == AtomicExpr::AO__hip_atomic_store) &&
      Context.AtomicUsesUnsupportedLibcall(AE))
    Diag(AE->getBeginLoc(), diag::err_atomic_load_store_uses_lib)
        << ((Op == AtomicExpr::AO__c11_atomic_load ||
             Op == AtomicExpr::AO__opencl_atomic_load ||
             Op == AtomicExpr::AO__hip_atomic_load)
                ? 0
                : 1);

  if (ValType->isBitIntType()) {
    Diag(Ptr->getExprLoc(), diag::err_atomic_builtin_bit_int_prohibit);
    return ExprError();
  }

  return AE;
}

/// checkBuiltinArgument - Given a call to a builtin function, perform
/// normal type-checking on the given argument, updating the call in
/// place.  This is useful when a builtin function requires custom
/// type-checking for some of its arguments but not necessarily all of
/// them.
///
/// Returns true on error.
static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) {
  FunctionDecl *Fn = E->getDirectCallee();
  assert(Fn && "builtin call without direct callee!");

  ParmVarDecl *Param = Fn->getParamDecl(ArgIndex);
  InitializedEntity Entity =
    InitializedEntity::InitializeParameter(S.Context, Param);

  ExprResult Arg = E->getArg(ArgIndex);
  Arg = S.PerformCopyInitialization(Entity, SourceLocation(), Arg);
  if (Arg.isInvalid())
    return true;

  E->setArg(ArgIndex, Arg.get());
  return false;
}

ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) {
  CallExpr *TheCall = static_cast<CallExpr *>(TheCallResult.get());
  Expr *Callee = TheCall->getCallee();
  DeclRefExpr *DRE = cast<DeclRefExpr>(Callee->IgnoreParenCasts());
  FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());

  // Ensure that we have at least one argument to do type inference from.
  if (TheCall->getNumArgs() < 1) {
    Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
        << 0 << 1 << TheCall->getNumArgs() << /*is non object*/ 0
        << Callee->getSourceRange();
    return ExprError();
  }

  // Inspect the first argument of the atomic builtin.  This should always be
  // a pointer type, whose element is an integral scalar or pointer type.
  // Because it is a pointer type, we don't have to worry about any implicit
  // casts here.
  // FIXME: We don't allow floating point scalars as input.
  Expr *FirstArg = TheCall->getArg(0);
  ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg);
  if (FirstArgResult.isInvalid())
    return ExprError();
  FirstArg = FirstArgResult.get();
  TheCall->setArg(0, FirstArg);

  const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>();
  if (!pointerType) {
    Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer)
        << FirstArg->getType() << 0 << FirstArg->getSourceRange();
    return ExprError();
  }

  QualType ValType = pointerType->getPointeeType();
  if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
      !ValType->isBlockPointerType()) {
    Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr)
        << FirstArg->getType() << 0 << FirstArg->getSourceRange();
    return ExprError();
  }
  PointerAuthQualifier PointerAuth = ValType.getPointerAuth();
  if (PointerAuth && PointerAuth.isAddressDiscriminated()) {
    Diag(FirstArg->getBeginLoc(),
         diag::err_atomic_op_needs_non_address_discriminated_pointer)
        << 1 << ValType << FirstArg->getSourceRange();
    return ExprError();
  }

  if (ValType.isConstQualified()) {
    Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_cannot_be_const)
        << FirstArg->getType() << FirstArg->getSourceRange();
    return ExprError();
  }

  switch (ValType.getObjCLifetime()) {
  case Qualifiers::OCL_None:
  case Qualifiers::OCL_ExplicitNone:
    // okay
    break;

  case Qualifiers::OCL_Weak:
  case Qualifiers::OCL_Strong:
  case Qualifiers::OCL_Autoreleasing:
    Diag(DRE->getBeginLoc(), diag::err_arc_atomic_ownership)
        << ValType << FirstArg->getSourceRange();
    return ExprError();
  }

  // Strip any qualifiers off ValType.
  ValType = ValType.getUnqualifiedType();

  // The majority of builtins return a value, but a few have special return
  // types, so allow them to override appropriately below.
  QualType ResultType = ValType;

  // We need to figure out which concrete builtin this maps onto.  For example,
  // __sync_fetch_and_add with a 2 byte object turns into
  // __sync_fetch_and_add_2.
#define BUILTIN_ROW(x) \
  { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \
    Builtin::BI##x##_8, Builtin::BI##x##_16 }

  static const unsigned BuiltinIndices[][5] = {
    BUILTIN_ROW(__sync_fetch_and_add),
    BUILTIN_ROW(__sync_fetch_and_sub),
    BUILTIN_ROW(__sync_fetch_and_or),
    BUILTIN_ROW(__sync_fetch_and_and),
    BUILTIN_ROW(__sync_fetch_and_xor),
    BUILTIN_ROW(__sync_fetch_and_nand),

    BUILTIN_ROW(__sync_add_and_fetch),
    BUILTIN_ROW(__sync_sub_and_fetch),
    BUILTIN_ROW(__sync_and_and_fetch),
    BUILTIN_ROW(__sync_or_and_fetch),
    BUILTIN_ROW(__sync_xor_and_fetch),
    BUILTIN_ROW(__sync_nand_and_fetch),

    BUILTIN_ROW(__sync_val_compare_and_swap),
    BUILTIN_ROW(__sync_bool_compare_and_swap),
    BUILTIN_ROW(__sync_lock_test_and_set),
    BUILTIN_ROW(__sync_lock_release),
    BUILTIN_ROW(__sync_swap)
  };
#undef BUILTIN_ROW

  // Determine the index of the size.
  unsigned SizeIndex;
  switch (Context.getTypeSizeInChars(ValType).getQuantity()) {
  case 1: SizeIndex = 0; break;
  case 2: SizeIndex = 1; break;
  case 4: SizeIndex = 2; break;
  case 8: SizeIndex = 3; break;
  case 16: SizeIndex = 4; break;
  default:
    Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_pointer_size)
        << FirstArg->getType() << FirstArg->getSourceRange();
    return ExprError();
  }

  // Each of these builtins has one pointer argument, followed by some number of
  // values (0, 1 or 2) followed by a potentially empty varags list of stuff
  // that we ignore.  Find out which row of BuiltinIndices to read from as well
  // as the number of fixed args.
  unsigned BuiltinID = FDecl->getBuiltinID();
  unsigned BuiltinIndex, NumFixed = 1;
  bool WarnAboutSemanticsChange = false;
  switch (BuiltinID) {
  default: llvm_unreachable("Unknown overloaded atomic builtin!");
  case Builtin::BI__sync_fetch_and_add:
  case Builtin::BI__sync_fetch_and_add_1:
  case Builtin::BI__sync_fetch_and_add_2:
  case Builtin::BI__sync_fetch_and_add_4:
  case Builtin::BI__sync_fetch_and_add_8:
  case Builtin::BI__sync_fetch_and_add_16:
    BuiltinIndex = 0;
    break;

  case Builtin::BI__sync_fetch_and_sub:
  case Builtin::BI__sync_fetch_and_sub_1:
  case Builtin::BI__sync_fetch_and_sub_2:
  case Builtin::BI__sync_fetch_and_sub_4:
  case Builtin::BI__sync_fetch_and_sub_8:
  case Builtin::BI__sync_fetch_and_sub_16:
    BuiltinIndex = 1;
    break;

  case Builtin::BI__sync_fetch_and_or:
  case Builtin::BI__sync_fetch_and_or_1:
  case Builtin::BI__sync_fetch_and_or_2:
  case Builtin::BI__sync_fetch_and_or_4:
  case Builtin::BI__sync_fetch_and_or_8:
  case Builtin::BI__sync_fetch_and_or_16:
    BuiltinIndex = 2;
    break;

  case Builtin::BI__sync_fetch_and_and:
  case Builtin::BI__sync_fetch_and_and_1:
  case Builtin::BI__sync_fetch_and_and_2:
  case Builtin::BI__sync_fetch_and_and_4:
  case Builtin::BI__sync_fetch_and_and_8:
  case Builtin::BI__sync_fetch_and_and_16:
    BuiltinIndex = 3;
    break;

  case Builtin::BI__sync_fetch_and_xor:
  case Builtin::BI__sync_fetch_and_xor_1:
  case Builtin::BI__sync_fetch_and_xor_2:
  case Builtin::BI__sync_fetch_and_xor_4:
  case Builtin::BI__sync_fetch_and_xor_8:
  case Builtin::BI__sync_fetch_and_xor_16:
    BuiltinIndex = 4;
    break;

  case Builtin::BI__sync_fetch_and_nand:
  case Builtin::BI__sync_fetch_and_nand_1:
  case Builtin::BI__sync_fetch_and_nand_2:
  case Builtin::BI__sync_fetch_and_nand_4:
  case Builtin::BI__sync_fetch_and_nand_8:
  case Builtin::BI__sync_fetch_and_nand_16:
    BuiltinIndex = 5;
    WarnAboutSemanticsChange = true;
    break;

  case Builtin::BI__sync_add_and_fetch:
  case Builtin::BI__sync_add_and_fetch_1:
  case Builtin::BI__sync_add_and_fetch_2:
  case Builtin::BI__sync_add_and_fetch_4:
  case Builtin::BI__sync_add_and_fetch_8:
  case Builtin::BI__sync_add_and_fetch_16:
    BuiltinIndex = 6;
    break;

  case Builtin::BI__sync_sub_and_fetch:
  case Builtin::BI__sync_sub_and_fetch_1:
  case Builtin::BI__sync_sub_and_fetch_2:
  case Builtin::BI__sync_sub_and_fetch_4:
  case Builtin::BI__sync_sub_and_fetch_8:
  case Builtin::BI__sync_sub_and_fetch_16:
    BuiltinIndex = 7;
    break;

  case Builtin::BI__sync_and_and_fetch:
  case Builtin::BI__sync_and_and_fetch_1:
  case Builtin::BI__sync_and_and_fetch_2:
  case Builtin::BI__sync_and_and_fetch_4:
  case Builtin::BI__sync_and_and_fetch_8:
  case Builtin::BI__sync_and_and_fetch_16:
    BuiltinIndex = 8;
    break;

  case Builtin::BI__sync_or_and_fetch:
  case Builtin::BI__sync_or_and_fetch_1:
  case Builtin::BI__sync_or_and_fetch_2:
  case Builtin::BI__sync_or_and_fetch_4:
  case Builtin::BI__sync_or_and_fetch_8:
  case Builtin::BI__sync_or_and_fetch_16:
    BuiltinIndex = 9;
    break;

  case Builtin::BI__sync_xor_and_fetch:
  case Builtin::BI__sync_xor_and_fetch_1:
  case Builtin::BI__sync_xor_and_fetch_2:
  case Builtin::BI__sync_xor_and_fetch_4:
  case Builtin::BI__sync_xor_and_fetch_8:
  case Builtin::BI__sync_xor_and_fetch_16:
    BuiltinIndex = 10;
    break;

  case Builtin::BI__sync_nand_and_fetch:
  case Builtin::BI__sync_nand_and_fetch_1:
  case Builtin::BI__sync_nand_and_fetch_2:
  case Builtin::BI__sync_nand_and_fetch_4:
  case Builtin::BI__sync_nand_and_fetch_8:
  case Builtin::BI__sync_nand_and_fetch_16:
    BuiltinIndex = 11;
    WarnAboutSemanticsChange = true;
    break;

  case Builtin::BI__sync_val_compare_and_swap:
  case Builtin::BI__sync_val_compare_and_swap_1:
  case Builtin::BI__sync_val_compare_and_swap_2:
  case Builtin::BI__sync_val_compare_and_swap_4:
  case Builtin::BI__sync_val_compare_and_swap_8:
  case Builtin::BI__sync_val_compare_and_swap_16:
    BuiltinIndex = 12;
    NumFixed = 2;
    break;

  case Builtin::BI__sync_bool_compare_and_swap:
  case Builtin::BI__sync_bool_compare_and_swap_1:
  case Builtin::BI__sync_bool_compare_and_swap_2:
  case Builtin::BI__sync_bool_compare_and_swap_4:
  case Builtin::BI__sync_bool_compare_and_swap_8:
  case Builtin::BI__sync_bool_compare_and_swap_16:
    BuiltinIndex = 13;
    NumFixed = 2;
    ResultType = Context.BoolTy;
    break;

  case Builtin::BI__sync_lock_test_and_set:
  case Builtin::BI__sync_lock_test_and_set_1:
  case Builtin::BI__sync_lock_test_and_set_2:
  case Builtin::BI__sync_lock_test_and_set_4:
  case Builtin::BI__sync_lock_test_and_set_8:
  case Builtin::BI__sync_lock_test_and_set_16:
    BuiltinIndex = 14;
    break;

  case Builtin::BI__sync_lock_release:
  case Builtin::BI__sync_lock_release_1:
  case Builtin::BI__sync_lock_release_2:
  case Builtin::BI__sync_lock_release_4:
  case Builtin::BI__sync_lock_release_8:
  case Builtin::BI__sync_lock_release_16:
    BuiltinIndex = 15;
    NumFixed = 0;
    ResultType = Context.VoidTy;
    break;

  case Builtin::BI__sync_swap:
  case Builtin::BI__sync_swap_1:
  case Builtin::BI__sync_swap_2:
  case Builtin::BI__sync_swap_4:
  case Builtin::BI__sync_swap_8:
  case Builtin::BI__sync_swap_16:
    BuiltinIndex = 16;
    break;
  }

  // Now that we know how many fixed arguments we expect, first check that we
  // have at least that many.
  if (TheCall->getNumArgs() < 1+NumFixed) {
    Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
        << 0 << 1 + NumFixed << TheCall->getNumArgs() << /*is non object*/ 0
        << Callee->getSourceRange();
    return ExprError();
  }

  Diag(TheCall->getEndLoc(), diag::warn_atomic_implicit_seq_cst)
      << Callee->getSourceRange();

  if (WarnAboutSemanticsChange) {
    Diag(TheCall->getEndLoc(), diag::warn_sync_fetch_and_nand_semantics_change)
        << Callee->getSourceRange();
  }

  // Get the decl for the concrete builtin from this, we can tell what the
  // concrete integer type we should convert to is.
  unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex];
  std::string NewBuiltinName = Context.BuiltinInfo.getName(NewBuiltinID);
  FunctionDecl *NewBuiltinDecl;
  if (NewBuiltinID == BuiltinID)
    NewBuiltinDecl = FDecl;
  else {
    // Perform builtin lookup to avoid redeclaring it.
    DeclarationName DN(&Context.Idents.get(NewBuiltinName));
    LookupResult Res(*this, DN, DRE->getBeginLoc(), LookupOrdinaryName);
    LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true);
    assert(Res.getFoundDecl());
    NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl());
    if (!NewBuiltinDecl)
      return ExprError();
  }

  // The first argument --- the pointer --- has a fixed type; we
  // deduce the types of the rest of the arguments accordingly.  Walk
  // the remaining arguments, converting them to the deduced value type.
  for (unsigned i = 0; i != NumFixed; ++i) {
    ExprResult Arg = TheCall->getArg(i+1);

    // GCC does an implicit conversion to the pointer or integer ValType.  This
    // can fail in some cases (1i -> int**), check for this error case now.
    // Initialize the argument.
    InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
                                                   ValType, /*consume*/ false);
    Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
    if (Arg.isInvalid())
      return ExprError();

    // Okay, we have something that *can* be converted to the right type.  Check
    // to see if there is a potentially weird extension going on here.  This can
    // happen when you do an atomic operation on something like an char* and
    // pass in 42.  The 42 gets converted to char.  This is even more strange
    // for things like 45.123 -> char, etc.
    // FIXME: Do this check.
    TheCall->setArg(i+1, Arg.get());
  }

  // Create a new DeclRefExpr to refer to the new decl.
  DeclRefExpr *NewDRE = DeclRefExpr::Create(
      Context, DRE->getQualifierLoc(), SourceLocation(), NewBuiltinDecl,
      /*enclosing*/ false, DRE->getLocation(), Context.BuiltinFnTy,
      DRE->getValueKind(), nullptr, nullptr, DRE->isNonOdrUse());

  // Set the callee in the CallExpr.
  // FIXME: This loses syntactic information.
  QualType CalleePtrTy = Context.getPointerType(NewBuiltinDecl->getType());
  ExprResult PromotedCall = ImpCastExprToType(NewDRE, CalleePtrTy,
                                              CK_BuiltinFnToFnPtr);
  TheCall->setCallee(PromotedCall.get());

  // Change the result type of the call to match the original value type. This
  // is arbitrary, but the codegen for these builtins ins design to handle it
  // gracefully.
  TheCall->setType(ResultType);

  // Prohibit problematic uses of bit-precise integer types with atomic
  // builtins. The arguments would have already been converted to the first
  // argument's type, so only need to check the first argument.
  const auto *BitIntValType = ValType->getAs<BitIntType>();
  if (BitIntValType && !llvm::isPowerOf2_64(BitIntValType->getNumBits())) {
    Diag(FirstArg->getExprLoc(), diag::err_atomic_builtin_ext_int_size);
    return ExprError();
  }

  return TheCallResult;
}

ExprResult Sema::BuiltinNontemporalOverloaded(ExprResult TheCallResult) {
  CallExpr *TheCall = (CallExpr *)TheCallResult.get();
  DeclRefExpr *DRE =
      cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
  FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
  unsigned BuiltinID = FDecl->getBuiltinID();
  assert((BuiltinID == Builtin::BI__builtin_nontemporal_store ||
          BuiltinID == Builtin::BI__builtin_nontemporal_load) &&
         "Unexpected nontemporal load/store builtin!");
  bool isStore = BuiltinID == Builtin::BI__builtin_nontemporal_store;
  unsigned numArgs = isStore ? 2 : 1;

  // Ensure that we have the proper number of arguments.
  if (checkArgCount(TheCall, numArgs))
    return ExprError();

  // Inspect the last argument of the nontemporal builtin.  This should always
  // be a pointer type, from which we imply the type of the memory access.
  // Because it is a pointer type, we don't have to worry about any implicit
  // casts here.
  Expr *PointerArg = TheCall->getArg(numArgs - 1);
  ExprResult PointerArgResult =
      DefaultFunctionArrayLvalueConversion(PointerArg);

  if (PointerArgResult.isInvalid())
    return ExprError();
  PointerArg = PointerArgResult.get();
  TheCall->setArg(numArgs - 1, PointerArg);

  const PointerType *pointerType = PointerArg->getType()->getAs<PointerType>();
  if (!pointerType) {
    Diag(DRE->getBeginLoc(), diag::err_nontemporal_builtin_must_be_pointer)
        << PointerArg->getType() << PointerArg->getSourceRange();
    return ExprError();
  }

  QualType ValType = pointerType->getPointeeType();

  // Strip any qualifiers off ValType.
  ValType = ValType.getUnqualifiedType();
  if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
      !ValType->isBlockPointerType() && !ValType->isFloatingType() &&
      !ValType->isVectorType()) {
    Diag(DRE->getBeginLoc(),
         diag::err_nontemporal_builtin_must_be_pointer_intfltptr_or_vector)
        << PointerArg->getType() << PointerArg->getSourceRange();
    return ExprError();
  }

  if (!isStore) {
    TheCall->setType(ValType);
    return TheCallResult;
  }

  ExprResult ValArg = TheCall->getArg(0);
  InitializedEntity Entity = InitializedEntity::InitializeParameter(
      Context, ValType, /*consume*/ false);
  ValArg = PerformCopyInitialization(Entity, SourceLocation(), ValArg);
  if (ValArg.isInvalid())
    return ExprError();

  TheCall->setArg(0, ValArg.get());
  TheCall->setType(Context.VoidTy);
  return TheCallResult;
}

/// CheckObjCString - Checks that the format string argument to the os_log()
/// and os_trace() functions is correct, and converts it to const char *.
ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) {
  Arg = Arg->IgnoreParenCasts();
  auto *Literal = dyn_cast<StringLiteral>(Arg);
  if (!Literal) {
    if (auto *ObjcLiteral = dyn_cast<ObjCStringLiteral>(Arg)) {
      Literal = ObjcLiteral->getString();
    }
  }

  if (!Literal || (!Literal->isOrdinary() && !Literal->isUTF8())) {
    return ExprError(
        Diag(Arg->getBeginLoc(), diag::err_os_log_format_not_string_constant)
        << Arg->getSourceRange());
  }

  ExprResult Result(Literal);
  QualType ResultTy = Context.getPointerType(Context.CharTy.withConst());
  InitializedEntity Entity =
      InitializedEntity::InitializeParameter(Context, ResultTy, false);
  Result = PerformCopyInitialization(Entity, SourceLocation(), Result);
  return Result;
}

/// Check that the user is calling the appropriate va_start builtin for the
/// target and calling convention.
static bool checkVAStartABI(Sema &S, unsigned BuiltinID, Expr *Fn) {
  const llvm::Triple &TT = S.Context.getTargetInfo().getTriple();
  bool IsX64 = TT.getArch() == llvm::Triple::x86_64;
  bool IsAArch64 = (TT.getArch() == llvm::Triple::aarch64 ||
                    TT.getArch() == llvm::Triple::aarch64_32);
  bool IsWindowsOrUEFI = TT.isOSWindows() || TT.isUEFI();
  bool IsMSVAStart = BuiltinID == Builtin::BI__builtin_ms_va_start;
  if (IsX64 || IsAArch64) {
    CallingConv CC = CC_C;
    if (const FunctionDecl *FD = S.getCurFunctionDecl())
      CC = FD->getType()->castAs<FunctionType>()->getCallConv();
    if (IsMSVAStart) {
      // Don't allow this in System V ABI functions.
      if (CC == CC_X86_64SysV || (!IsWindowsOrUEFI && CC != CC_Win64))
        return S.Diag(Fn->getBeginLoc(),
                      diag::err_ms_va_start_used_in_sysv_function);
    } else {
      // On x86-64/AArch64 Unix, don't allow this in Win64 ABI functions.
      // On x64 Windows, don't allow this in System V ABI functions.
      // (Yes, that means there's no corresponding way to support variadic
      // System V ABI functions on Windows.)
      if ((IsWindowsOrUEFI && CC == CC_X86_64SysV) ||
          (!IsWindowsOrUEFI && CC == CC_Win64))
        return S.Diag(Fn->getBeginLoc(),
                      diag::err_va_start_used_in_wrong_abi_function)
               << !IsWindowsOrUEFI;
    }
    return false;
  }

  if (IsMSVAStart)
    return S.Diag(Fn->getBeginLoc(), diag::err_builtin_x64_aarch64_only);
  return false;
}

static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn,
                                             ParmVarDecl **LastParam = nullptr) {
  // Determine whether the current function, block, or obj-c method is variadic
  // and get its parameter list.
  bool IsVariadic = false;
  ArrayRef<ParmVarDecl *> Params;
  DeclContext *Caller = S.CurContext;
  if (auto *Block = dyn_cast<BlockDecl>(Caller)) {
    IsVariadic = Block->isVariadic();
    Params = Block->parameters();
  } else if (auto *FD = dyn_cast<FunctionDecl>(Caller)) {
    IsVariadic = FD->isVariadic();
    Params = FD->parameters();
  } else if (auto *MD = dyn_cast<ObjCMethodDecl>(Caller)) {
    IsVariadic = MD->isVariadic();
    // FIXME: This isn't correct for methods (results in bogus warning).
    Params = MD->parameters();
  } else if (isa<CapturedDecl>(Caller)) {
    // We don't support va_start in a CapturedDecl.
    S.Diag(Fn->getBeginLoc(), diag::err_va_start_captured_stmt);
    return true;
  } else {
    // This must be some other declcontext that parses exprs.
    S.Diag(Fn->getBeginLoc(), diag::err_va_start_outside_function);
    return true;
  }

  if (!IsVariadic) {
    S.Diag(Fn->getBeginLoc(), diag::err_va_start_fixed_function);
    return true;
  }

  if (LastParam)
    *LastParam = Params.empty() ? nullptr : Params.back();

  return false;
}

bool Sema::BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
  Expr *Fn = TheCall->getCallee();
  if (checkVAStartABI(*this, BuiltinID, Fn))
    return true;

  if (BuiltinID == Builtin::BI__builtin_c23_va_start) {
    // This builtin requires one argument (the va_list), allows two arguments,
    // but diagnoses more than two arguments. e.g.,
    //   __builtin_c23_va_start(); // error
    //   __builtin_c23_va_start(list); // ok
    //   __builtin_c23_va_start(list, param); // ok
    //   __builtin_c23_va_start(list, anything, anything); // error
    // This differs from the GCC behavior in that they accept the last case
    // with a warning, but it doesn't seem like a useful behavior to allow.
    if (checkArgCountRange(TheCall, 1, 2))
      return true;
  } else {
    // In C23 mode, va_start only needs one argument. However, the builtin still
    // requires two arguments (which matches the behavior of the GCC builtin),
    // <stdarg.h> passes `0` as the second argument in C23 mode.
    if (checkArgCount(TheCall, 2))
      return true;
  }

  // Type-check the first argument normally.
  if (checkBuiltinArgument(*this, TheCall, 0))
    return true;

  // Check that the current function is variadic, and get its last parameter.
  ParmVarDecl *LastParam;
  if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam))
    return true;

  // Verify that the second argument to the builtin is the last non-variadic
  // argument of the current function or method. In C23 mode, if the call is
  // not to __builtin_c23_va_start, and the second argument is an integer
  // constant expression with value 0, then we don't bother with this check.
  // For __builtin_c23_va_start, we only perform the check for the second
  // argument being the last argument to the current function if there is a
  // second argument present.
  if (BuiltinID == Builtin::BI__builtin_c23_va_start &&
      TheCall->getNumArgs() < 2) {
    Diag(TheCall->getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
    return false;
  }

  const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
  if (std::optional<llvm::APSInt> Val =
          TheCall->getArg(1)->getIntegerConstantExpr(Context);
      Val && LangOpts.C23 && *Val == 0 &&
      BuiltinID != Builtin::BI__builtin_c23_va_start) {
    Diag(TheCall->getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
    return false;
  }

  // These are valid if SecondArgIsLastNonVariadicArgument is false after the
  // next block.
  QualType Type;
  SourceLocation ParamLoc;
  bool IsCRegister = false;
  bool SecondArgIsLastNonVariadicArgument = false;
  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
    if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
      SecondArgIsLastNonVariadicArgument = PV == LastParam;

      Type = PV->getType();
      ParamLoc = PV->getLocation();
      IsCRegister =
          PV->getStorageClass() == SC_Register && !getLangOpts().CPlusPlus;
    }
  }

  if (!SecondArgIsLastNonVariadicArgument)
    Diag(TheCall->getArg(1)->getBeginLoc(),
         diag::warn_second_arg_of_va_start_not_last_non_variadic_param);
  else if (IsCRegister || Type->isReferenceType() ||
           Type->isSpecificBuiltinType(BuiltinType::Float) || [=] {
             // Promotable integers are UB, but enumerations need a bit of
             // extra checking to see what their promotable type actually is.
             if (!Context.isPromotableIntegerType(Type))
               return false;
             if (!Type->isEnumeralType())
               return true;
             const EnumDecl *ED = Type->castAs<EnumType>()->getDecl();
             return !(ED &&
                      Context.typesAreCompatible(ED->getPromotionType(), Type));
           }()) {
    unsigned Reason = 0;
    if (Type->isReferenceType())  Reason = 1;
    else if (IsCRegister)         Reason = 2;
    Diag(Arg->getBeginLoc(), diag::warn_va_start_type_is_undefined) << Reason;
    Diag(ParamLoc, diag::note_parameter_type) << Type;
  }

  return false;
}

bool Sema::BuiltinVAStartARMMicrosoft(CallExpr *Call) {
  auto IsSuitablyTypedFormatArgument = [this](const Expr *Arg) -> bool {
    const LangOptions &LO = getLangOpts();

    if (LO.CPlusPlus)
      return Arg->getType()
                 .getCanonicalType()
                 .getTypePtr()
                 ->getPointeeType()
                 .withoutLocalFastQualifiers() == Context.CharTy;

    // In C, allow aliasing through `char *`, this is required for AArch64 at
    // least.
    return true;
  };

  // void __va_start(va_list *ap, const char *named_addr, size_t slot_size,
  //                 const char *named_addr);

  Expr *Func = Call->getCallee();

  if (Call->getNumArgs() < 3)
    return Diag(Call->getEndLoc(),
                diag::err_typecheck_call_too_few_args_at_least)
           << 0 /*function call*/ << 3 << Call->getNumArgs()
           << /*is non object*/ 0;

  // Type-check the first argument normally.
  if (checkBuiltinArgument(*this, Call, 0))
    return true;

  // Check that the current function is variadic.
  if (checkVAStartIsInVariadicFunction(*this, Func))
    return true;

  // __va_start on Windows does not validate the parameter qualifiers

  const Expr *Arg1 = Call->getArg(1)->IgnoreParens();
  const Type *Arg1Ty = Arg1->getType().getCanonicalType().getTypePtr();

  const Expr *Arg2 = Call->getArg(2)->IgnoreParens();
  const Type *Arg2Ty = Arg2->getType().getCanonicalType().getTypePtr();

  const QualType &ConstCharPtrTy =
      Context.getPointerType(Context.CharTy.withConst());
  if (!Arg1Ty->isPointerType() || !IsSuitablyTypedFormatArgument(Arg1))
    Diag(Arg1->getBeginLoc(), diag::err_typecheck_convert_incompatible)
        << Arg1->getType() << ConstCharPtrTy << 1 /* different class */
        << 0                                      /* qualifier difference */
        << 3                                      /* parameter mismatch */
        << 2 << Arg1->getType() << ConstCharPtrTy;

  const QualType SizeTy = Context.getSizeType();
  if (Arg2Ty->getCanonicalTypeInternal().withoutLocalFastQualifiers() != SizeTy)
    Diag(Arg2->getBeginLoc(), diag::err_typecheck_convert_incompatible)
        << Arg2->getType() << SizeTy << 1 /* different class */
        << 0                              /* qualifier difference */
        << 3                              /* parameter mismatch */
        << 3 << Arg2->getType() << SizeTy;

  return false;
}

bool Sema::BuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) {
  if (checkArgCount(TheCall, 2))
    return true;

  if (BuiltinID == Builtin::BI__builtin_isunordered &&
      TheCall->getFPFeaturesInEffect(getLangOpts()).getNoHonorNaNs())
    Diag(TheCall->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
        << 1 << 0 << TheCall->getSourceRange();

  ExprResult OrigArg0 = TheCall->getArg(0);
  ExprResult OrigArg1 = TheCall->getArg(1);

  // Do standard promotions between the two arguments, returning their common
  // type.
  QualType Res = UsualArithmeticConversions(
      OrigArg0, OrigArg1, TheCall->getExprLoc(), ArithConvKind::Comparison);
  if (OrigArg0.isInvalid() || OrigArg1.isInvalid())
    return true;

  // Make sure any conversions are pushed back into the call; this is
  // type safe since unordered compare builtins are declared as "_Bool
  // foo(...)".
  TheCall->setArg(0, OrigArg0.get());
  TheCall->setArg(1, OrigArg1.get());

  if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent())
    return false;

  // If the common type isn't a real floating type, then the arguments were
  // invalid for this operation.
  if (Res.isNull() || !Res->isRealFloatingType())
    return Diag(OrigArg0.get()->getBeginLoc(),
                diag::err_typecheck_call_invalid_ordered_compare)
           << OrigArg0.get()->getType() << OrigArg1.get()->getType()
           << SourceRange(OrigArg0.get()->getBeginLoc(),
                          OrigArg1.get()->getEndLoc());

  return false;
}

bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
                                   unsigned BuiltinID) {
  if (checkArgCount(TheCall, NumArgs))
    return true;

  FPOptions FPO = TheCall->getFPFeaturesInEffect(getLangOpts());
  if (FPO.getNoHonorInfs() && (BuiltinID == Builtin::BI__builtin_isfinite ||
                               BuiltinID == Builtin::BI__builtin_isinf ||
                               BuiltinID == Builtin::BI__builtin_isinf_sign))
    Diag(TheCall->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
        << 0 << 0 << TheCall->getSourceRange();

  if (FPO.getNoHonorNaNs() && (BuiltinID == Builtin::BI__builtin_isnan ||
                               BuiltinID == Builtin::BI__builtin_isunordered))
    Diag(TheCall->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
        << 1 << 0 << TheCall->getSourceRange();

  bool IsFPClass = NumArgs == 2;

  // Find out position of floating-point argument.
  unsigned FPArgNo = IsFPClass ? 0 : NumArgs - 1;

  // We can count on all parameters preceding the floating-point just being int.
  // Try all of those.
  for (unsigned i = 0; i < FPArgNo; ++i) {
    Expr *Arg = TheCall->getArg(i);

    if (Arg->isTypeDependent())
      return false;

    ExprResult Res = PerformImplicitConversion(Arg, Context.IntTy,
                                               AssignmentAction::Passing);

    if (Res.isInvalid())
      return true;
    TheCall->setArg(i, Res.get());
  }

  Expr *OrigArg = TheCall->getArg(FPArgNo);

  if (OrigArg->isTypeDependent())
    return false;

  // Usual Unary Conversions will convert half to float, which we want for
  // machines that use fp16 conversion intrinsics. Else, we wnat to leave the
  // type how it is, but do normal L->Rvalue conversions.
  if (Context.getTargetInfo().useFP16ConversionIntrinsics()) {
    ExprResult Res = UsualUnaryConversions(OrigArg);

    if (!Res.isUsable())
      return true;
    OrigArg = Res.get();
  } else {
    ExprResult Res = DefaultFunctionArrayLvalueConversion(OrigArg);

    if (!Res.isUsable())
      return true;
    OrigArg = Res.get();
  }
  TheCall->setArg(FPArgNo, OrigArg);

  QualType VectorResultTy;
  QualType ElementTy = OrigArg->getType();
  // TODO: When all classification function are implemented with is_fpclass,
  // vector argument can be supported in all of them.
  if (ElementTy->isVectorType() && IsFPClass) {
    VectorResultTy = GetSignedVectorType(ElementTy);
    ElementTy = ElementTy->castAs<VectorType>()->getElementType();
  }

  // This operation requires a non-_Complex floating-point number.
  if (!ElementTy->isRealFloatingType())
    return Diag(OrigArg->getBeginLoc(),
                diag::err_typecheck_call_invalid_unary_fp)
           << OrigArg->getType() << OrigArg->getSourceRange();

  // __builtin_isfpclass has integer parameter that specify test mask. It is
  // passed in (...), so it should be analyzed completely here.
  if (IsFPClass)
    if (BuiltinConstantArgRange(TheCall, 1, 0, llvm::fcAllFlags))
      return true;

  // TODO: enable this code to all classification functions.
  if (IsFPClass) {
    QualType ResultTy;
    if (!VectorResultTy.isNull())
      ResultTy = VectorResultTy;
    else
      ResultTy = Context.IntTy;
    TheCall->setType(ResultTy);
  }

  return false;
}

bool Sema::BuiltinComplex(CallExpr *TheCall) {
  if (checkArgCount(TheCall, 2))
    return true;

  bool Dependent = false;
  for (unsigned I = 0; I != 2; ++I) {
    Expr *Arg = TheCall->getArg(I);
    QualType T = Arg->getType();
    if (T->isDependentType()) {
      Dependent = true;
      continue;
    }

    // Despite supporting _Complex int, GCC requires a real floating point type
    // for the operands of __builtin_complex.
    if (!T->isRealFloatingType()) {
      return Diag(Arg->getBeginLoc(), diag::err_typecheck_call_requires_real_fp)
             << Arg->getType() << Arg->getSourceRange();
    }

    ExprResult Converted = DefaultLvalueConversion(Arg);
    if (Converted.isInvalid())
      return true;
    TheCall->setArg(I, Converted.get());
  }

  if (Dependent) {
    TheCall->setType(Context.DependentTy);
    return false;
  }

  Expr *Real = TheCall->getArg(0);
  Expr *Imag = TheCall->getArg(1);
  if (!Context.hasSameType(Real->getType(), Imag->getType())) {
    return Diag(Real->getBeginLoc(),
                diag::err_typecheck_call_different_arg_types)
           << Real->getType() << Imag->getType()
           << Real->getSourceRange() << Imag->getSourceRange();
  }

  // We don't allow _Complex _Float16 nor _Complex __fp16 as type specifiers;
  // don't allow this builtin to form those types either.
  // FIXME: Should we allow these types?
  if (Real->getType()->isFloat16Type())
    return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec)
           << "_Float16";
  if (Real->getType()->isHalfType())
    return Diag(TheCall->getBeginLoc(), diag::err_invalid_complex_spec)
           << "half";

  TheCall->setType(Context.getComplexType(Real->getType()));
  return false;
}

/// BuiltinShuffleVector - Handle __builtin_shufflevector.
// This is declared to take (...), so we have to check everything.
ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) {
  if (TheCall->getNumArgs() < 2)
    return ExprError(Diag(TheCall->getEndLoc(),
                          diag::err_typecheck_call_too_few_args_at_least)
                     << 0 /*function call*/ << 2 << TheCall->getNumArgs()
                     << /*is non object*/ 0 << TheCall->getSourceRange());

  // Determine which of the following types of shufflevector we're checking:
  // 1) unary, vector mask: (lhs, mask)
  // 2) binary, scalar mask: (lhs, rhs, index, ..., index)
  QualType resType = TheCall->getArg(0)->getType();
  unsigned numElements = 0;

  if (!TheCall->getArg(0)->isTypeDependent() &&
      !TheCall->getArg(1)->isTypeDependent()) {
    QualType LHSType = TheCall->getArg(0)->getType();
    QualType RHSType = TheCall->getArg(1)->getType();

    if (!LHSType->isVectorType() || !RHSType->isVectorType())
      return ExprError(
          Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector)
          << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
          << SourceRange(TheCall->getArg(0)->getBeginLoc(),
                         TheCall->getArg(1)->getEndLoc()));

    numElements = LHSType->castAs<VectorType>()->getNumElements();
    unsigned numResElements = TheCall->getNumArgs() - 2;

    // Check to see if we have a call with 2 vector arguments, the unary shuffle
    // with mask.  If so, verify that RHS is an integer vector type with the
    // same number of elts as lhs.
    if (TheCall->getNumArgs() == 2) {
      if (!RHSType->hasIntegerRepresentation() ||
          RHSType->castAs<VectorType>()->getNumElements() != numElements)
        return ExprError(Diag(TheCall->getBeginLoc(),
                              diag::err_vec_builtin_incompatible_vector)
                         << TheCall->getDirectCallee()
                         << /*isMorethantwoArgs*/ false
                         << SourceRange(TheCall->getArg(1)->getBeginLoc(),
                                        TheCall->getArg(1)->getEndLoc()));
    } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
      return ExprError(Diag(TheCall->getBeginLoc(),
                            diag::err_vec_builtin_incompatible_vector)
                       << TheCall->getDirectCallee()
                       << /*isMorethantwoArgs*/ false
                       << SourceRange(TheCall->getArg(0)->getBeginLoc(),
                                      TheCall->getArg(1)->getEndLoc()));
    } else if (numElements != numResElements) {
      QualType eltType = LHSType->castAs<VectorType>()->getElementType();
      resType =
          Context.getVectorType(eltType, numResElements, VectorKind::Generic);
    }
  }

  for (unsigned i = 2; i < TheCall->getNumArgs(); i++) {
    Expr *Arg = TheCall->getArg(i);
    if (Arg->isTypeDependent() || Arg->isValueDependent())
      continue;

    std::optional<llvm::APSInt> Result;
    if (!(Result = Arg->getIntegerConstantExpr(Context)))
      return ExprError(Diag(TheCall->getBeginLoc(),
                            diag::err_shufflevector_nonconstant_argument)
                       << Arg->getSourceRange());

    // Allow -1 which will be translated to undef in the IR.
    if (Result->isSigned() && Result->isAllOnes())
      ;
    else if (Result->getActiveBits() > 64 ||
             Result->getZExtValue() >= numElements * 2)
      return ExprError(Diag(TheCall->getBeginLoc(),
                            diag::err_shufflevector_argument_too_large)
                       << Arg->getSourceRange());

    TheCall->setArg(i, ConstantExpr::Create(Context, Arg, APValue(*Result)));
  }

  SmallVector<Expr *> exprs;
  for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) {
    exprs.push_back(TheCall->getArg(i));
    TheCall->setArg(i, nullptr);
  }

  return new (Context) ShuffleVectorExpr(Context, exprs, resType,
                                         TheCall->getCallee()->getBeginLoc(),
                                         TheCall->getRParenLoc());
}

ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
                                   SourceLocation BuiltinLoc,
                                   SourceLocation RParenLoc) {
  ExprValueKind VK = VK_PRValue;
  ExprObjectKind OK = OK_Ordinary;
  QualType DstTy = TInfo->getType();
  QualType SrcTy = E->getType();

  if (!SrcTy->isVectorType() && !SrcTy->isDependentType())
    return ExprError(Diag(BuiltinLoc,
                          diag::err_convertvector_non_vector)
                     << E->getSourceRange());
  if (!DstTy->isVectorType() && !DstTy->isDependentType())
    return ExprError(Diag(BuiltinLoc, diag::err_builtin_non_vector_type)
                     << "second"
                     << "__builtin_convertvector");

  if (!SrcTy->isDependentType() && !DstTy->isDependentType()) {
    unsigned SrcElts = SrcTy->castAs<VectorType>()->getNumElements();
    unsigned DstElts = DstTy->castAs<VectorType>()->getNumElements();
    if (SrcElts != DstElts)
      return ExprError(Diag(BuiltinLoc,
                            diag::err_convertvector_incompatible_vector)
                       << E->getSourceRange());
  }

  return ConvertVectorExpr::Create(Context, E, TInfo, DstTy, VK, OK, BuiltinLoc,
                                   RParenLoc, CurFPFeatureOverrides());
}

bool Sema::BuiltinPrefetch(CallExpr *TheCall) {
  unsigned NumArgs = TheCall->getNumArgs();

  if (NumArgs > 3)
    return Diag(TheCall->getEndLoc(),
                diag::err_typecheck_call_too_many_args_at_most)
           << 0 /*function call*/ << 3 << NumArgs << /*is non object*/ 0
           << TheCall->getSourceRange();

  // Argument 0 is checked for us and the remaining arguments must be
  // constant integers.
  for (unsigned i = 1; i != NumArgs; ++i)
    if (BuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3))
      return true;

  return false;
}

bool Sema::BuiltinArithmeticFence(CallExpr *TheCall) {
  if (!Context.getTargetInfo().checkArithmeticFenceSupported())
    return Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
           << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
  if (checkArgCount(TheCall, 1))
    return true;
  Expr *Arg = TheCall->getArg(0);
  if (Arg->isInstantiationDependent())
    return false;

  QualType ArgTy = Arg->getType();
  if (!ArgTy->hasFloatingRepresentation())
    return Diag(TheCall->getEndLoc(), diag::err_typecheck_expect_flt_or_vector)
           << ArgTy;
  if (Arg->isLValue()) {
    ExprResult FirstArg = DefaultLvalueConversion(Arg);
    TheCall->setArg(0, FirstArg.get());
  }
  TheCall->setType(TheCall->getArg(0)->getType());
  return false;
}

bool Sema::BuiltinAssume(CallExpr *TheCall) {
  Expr *Arg = TheCall->getArg(0);
  if (Arg->isInstantiationDependent()) return false;

  if (Arg->HasSideEffects(Context))
    Diag(Arg->getBeginLoc(), diag::warn_assume_side_effects)
        << Arg->getSourceRange()
        << cast<FunctionDecl>(TheCall->getCalleeDecl())->getIdentifier();

  return false;
}

bool Sema::BuiltinAllocaWithAlign(CallExpr *TheCall) {
  // The alignment must be a constant integer.
  Expr *Arg = TheCall->getArg(1);

  // We can't check the value of a dependent argument.
  if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
    if (const auto *UE =
            dyn_cast<UnaryExprOrTypeTraitExpr>(Arg->IgnoreParenImpCasts()))
      if (UE->getKind() == UETT_AlignOf ||
          UE->getKind() == UETT_PreferredAlignOf)
        Diag(TheCall->getBeginLoc(), diag::warn_alloca_align_alignof)
            << Arg->getSourceRange();

    llvm::APSInt Result = Arg->EvaluateKnownConstInt(Context);

    if (!Result.isPowerOf2())
      return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two)
             << Arg->getSourceRange();

    if (Result < Context.getCharWidth())
      return Diag(TheCall->getBeginLoc(), diag::err_alignment_too_small)
             << (unsigned)Context.getCharWidth() << Arg->getSourceRange();

    if (Result > std::numeric_limits<int32_t>::max())
      return Diag(TheCall->getBeginLoc(), diag::err_alignment_too_big)
             << std::numeric_limits<int32_t>::max() << Arg->getSourceRange();
  }

  return false;
}

bool Sema::BuiltinAssumeAligned(CallExpr *TheCall) {
  if (checkArgCountRange(TheCall, 2, 3))
    return true;

  unsigned NumArgs = TheCall->getNumArgs();
  Expr *FirstArg = TheCall->getArg(0);

  {
    ExprResult FirstArgResult =
        DefaultFunctionArrayLvalueConversion(FirstArg);
    if (!FirstArgResult.get()->getType()->isPointerType()) {
      Diag(TheCall->getBeginLoc(), diag::err_builtin_assume_aligned_invalid_arg)
          << TheCall->getSourceRange();
      return true;
    }
    TheCall->setArg(0, FirstArgResult.get());
  }

  // The alignment must be a constant integer.
  Expr *SecondArg = TheCall->getArg(1);

  // We can't check the value of a dependent argument.
  if (!SecondArg->isValueDependent()) {
    llvm::APSInt Result;
    if (BuiltinConstantArg(TheCall, 1, Result))
      return true;

    if (!Result.isPowerOf2())
      return Diag(TheCall->getBeginLoc(), diag::err_alignment_not_power_of_two)
             << SecondArg->getSourceRange();

    if (Result > Sema::MaximumAlignment)
      Diag(TheCall->getBeginLoc(), diag::warn_assume_aligned_too_great)
          << SecondArg->getSourceRange() << Sema::MaximumAlignment;
  }

  if (NumArgs > 2) {
    Expr *ThirdArg = TheCall->getArg(2);
    if (convertArgumentToType(*this, ThirdArg, Context.getSizeType()))
      return true;
    TheCall->setArg(2, ThirdArg);
  }

  return false;
}

bool Sema::BuiltinOSLogFormat(CallExpr *TheCall) {
  unsigned BuiltinID =
      cast<FunctionDecl>(TheCall->getCalleeDecl())->getBuiltinID();
  bool IsSizeCall = BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;

  unsigned NumArgs = TheCall->getNumArgs();
  unsigned NumRequiredArgs = IsSizeCall ? 1 : 2;
  if (NumArgs < NumRequiredArgs) {
    return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args)
           << 0 /* function call */ << NumRequiredArgs << NumArgs
           << /*is non object*/ 0 << TheCall->getSourceRange();
  }
  if (NumArgs >= NumRequiredArgs + 0x100) {
    return Diag(TheCall->getEndLoc(),
                diag::err_typecheck_call_too_many_args_at_most)
           << 0 /* function call */ << (NumRequiredArgs + 0xff) << NumArgs
           << /*is non object*/ 0 << TheCall->getSourceRange();
  }
  unsigned i = 0;

  // For formatting call, check buffer arg.
  if (!IsSizeCall) {
    ExprResult Arg(TheCall->getArg(i));
    InitializedEntity Entity = InitializedEntity::InitializeParameter(
        Context, Context.VoidPtrTy, false);
    Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
    if (Arg.isInvalid())
      return true;
    TheCall->setArg(i, Arg.get());
    i++;
  }

  // Check string literal arg.
  unsigned FormatIdx = i;
  {
    ExprResult Arg = CheckOSLogFormatStringArg(TheCall->getArg(i));
    if (Arg.isInvalid())
      return true;
    TheCall->setArg(i, Arg.get());
    i++;
  }

  // Make sure variadic args are scalar.
  unsigned FirstDataArg = i;
  while (i < NumArgs) {
    ExprResult Arg = DefaultVariadicArgumentPromotion(
        TheCall->getArg(i), VariadicCallType::Function, nullptr);
    if (Arg.isInvalid())
      return true;
    CharUnits ArgSize = Context.getTypeSizeInChars(Arg.get()->getType());
    if (ArgSize.getQuantity() >= 0x100) {
      return Diag(Arg.get()->getEndLoc(), diag::err_os_log_argument_too_big)
             << i << (int)ArgSize.getQuantity() << 0xff
             << TheCall->getSourceRange();
    }
    TheCall->setArg(i, Arg.get());
    i++;
  }

  // Check formatting specifiers. NOTE: We're only doing this for the non-size
  // call to avoid duplicate diagnostics.
  if (!IsSizeCall) {
    llvm::SmallBitVector CheckedVarArgs(NumArgs, false);
    ArrayRef<const Expr *> Args(TheCall->getArgs(), TheCall->getNumArgs());
    bool Success = CheckFormatArguments(
        Args, FAPK_Variadic, nullptr, FormatIdx, FirstDataArg,
        FormatStringType::OSLog, VariadicCallType::Function,
        TheCall->getBeginLoc(), SourceRange(), CheckedVarArgs);
    if (!Success)
      return true;
  }

  if (IsSizeCall) {
    TheCall->setType(Context.getSizeType());
  } else {
    TheCall->setType(Context.VoidPtrTy);
  }
  return false;
}

bool Sema::BuiltinConstantArg(CallExpr *TheCall, int ArgNum,
                              llvm::APSInt &Result) {
  Expr *Arg = TheCall->getArg(ArgNum);
  DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
  FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());

  if (Arg->isTypeDependent() || Arg->isValueDependent()) return false;

  std::optional<llvm::APSInt> R;
  if (!(R = Arg->getIntegerConstantExpr(Context)))
    return Diag(TheCall->getBeginLoc(), diag::err_constant_integer_arg_type)
           << FDecl->getDeclName() << Arg->getSourceRange();
  Result = *R;
  return false;
}

bool Sema::BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low,
                                   int High, bool RangeIsError) {
  if (isConstantEvaluatedContext())
    return false;
  llvm::APSInt Result;

  // We can't check the value of a dependent argument.
  Expr *Arg = TheCall->getArg(ArgNum);
  if (Arg->isTypeDependent() || Arg->isValueDependent())
    return false;

  // Check constant-ness first.
  if (BuiltinConstantArg(TheCall, ArgNum, Result))
    return true;

  if (Result.getSExtValue() < Low || Result.getSExtValue() > High) {
    if (RangeIsError)
      return Diag(TheCall->getBeginLoc(), diag::err_argument_invalid_range)
             << toString(Result, 10) << Low << High << Arg->getSourceRange();
    else
      // Defer the warning until we know if the code will be emitted so that
      // dead code can ignore this.
      DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
                          PDiag(diag::warn_argument_invalid_range)
                              << toString(Result, 10) << Low << High
                              << Arg->getSourceRange());
  }

  return false;
}

bool Sema::BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum,
                                      unsigned Num) {
  llvm::APSInt Result;

  // We can't check the value of a dependent argument.
  Expr *Arg = TheCall->getArg(ArgNum);
  if (Arg->isTypeDependent() || Arg->isValueDependent())
    return false;

  // Check constant-ness first.
  if (BuiltinConstantArg(TheCall, ArgNum, Result))
    return true;

  if (Result.getSExtValue() % Num != 0)
    return Diag(TheCall->getBeginLoc(), diag::err_argument_not_multiple)
           << Num << Arg->getSourceRange();

  return false;
}

bool Sema::BuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum) {
  llvm::APSInt Result;

  // We can't check the value of a dependent argument.
  Expr *Arg = TheCall->getArg(ArgNum);
  if (Arg->isTypeDependent() || Arg->isValueDependent())
    return false;

  // Check constant-ness first.
  if (BuiltinConstantArg(TheCall, ArgNum, Result))
    return true;

  // Bit-twiddling to test for a power of 2: for x > 0, x & (x-1) is zero if
  // and only if x is a power of 2.
  if (Result.isStrictlyPositive() && (Result & (Result - 1)) == 0)
    return false;

  return Diag(TheCall->getBeginLoc(), diag::err_argument_not_power_of_2)
         << Arg->getSourceRange();
}

static bool IsShiftedByte(llvm::APSInt Value) {
  if (Value.isNegative())
    return false;

  // Check if it's a shifted byte, by shifting it down
  while (true) {
    // If the value fits in the bottom byte, the check passes.
    if (Value < 0x100)
      return true;

    // Otherwise, if the value has _any_ bits in the bottom byte, the check
    // fails.
    if ((Value & 0xFF) != 0)
      return false;

    // If the bottom 8 bits are all 0, but something above that is nonzero,
    // then shifting the value right by 8 bits won't affect whether it's a
    // shifted byte or not. So do that, and go round again.
    Value >>= 8;
  }
}

bool Sema::BuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum,
                                         unsigned ArgBits) {
  llvm::APSInt Result;

  // We can't check the value of a dependent argument.
  Expr *Arg = TheCall->getArg(ArgNum);
  if (Arg->isTypeDependent() || Arg->isValueDependent())
    return false;

  // Check constant-ness first.
  if (BuiltinConstantArg(TheCall, ArgNum, Result))
    return true;

  // Truncate to the given size.
  Result = Result.getLoBits(ArgBits);
  Result.setIsUnsigned(true);

  if (IsShiftedByte(Result))
    return false;

  return Diag(TheCall->getBeginLoc(), diag::err_argument_not_shifted_byte)
         << Arg->getSourceRange();
}

bool Sema::BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum,
                                               unsigned ArgBits) {
  llvm::APSInt Result;

  // We can't check the value of a dependent argument.
  Expr *Arg = TheCall->getArg(ArgNum);
  if (Arg->isTypeDependent() || Arg->isValueDependent())
    return false;

  // Check constant-ness first.
  if (BuiltinConstantArg(TheCall, ArgNum, Result))
    return true;

  // Truncate to the given size.
  Result = Result.getLoBits(ArgBits);
  Result.setIsUnsigned(true);

  // Check to see if it's in either of the required forms.
  if (IsShiftedByte(Result) ||
      (Result > 0 && Result < 0x10000 && (Result & 0xFF) == 0xFF))
    return false;

  return Diag(TheCall->getBeginLoc(),
              diag::err_argument_not_shifted_byte_or_xxff)
         << Arg->getSourceRange();
}

bool Sema::BuiltinLongjmp(CallExpr *TheCall) {
  if (!Context.getTargetInfo().hasSjLjLowering())
    return Diag(TheCall->getBeginLoc(), diag::err_builtin_longjmp_unsupported)
           << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());

  Expr *Arg = TheCall->getArg(1);
  llvm::APSInt Result;

  // TODO: This is less than ideal. Overload this to take a value.
  if (BuiltinConstantArg(TheCall, 1, Result))
    return true;

  if (Result != 1)
    return Diag(TheCall->getBeginLoc(), diag::err_builtin_longjmp_invalid_val)
           << SourceRange(Arg->getBeginLoc(), Arg->getEndLoc());

  return false;
}

bool Sema::BuiltinSetjmp(CallExpr *TheCall) {
  if (!Context.getTargetInfo().hasSjLjLowering())
    return Diag(TheCall->getBeginLoc(), diag::err_builtin_setjmp_unsupported)
           << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
  return false;
}

bool Sema::BuiltinCountedByRef(CallExpr *TheCall) {
  if (checkArgCount(TheCall, 1))
    return true;

  ExprResult ArgRes = UsualUnaryConversions(TheCall->getArg(0));
  if (ArgRes.isInvalid())
    return true;

  // For simplicity, we support only limited expressions for the argument.
  // Specifically a pointer to a flexible array member:'ptr->array'. This
  // allows us to reject arguments with complex casting, which really shouldn't
  // be a huge problem.
  const Expr *Arg = ArgRes.get()->IgnoreParenImpCasts();
  if (!isa<PointerType>(Arg->getType()) && !Arg->getType()->isArrayType())
    return Diag(Arg->getBeginLoc(),
                diag::err_builtin_counted_by_ref_must_be_flex_array_member)
           << Arg->getSourceRange();

  if (Arg->HasSideEffects(Context))
    return Diag(Arg->getBeginLoc(),
                diag::err_builtin_counted_by_ref_has_side_effects)
           << Arg->getSourceRange();

  if (const auto *ME = dyn_cast<MemberExpr>(Arg)) {
    if (!ME->isFlexibleArrayMemberLike(
            Context, getLangOpts().getStrictFlexArraysLevel()))
      return Diag(Arg->getBeginLoc(),
                  diag::err_builtin_counted_by_ref_must_be_flex_array_member)
             << Arg->getSourceRange();

    if (auto *CATy =
            ME->getMemberDecl()->getType()->getAs<CountAttributedType>();
        CATy && CATy->getKind() == CountAttributedType::CountedBy) {
      const auto *FAMDecl = cast<FieldDecl>(ME->getMemberDecl());
      if (const FieldDecl *CountFD = FAMDecl->findCountedByField()) {
        TheCall->setType(Context.getPointerType(CountFD->getType()));
        return false;
      }
    }
  } else {
    return Diag(Arg->getBeginLoc(),
                diag::err_builtin_counted_by_ref_must_be_flex_array_member)
           << Arg->getSourceRange();
  }

  TheCall->setType(Context.getPointerType(Context.VoidTy));
  return false;
}

/// The result of __builtin_counted_by_ref cannot be assigned to a variable.
/// It allows leaking and modification of bounds safety information.
bool Sema::CheckInvalidBuiltinCountedByRef(const Expr *E,
                                           BuiltinCountedByRefKind K) {
  const CallExpr *CE =
      E ? dyn_cast<CallExpr>(E->IgnoreParenImpCasts()) : nullptr;
  if (!CE || CE->getBuiltinCallee() != Builtin::BI__builtin_counted_by_ref)
    return false;

  switch (K) {
  case BuiltinCountedByRefKind::Assignment:
  case BuiltinCountedByRefKind::Initializer:
    Diag(E->getExprLoc(),
         diag::err_builtin_counted_by_ref_cannot_leak_reference)
        << 0 << E->getSourceRange();
    break;
  case BuiltinCountedByRefKind::FunctionArg:
    Diag(E->getExprLoc(),
         diag::err_builtin_counted_by_ref_cannot_leak_reference)
        << 1 << E->getSourceRange();
    break;
  case BuiltinCountedByRefKind::ReturnArg:
    Diag(E->getExprLoc(),
         diag::err_builtin_counted_by_ref_cannot_leak_reference)
        << 2 << E->getSourceRange();
    break;
  case BuiltinCountedByRefKind::ArraySubscript:
    Diag(E->getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
        << 0 << E->getSourceRange();
    break;
  case BuiltinCountedByRefKind::BinaryExpr:
    Diag(E->getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
        << 1 << E->getSourceRange();
    break;
  }

  return true;
}

namespace {

class UncoveredArgHandler {
  enum { Unknown = -1, AllCovered = -2 };

  signed FirstUncoveredArg = Unknown;
  SmallVector<const Expr *, 4> DiagnosticExprs;

public:
  UncoveredArgHandler() = default;

  bool hasUncoveredArg() const {
    return (FirstUncoveredArg >= 0);
  }

  unsigned getUncoveredArg() const {
    assert(hasUncoveredArg() && "no uncovered argument");
    return FirstUncoveredArg;
  }

  void setAllCovered() {
    // A string has been found with all arguments covered, so clear out
    // the diagnostics.
    DiagnosticExprs.clear();
    FirstUncoveredArg = AllCovered;
  }

  void Update(signed NewFirstUncoveredArg, const Expr *StrExpr) {
    assert(NewFirstUncoveredArg >= 0 && "Outside range");

    // Don't update if a previous string covers all arguments.
    if (FirstUncoveredArg == AllCovered)
      return;

    // UncoveredArgHandler tracks the highest uncovered argument index
    // and with it all the strings that match this index.
    if (NewFirstUncoveredArg == FirstUncoveredArg)
      DiagnosticExprs.push_back(StrExpr);
    else if (NewFirstUncoveredArg > FirstUncoveredArg) {
      DiagnosticExprs.clear();
      DiagnosticExprs.push_back(StrExpr);
      FirstUncoveredArg = NewFirstUncoveredArg;
    }
  }

  void Diagnose(Sema &S, bool IsFunctionCall, const Expr *ArgExpr);
};

enum StringLiteralCheckType {
  SLCT_NotALiteral,
  SLCT_UncheckedLiteral,
  SLCT_CheckedLiteral
};

} // namespace

static void sumOffsets(llvm::APSInt &Offset, llvm::APSInt Addend,
                                     BinaryOperatorKind BinOpKind,
                                     bool AddendIsRight) {
  unsigned BitWidth = Offset.getBitWidth();
  unsigned AddendBitWidth = Addend.getBitWidth();
  // There might be negative interim results.
  if (Addend.isUnsigned()) {
    Addend = Addend.zext(++AddendBitWidth);
    Addend.setIsSigned(true);
  }
  // Adjust the bit width of the APSInts.
  if (AddendBitWidth > BitWidth) {
    Offset = Offset.sext(AddendBitWidth);
    BitWidth = AddendBitWidth;
  } else if (BitWidth > AddendBitWidth) {
    Addend = Addend.sext(BitWidth);
  }

  bool Ov = false;
  llvm::APSInt ResOffset = Offset;
  if (BinOpKind == BO_Add)
    ResOffset = Offset.sadd_ov(Addend, Ov);
  else {
    assert(AddendIsRight && BinOpKind == BO_Sub &&
           "operator must be add or sub with addend on the right");
    ResOffset = Offset.ssub_ov(Addend, Ov);
  }

  // We add an offset to a pointer here so we should support an offset as big as
  // possible.
  if (Ov) {
    assert(BitWidth <= std::numeric_limits<unsigned>::max() / 2 &&
           "index (intermediate) result too big");
    Offset = Offset.sext(2 * BitWidth);
    sumOffsets(Offset, Addend, BinOpKind, AddendIsRight);
    return;
  }

  Offset = ResOffset;
}

namespace {

// This is a wrapper class around StringLiteral to support offsetted string
// literals as format strings. It takes the offset into account when returning
// the string and its length or the source locations to display notes correctly.
class FormatStringLiteral {
  const StringLiteral *FExpr;
  int64_t Offset;

public:
  FormatStringLiteral(const StringLiteral *fexpr, int64_t Offset = 0)
      : FExpr(fexpr), Offset(Offset) {}

  const StringLiteral *getFormatString() const { return FExpr; }

  StringRef getString() const { return FExpr->getString().drop_front(Offset); }

  unsigned getByteLength() const {
    return FExpr->getByteLength() - getCharByteWidth() * Offset;
  }

  unsigned getLength() const { return FExpr->getLength() - Offset; }
  unsigned getCharByteWidth() const { return FExpr->getCharByteWidth(); }

  StringLiteralKind getKind() const { return FExpr->getKind(); }

  QualType getType() const { return FExpr->getType(); }

  bool isAscii() const { return FExpr->isOrdinary(); }
  bool isWide() const { return FExpr->isWide(); }
  bool isUTF8() const { return FExpr->isUTF8(); }
  bool isUTF16() const { return FExpr->isUTF16(); }
  bool isUTF32() const { return FExpr->isUTF32(); }
  bool isPascal() const { return FExpr->isPascal(); }

  SourceLocation getLocationOfByte(
      unsigned ByteNo, const SourceManager &SM, const LangOptions &Features,
      const TargetInfo &Target, unsigned *StartToken = nullptr,
      unsigned *StartTokenByteOffset = nullptr) const {
    return FExpr->getLocationOfByte(ByteNo + Offset, SM, Features, Target,
                                    StartToken, StartTokenByteOffset);
  }

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return FExpr->getBeginLoc().getLocWithOffset(Offset);
  }

  SourceLocation getEndLoc() const LLVM_READONLY { return FExpr->getEndLoc(); }
};

} // namespace

static void CheckFormatString(
    Sema &S, const FormatStringLiteral *FExpr,
    const StringLiteral *ReferenceFormatString, const Expr *OrigFormatExpr,
    ArrayRef<const Expr *> Args, Sema::FormatArgumentPassingKind APK,
    unsigned format_idx, unsigned firstDataArg, FormatStringType Type,
    bool inFunctionCall, VariadicCallType CallType,
    llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
    bool IgnoreStringsWithoutSpecifiers);

static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
                                               const Expr *E);

// Determine if an expression is a string literal or constant string.
// If this function returns false on the arguments to a function expecting a
// format string, we will usually need to emit a warning.
// True string literals are then checked by CheckFormatString.
static StringLiteralCheckType checkFormatStringExpr(
    Sema &S, const StringLiteral *ReferenceFormatString, const Expr *E,
    ArrayRef<const Expr *> Args, Sema::FormatArgumentPassingKind APK,
    unsigned format_idx, unsigned firstDataArg, FormatStringType Type,
    VariadicCallType CallType, bool InFunctionCall,
    llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
    llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) {
  if (S.isConstantEvaluatedContext())
    return SLCT_NotALiteral;
tryAgain:
  assert(Offset.isSigned() && "invalid offset");

  if (E->isTypeDependent() || E->isValueDependent())
    return SLCT_NotALiteral;

  E = E->IgnoreParenCasts();

  if (E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull))
    // Technically -Wformat-nonliteral does not warn about this case.
    // The behavior of printf and friends in this case is implementation
    // dependent.  Ideally if the format string cannot be null then
    // it should have a 'nonnull' attribute in the function prototype.
    return SLCT_UncheckedLiteral;

  switch (E->getStmtClass()) {
  case Stmt::InitListExprClass:
    // Handle expressions like {"foobar"}.
    if (const clang::Expr *SLE = maybeConstEvalStringLiteral(S.Context, E)) {
      return checkFormatStringExpr(
          S, ReferenceFormatString, SLE, Args, APK, format_idx, firstDataArg,
          Type, CallType, /*InFunctionCall*/ false, CheckedVarArgs,
          UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
    }
    return SLCT_NotALiteral;
  case Stmt::BinaryConditionalOperatorClass:
  case Stmt::ConditionalOperatorClass: {
    // The expression is a literal if both sub-expressions were, and it was
    // completely checked only if both sub-expressions were checked.
    const AbstractConditionalOperator *C =
        cast<AbstractConditionalOperator>(E);

    // Determine whether it is necessary to check both sub-expressions, for
    // example, because the condition expression is a constant that can be
    // evaluated at compile time.
    bool CheckLeft = true, CheckRight = true;

    bool Cond;
    if (C->getCond()->EvaluateAsBooleanCondition(
            Cond, S.getASTContext(), S.isConstantEvaluatedContext())) {
      if (Cond)
        CheckRight = false;
      else
        CheckLeft = false;
    }

    // We need to maintain the offsets for the right and the left hand side
    // separately to check if every possible indexed expression is a valid
    // string literal. They might have different offsets for different string
    // literals in the end.
    StringLiteralCheckType Left;
    if (!CheckLeft)
      Left = SLCT_UncheckedLiteral;
    else {
      Left = checkFormatStringExpr(
          S, ReferenceFormatString, C->getTrueExpr(), Args, APK, format_idx,
          firstDataArg, Type, CallType, InFunctionCall, CheckedVarArgs,
          UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
      if (Left == SLCT_NotALiteral || !CheckRight) {
        return Left;
      }
    }

    StringLiteralCheckType Right = checkFormatStringExpr(
        S, ReferenceFormatString, C->getFalseExpr(), Args, APK, format_idx,
        firstDataArg, Type, CallType, InFunctionCall, CheckedVarArgs,
        UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);

    return (CheckLeft && Left < Right) ? Left : Right;
  }

  case Stmt::ImplicitCastExprClass:
    E = cast<ImplicitCastExpr>(E)->getSubExpr();
    goto tryAgain;

  case Stmt::OpaqueValueExprClass:
    if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) {
      E = src;
      goto tryAgain;
    }
    return SLCT_NotALiteral;

  case Stmt::PredefinedExprClass:
    // While __func__, etc., are technically not string literals, they
    // cannot contain format specifiers and thus are not a security
    // liability.
    return SLCT_UncheckedLiteral;

  case Stmt::DeclRefExprClass: {
    const DeclRefExpr *DR = cast<DeclRefExpr>(E);

    // As an exception, do not flag errors for variables binding to
    // const string literals.
    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
      bool isConstant = false;
      QualType T = DR->getType();

      if (const ArrayType *AT = S.Context.getAsArrayType(T)) {
        isConstant = AT->getElementType().isConstant(S.Context);
      } else if (const PointerType *PT = T->getAs<PointerType>()) {
        isConstant = T.isConstant(S.Context) &&
                     PT->getPointeeType().isConstant(S.Context);
      } else if (T->isObjCObjectPointerType()) {
        // In ObjC, there is usually no "const ObjectPointer" type,
        // so don't check if the pointee type is constant.
        isConstant = T.isConstant(S.Context);
      }

      if (isConstant) {
        if (const Expr *Init = VD->getAnyInitializer()) {
          // Look through initializers like const char c[] = { "foo" }
          if (const InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) {
            if (InitList->isStringLiteralInit())
              Init = InitList->getInit(0)->IgnoreParenImpCasts();
          }
          return checkFormatStringExpr(
              S, ReferenceFormatString, Init, Args, APK, format_idx,
              firstDataArg, Type, CallType,
              /*InFunctionCall*/ false, CheckedVarArgs, UncoveredArg, Offset);
        }
      }

      // When the format argument is an argument of this function, and this
      // function also has the format attribute, there are several interactions
      // for which there shouldn't be a warning. For instance, when calling
      // v*printf from a function that has the printf format attribute, we
      // should not emit a warning about using `fmt`, even though it's not
      // constant, because the arguments have already been checked for the
      // caller of `logmessage`:
      //
      //  __attribute__((format(printf, 1, 2)))
      //  void logmessage(char const *fmt, ...) {
      //    va_list ap;
      //    va_start(ap, fmt);
      //    vprintf(fmt, ap);  /* do not emit a warning about "fmt" */
      //    ...
      // }
      //
      // Another interaction that we need to support is using a format string
      // specified by the format_matches attribute:
      //
      //  __attribute__((format_matches(printf, 1, "%s %d")))
      //  void logmessage(char const *fmt, const char *a, int b) {
      //    printf(fmt, a, b); /* do not emit a warning about "fmt" */
      //    printf(fmt, 123.4); /* emit warnings that "%s %d" is incompatible */
      //    ...
      // }
      //
      // Yet another interaction that we need to support is calling a variadic
      // format function from a format function that has fixed arguments. For
      // instance:
      //
      //  __attribute__((format(printf, 1, 2)))
      //  void logstring(char const *fmt, char const *str) {
      //    printf(fmt, str);  /* do not emit a warning about "fmt" */
      //  }
      //
      // Same (and perhaps more relatably) for the variadic template case:
      //
      //  template<typename... Args>
      //  __attribute__((format(printf, 1, 2)))
      //  void log(const char *fmt, Args&&... args) {
      //    printf(fmt, forward<Args>(args)...);
      //           /* do not emit a warning about "fmt" */
      //  }
      //
      // Due to implementation difficulty, we only check the format, not the
      // format arguments, in all cases.
      //
      if (const auto *PV = dyn_cast<ParmVarDecl>(VD)) {
        if (const auto *D = dyn_cast<Decl>(PV->getDeclContext())) {
          for (const auto *PVFormatMatches :
               D->specific_attrs<FormatMatchesAttr>()) {
            Sema::FormatStringInfo CalleeFSI;
            if (!Sema::getFormatStringInfo(D, PVFormatMatches->getFormatIdx(),
                                           0, &CalleeFSI))
              continue;
            if (PV->getFunctionScopeIndex() == CalleeFSI.FormatIdx) {
              // If using the wrong type of format string, emit a diagnostic
              // here and stop checking to avoid irrelevant diagnostics.
              if (Type != S.GetFormatStringType(PVFormatMatches)) {
                S.Diag(Args[format_idx]->getBeginLoc(),
                       diag::warn_format_string_type_incompatible)
                    << PVFormatMatches->getType()->getName()
                    << S.GetFormatStringTypeName(Type);
                if (!InFunctionCall) {
                  S.Diag(PVFormatMatches->getFormatString()->getBeginLoc(),
                         diag::note_format_string_defined);
                }
                return SLCT_UncheckedLiteral;
              }
              return checkFormatStringExpr(
                  S, ReferenceFormatString, PVFormatMatches->getFormatString(),
                  Args, APK, format_idx, firstDataArg, Type, CallType,
                  /*InFunctionCall*/ false, CheckedVarArgs, UncoveredArg,
                  Offset, IgnoreStringsWithoutSpecifiers);
            }
          }

          for (const auto *PVFormat : D->specific_attrs<FormatAttr>()) {
            Sema::FormatStringInfo CallerFSI;
            if (!Sema::getFormatStringInfo(D, PVFormat->getFormatIdx(),
                                           PVFormat->getFirstArg(), &CallerFSI))
              continue;
            if (PV->getFunctionScopeIndex() == CallerFSI.FormatIdx) {
              // We also check if the formats are compatible.
              // We can't pass a 'scanf' string to a 'printf' function.
              if (Type != S.GetFormatStringType(PVFormat)) {
                S.Diag(Args[format_idx]->getBeginLoc(),
                       diag::warn_format_string_type_incompatible)
                    << PVFormat->getType()->getName()
                    << S.GetFormatStringTypeName(Type);
                if (!InFunctionCall) {
                  S.Diag(E->getBeginLoc(), diag::note_format_string_defined);
                }
                return SLCT_UncheckedLiteral;
              }
              // Lastly, check that argument passing kinds transition in a
              // way that makes sense:
              // from a caller with FAPK_VAList, allow FAPK_VAList
              // from a caller with FAPK_Fixed, allow FAPK_Fixed
              // from a caller with FAPK_Fixed, allow FAPK_Variadic
              // from a caller with FAPK_Variadic, allow FAPK_VAList
              switch (combineFAPK(CallerFSI.ArgPassingKind, APK)) {
              case combineFAPK(Sema::FAPK_VAList, Sema::FAPK_VAList):
              case combineFAPK(Sema::FAPK_Fixed, Sema::FAPK_Fixed):
              case combineFAPK(Sema::FAPK_Fixed, Sema::FAPK_Variadic):
              case combineFAPK(Sema::FAPK_Variadic, Sema::FAPK_VAList):
                return SLCT_UncheckedLiteral;
              }
            }
          }
        }
      }
    }

    return SLCT_NotALiteral;
  }

  case Stmt::CallExprClass:
  case Stmt::CXXMemberCallExprClass: {
    const CallExpr *CE = cast<CallExpr>(E);
    if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
      bool IsFirst = true;
      StringLiteralCheckType CommonResult;
      for (const auto *FA : ND->specific_attrs<FormatArgAttr>()) {
        const Expr *Arg = CE->getArg(FA->getFormatIdx().getASTIndex());
        StringLiteralCheckType Result = checkFormatStringExpr(
            S, ReferenceFormatString, Arg, Args, APK, format_idx, firstDataArg,
            Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,
            Offset, IgnoreStringsWithoutSpecifiers);
        if (IsFirst) {
          CommonResult = Result;
          IsFirst = false;
        }
      }
      if (!IsFirst)
        return CommonResult;

      if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
        unsigned BuiltinID = FD->getBuiltinID();
        if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
            BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) {
          const Expr *Arg = CE->getArg(0);
          return checkFormatStringExpr(
              S, ReferenceFormatString, Arg, Args, APK, format_idx,
              firstDataArg, Type, CallType, InFunctionCall, CheckedVarArgs,
              UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
        }
      }
    }
    if (const Expr *SLE = maybeConstEvalStringLiteral(S.Context, E))
      return checkFormatStringExpr(
          S, ReferenceFormatString, SLE, Args, APK, format_idx, firstDataArg,
          Type, CallType, /*InFunctionCall*/ false, CheckedVarArgs,
          UncoveredArg, Offset, IgnoreStringsWithoutSpecifiers);
    return SLCT_NotALiteral;
  }
  case Stmt::ObjCMessageExprClass: {
    const auto *ME = cast<ObjCMessageExpr>(E);
    if (const auto *MD = ME->getMethodDecl()) {
      if (const auto *FA = MD->getAttr<FormatArgAttr>()) {
        // As a special case heuristic, if we're using the method -[NSBundle
        // localizedStringForKey:value:table:], ignore any key strings that lack
        // format specifiers. The idea is that if the key doesn't have any
        // format specifiers then its probably just a key to map to the
        // localized strings. If it does have format specifiers though, then its
        // likely that the text of the key is the format string in the
        // programmer's language, and should be checked.
        const ObjCInterfaceDecl *IFace;
        if (MD->isInstanceMethod() && (IFace = MD->getClassInterface()) &&
            IFace->getIdentifier()->isStr("NSBundle") &&
            MD->getSelector().isKeywordSelector(
                {"localizedStringForKey", "value", "table"})) {
          IgnoreStringsWithoutSpecifiers = true;
        }

        const Expr *Arg = ME->getArg(FA->getFormatIdx().getASTIndex());
        return checkFormatStringExpr(
            S, ReferenceFormatString, Arg, Args, APK, format_idx, firstDataArg,
            Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,
            Offset, IgnoreStringsWithoutSpecifiers);
      }
    }

    return SLCT_NotALiteral;
  }
  case Stmt::ObjCStringLiteralClass:
  case Stmt::StringLiteralClass: {
    const StringLiteral *StrE = nullptr;

    if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E))
      StrE = ObjCFExpr->getString();
    else
      StrE = cast<StringLiteral>(E);

    if (StrE) {
      if (Offset.isNegative() || Offset > StrE->getLength()) {
        // TODO: It would be better to have an explicit warning for out of
        // bounds literals.
        return SLCT_NotALiteral;
      }
      FormatStringLiteral FStr(StrE, Offset.sextOrTrunc(64).getSExtValue());
      CheckFormatString(S, &FStr, ReferenceFormatString, E, Args, APK,
                        format_idx, firstDataArg, Type, InFunctionCall,
                        CallType, CheckedVarArgs, UncoveredArg,
                        IgnoreStringsWithoutSpecifiers);
      return SLCT_CheckedLiteral;
    }

    return SLCT_NotALiteral;
  }
  case Stmt::BinaryOperatorClass: {
    const BinaryOperator *BinOp = cast<BinaryOperator>(E);

    // A string literal + an int offset is still a string literal.
    if (BinOp->isAdditiveOp()) {
      Expr::EvalResult LResult, RResult;

      bool LIsInt = BinOp->getLHS()->EvaluateAsInt(
          LResult, S.Context, Expr::SE_NoSideEffects,
          S.isConstantEvaluatedContext());
      bool RIsInt = BinOp->getRHS()->EvaluateAsInt(
          RResult, S.Context, Expr::SE_NoSideEffects,
          S.isConstantEvaluatedContext());

      if (LIsInt != RIsInt) {
        BinaryOperatorKind BinOpKind = BinOp->getOpcode();

        if (LIsInt) {
          if (BinOpKind == BO_Add) {
            sumOffsets(Offset, LResult.Val.getInt(), BinOpKind, RIsInt);
            E = BinOp->getRHS();
            goto tryAgain;
          }
        } else {
          sumOffsets(Offset, RResult.Val.getInt(), BinOpKind, RIsInt);
          E = BinOp->getLHS();
          goto tryAgain;
        }
      }
    }

    return SLCT_NotALiteral;
  }
  case Stmt::UnaryOperatorClass: {
    const UnaryOperator *UnaOp = cast<UnaryOperator>(E);
    auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr());
    if (UnaOp->getOpcode() == UO_AddrOf && ASE) {
      Expr::EvalResult IndexResult;
      if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context,
                                       Expr::SE_NoSideEffects,
                                       S.isConstantEvaluatedContext())) {
        sumOffsets(Offset, IndexResult.Val.getInt(), BO_Add,
                   /*RHS is int*/ true);
        E = ASE->getBase();
        goto tryAgain;
      }
    }

    return SLCT_NotALiteral;
  }

  default:
    return SLCT_NotALiteral;
  }
}

// If this expression can be evaluated at compile-time,
// check if the result is a StringLiteral and return it
// otherwise return nullptr
static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
                                               const Expr *E) {
  Expr::EvalResult Result;
  if (E->EvaluateAsRValue(Result, Context) && Result.Val.isLValue()) {
    const auto *LVE = Result.Val.getLValueBase().dyn_cast<const Expr *>();
    if (isa_and_nonnull<StringLiteral>(LVE))
      return LVE;
  }
  return nullptr;
}

StringRef Sema::GetFormatStringTypeName(FormatStringType FST) {
  switch (FST) {
  case FormatStringType::Scanf:
    return "scanf";
  case FormatStringType::Printf:
    return "printf";
  case FormatStringType::NSString:
    return "NSString";
  case FormatStringType::Strftime:
    return "strftime";
  case FormatStringType::Strfmon:
    return "strfmon";
  case FormatStringType::Kprintf:
    return "kprintf";
  case FormatStringType::FreeBSDKPrintf:
    return "freebsd_kprintf";
  case FormatStringType::OSLog:
    return "os_log";
  default:
    return "<unknown>";
  }
}

FormatStringType Sema::GetFormatStringType(StringRef Flavor) {
  return llvm::StringSwitch<FormatStringType>(Flavor)
      .Case("scanf", FormatStringType::Scanf)
      .Cases("printf", "printf0", "syslog", FormatStringType::Printf)
      .Cases("NSString", "CFString", FormatStringType::NSString)
      .Case("strftime", FormatStringType::Strftime)
      .Case("strfmon", FormatStringType::Strfmon)
      .Cases("kprintf", "cmn_err", "vcmn_err", "zcmn_err",
             FormatStringType::Kprintf)
      .Case("freebsd_kprintf", FormatStringType::FreeBSDKPrintf)
      .Case("os_trace", FormatStringType::OSLog)
      .Case("os_log", FormatStringType::OSLog)
      .Default(FormatStringType::Unknown);
}

FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
  return GetFormatStringType(Format->getType()->getName());
}

FormatStringType Sema::GetFormatStringType(const FormatMatchesAttr *Format) {
  return GetFormatStringType(Format->getType()->getName());
}

bool Sema::CheckFormatArguments(const FormatAttr *Format,
                                ArrayRef<const Expr *> Args, bool IsCXXMember,
                                VariadicCallType CallType, SourceLocation Loc,
                                SourceRange Range,
                                llvm::SmallBitVector &CheckedVarArgs) {
  FormatStringInfo FSI;
  if (getFormatStringInfo(Format->getFormatIdx(), Format->getFirstArg(),
                          IsCXXMember,
                          CallType != VariadicCallType::DoesNotApply, &FSI))
    return CheckFormatArguments(
        Args, FSI.ArgPassingKind, nullptr, FSI.FormatIdx, FSI.FirstDataArg,
        GetFormatStringType(Format), CallType, Loc, Range, CheckedVarArgs);
  return false;
}

bool Sema::CheckFormatString(const FormatMatchesAttr *Format,
                             ArrayRef<const Expr *> Args, bool IsCXXMember,
                             VariadicCallType CallType, SourceLocation Loc,
                             SourceRange Range,
                             llvm::SmallBitVector &CheckedVarArgs) {
  FormatStringInfo FSI;
  if (getFormatStringInfo(Format->getFormatIdx(), 0, IsCXXMember, false,
                          &FSI)) {
    FSI.ArgPassingKind = Sema::FAPK_Elsewhere;
    return CheckFormatArguments(Args, FSI.ArgPassingKind,
                                Format->getFormatString(), FSI.FormatIdx,
                                FSI.FirstDataArg, GetFormatStringType(Format),
                                CallType, Loc, Range, CheckedVarArgs);
  }
  return false;
}

bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args,
                                Sema::FormatArgumentPassingKind APK,
                                const StringLiteral *ReferenceFormatString,
                                unsigned format_idx, unsigned firstDataArg,
                                FormatStringType Type,
                                VariadicCallType CallType, SourceLocation Loc,
                                SourceRange Range,
                                llvm::SmallBitVector &CheckedVarArgs) {
  // CHECK: printf/scanf-like function is called with no format string.
  if (format_idx >= Args.size()) {
    Diag(Loc, diag::warn_missing_format_string) << Range;
    return false;
  }

  const Expr *OrigFormatExpr = Args[format_idx]->IgnoreParenCasts();

  // CHECK: format string is not a string literal.
  //
  // Dynamically generated format strings are difficult to
  // automatically vet at compile time.  Requiring that format strings
  // are string literals: (1) permits the checking of format strings by
  // the compiler and thereby (2) can practically remove the source of
  // many format string exploits.

  // Format string can be either ObjC string (e.g. @"%d") or
  // C string (e.g. "%d")
  // ObjC string uses the same format specifiers as C string, so we can use
  // the same format string checking logic for both ObjC and C strings.
  UncoveredArgHandler UncoveredArg;
  StringLiteralCheckType CT = checkFormatStringExpr(
      *this, ReferenceFormatString, OrigFormatExpr, Args, APK, format_idx,
      firstDataArg, Type, CallType,
      /*IsFunctionCall*/ true, CheckedVarArgs, UncoveredArg,
      /*no string offset*/ llvm::APSInt(64, false) = 0);

  // Generate a diagnostic where an uncovered argument is detected.
  if (UncoveredArg.hasUncoveredArg()) {
    unsigned ArgIdx = UncoveredArg.getUncoveredArg() + firstDataArg;
    assert(ArgIdx < Args.size() && "ArgIdx outside bounds");
    UncoveredArg.Diagnose(*this, /*IsFunctionCall*/true, Args[ArgIdx]);
  }

  if (CT != SLCT_NotALiteral)
    // Literal format string found, check done!
    return CT == SLCT_CheckedLiteral;

  // Strftime is particular as it always uses a single 'time' argument,
  // so it is safe to pass a non-literal string.
  if (Type == FormatStringType::Strftime)
    return false;

  // Do not emit diag when the string param is a macro expansion and the
  // format is either NSString or CFString. This is a hack to prevent
  // diag when using the NSLocalizedString and CFCopyLocalizedString macros
  // which are usually used in place of NS and CF string literals.
  SourceLocation FormatLoc = Args[format_idx]->getBeginLoc();
  if (Type == FormatStringType::NSString &&
      SourceMgr.isInSystemMacro(FormatLoc))
    return false;

  // If there are no arguments specified, warn with -Wformat-security, otherwise
  // warn only with -Wformat-nonliteral.
  if (Args.size() == firstDataArg) {
    Diag(FormatLoc, diag::warn_format_nonliteral_noargs)
      << OrigFormatExpr->getSourceRange();
    switch (Type) {
    default:
      break;
    case FormatStringType::Kprintf:
    case FormatStringType::FreeBSDKPrintf:
    case FormatStringType::Printf:
    case FormatStringType::Syslog:
      Diag(FormatLoc, diag::note_format_security_fixit)
        << FixItHint::CreateInsertion(FormatLoc, "\"%s\", ");
      break;
    case FormatStringType::NSString:
      Diag(FormatLoc, diag::note_format_security_fixit)
        << FixItHint::CreateInsertion(FormatLoc, "@\"%@\", ");
      break;
    }
  } else {
    Diag(FormatLoc, diag::warn_format_nonliteral)
      << OrigFormatExpr->getSourceRange();
  }
  return false;
}

namespace {

class CheckFormatHandler : public analyze_format_string::FormatStringHandler {
protected:
  Sema &S;
  const FormatStringLiteral *FExpr;
  const Expr *OrigFormatExpr;
  const FormatStringType FSType;
  const unsigned FirstDataArg;
  const unsigned NumDataArgs;
  const char *Beg; // Start of format string.
  const Sema::FormatArgumentPassingKind ArgPassingKind;
  ArrayRef<const Expr *> Args;
  unsigned FormatIdx;
  llvm::SmallBitVector CoveredArgs;
  bool usesPositionalArgs = false;
  bool atFirstArg = true;
  bool inFunctionCall;
  VariadicCallType CallType;
  llvm::SmallBitVector &CheckedVarArgs;
  UncoveredArgHandler &UncoveredArg;

public:
  CheckFormatHandler(Sema &s, const FormatStringLiteral *fexpr,
                     const Expr *origFormatExpr, const FormatStringType type,
                     unsigned firstDataArg, unsigned numDataArgs,
                     const char *beg, Sema::FormatArgumentPassingKind APK,
                     ArrayRef<const Expr *> Args, unsigned formatIdx,
                     bool inFunctionCall, VariadicCallType callType,
                     llvm::SmallBitVector &CheckedVarArgs,
                     UncoveredArgHandler &UncoveredArg)
      : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FSType(type),
        FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg),
        ArgPassingKind(APK), Args(Args), FormatIdx(formatIdx),
        inFunctionCall(inFunctionCall), CallType(callType),
        CheckedVarArgs(CheckedVarArgs), UncoveredArg(UncoveredArg) {
    CoveredArgs.resize(numDataArgs);
    CoveredArgs.reset();
  }

  bool HasFormatArguments() const {
    return ArgPassingKind == Sema::FAPK_Fixed ||
           ArgPassingKind == Sema::FAPK_Variadic;
  }

  void DoneProcessing();

  void HandleIncompleteSpecifier(const char *startSpecifier,
                                 unsigned specifierLen) override;

  void HandleInvalidLengthModifier(
                           const analyze_format_string::FormatSpecifier &FS,
                           const analyze_format_string::ConversionSpecifier &CS,
                           const char *startSpecifier, unsigned specifierLen,
                           unsigned DiagID);

  void HandleNonStandardLengthModifier(
                    const analyze_format_string::FormatSpecifier &FS,
                    const char *startSpecifier, unsigned specifierLen);

  void HandleNonStandardConversionSpecifier(
                    const analyze_format_string::ConversionSpecifier &CS,
                    const char *startSpecifier, unsigned specifierLen);

  void HandlePosition(const char *startPos, unsigned posLen) override;

  void HandleInvalidPosition(const char *startSpecifier,
                             unsigned specifierLen,
                             analyze_format_string::PositionContext p) override;

  void HandleZeroPosition(const char *startPos, unsigned posLen) override;

  void HandleNullChar(const char *nullCharacter) override;

  template <typename Range>
  static void
  EmitFormatDiagnostic(Sema &S, bool inFunctionCall, const Expr *ArgumentExpr,
                       const PartialDiagnostic &PDiag, SourceLocation StringLoc,
                       bool IsStringLocation, Range StringRange,
                       ArrayRef<FixItHint> Fixit = {});

protected:
  bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc,
                                        const char *startSpec,
                                        unsigned specifierLen,
                                        const char *csStart, unsigned csLen);

  void HandlePositionalNonpositionalArgs(SourceLocation Loc,
                                         const char *startSpec,
                                         unsigned specifierLen);

  SourceRange getFormatStringRange();
  CharSourceRange getSpecifierRange(const char *startSpecifier,
                                    unsigned specifierLen);
  SourceLocation getLocationOfByte(const char *x);

  const Expr *getDataArg(unsigned i) const;

  bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS,
                    const analyze_format_string::ConversionSpecifier &CS,
                    const char *startSpecifier, unsigned specifierLen,
                    unsigned argIndex);

  template <typename Range>
  void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc,
                            bool IsStringLocation, Range StringRange,
                            ArrayRef<FixItHint> Fixit = {});
};

} // namespace

SourceRange CheckFormatHandler::getFormatStringRange() {
  return OrigFormatExpr->getSourceRange();
}

CharSourceRange CheckFormatHandler::
getSpecifierRange(const char *startSpecifier, unsigned specifierLen) {
  SourceLocation Start = getLocationOfByte(startSpecifier);
  SourceLocation End   = getLocationOfByte(startSpecifier + specifierLen - 1);

  // Advance the end SourceLocation by one due to half-open ranges.
  End = End.getLocWithOffset(1);

  return CharSourceRange::getCharRange(Start, End);
}

SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) {
  return FExpr->getLocationOfByte(x - Beg, S.getSourceManager(),
                                  S.getLangOpts(), S.Context.getTargetInfo());
}

void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier,
                                                   unsigned specifierLen){
  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_incomplete_specifier),
                       getLocationOfByte(startSpecifier),
                       /*IsStringLocation*/true,
                       getSpecifierRange(startSpecifier, specifierLen));
}

void CheckFormatHandler::HandleInvalidLengthModifier(
    const analyze_format_string::FormatSpecifier &FS,
    const analyze_format_string::ConversionSpecifier &CS,
    const char *startSpecifier, unsigned specifierLen, unsigned DiagID) {
  using namespace analyze_format_string;

  const LengthModifier &LM = FS.getLengthModifier();
  CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength());

  // See if we know how to fix this length modifier.
  std::optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier();
  if (FixedLM) {
    EmitFormatDiagnostic(S.PDiag(DiagID) << LM.toString() << CS.toString(),
                         getLocationOfByte(LM.getStart()),
                         /*IsStringLocation*/true,
                         getSpecifierRange(startSpecifier, specifierLen));

    S.Diag(getLocationOfByte(LM.getStart()), diag::note_format_fix_specifier)
      << FixedLM->toString()
      << FixItHint::CreateReplacement(LMRange, FixedLM->toString());

  } else {
    FixItHint Hint;
    if (DiagID == diag::warn_format_nonsensical_length)
      Hint = FixItHint::CreateRemoval(LMRange);

    EmitFormatDiagnostic(S.PDiag(DiagID) << LM.toString() << CS.toString(),
                         getLocationOfByte(LM.getStart()),
                         /*IsStringLocation*/true,
                         getSpecifierRange(startSpecifier, specifierLen),
                         Hint);
  }
}

void CheckFormatHandler::HandleNonStandardLengthModifier(
    const analyze_format_string::FormatSpecifier &FS,
    const char *startSpecifier, unsigned specifierLen) {
  using namespace analyze_format_string;

  const LengthModifier &LM = FS.getLengthModifier();
  CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength());

  // See if we know how to fix this length modifier.
  std::optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier();
  if (FixedLM) {
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard)
                           << LM.toString() << 0,
                         getLocationOfByte(LM.getStart()),
                         /*IsStringLocation*/true,
                         getSpecifierRange(startSpecifier, specifierLen));

    S.Diag(getLocationOfByte(LM.getStart()), diag::note_format_fix_specifier)
      << FixedLM->toString()
      << FixItHint::CreateReplacement(LMRange, FixedLM->toString());

  } else {
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard)
                           << LM.toString() << 0,
                         getLocationOfByte(LM.getStart()),
                         /*IsStringLocation*/true,
                         getSpecifierRange(startSpecifier, specifierLen));
  }
}

void CheckFormatHandler::HandleNonStandardConversionSpecifier(
    const analyze_format_string::ConversionSpecifier &CS,
    const char *startSpecifier, unsigned specifierLen) {
  using namespace analyze_format_string;

  // See if we know how to fix this conversion specifier.
  std::optional<ConversionSpecifier> FixedCS = CS.getStandardSpecifier();
  if (FixedCS) {
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard)
                          << CS.toString() << /*conversion specifier*/1,
                         getLocationOfByte(CS.getStart()),
                         /*IsStringLocation*/true,
                         getSpecifierRange(startSpecifier, specifierLen));

    CharSourceRange CSRange = getSpecifierRange(CS.getStart(), CS.getLength());
    S.Diag(getLocationOfByte(CS.getStart()), diag::note_format_fix_specifier)
      << FixedCS->toString()
      << FixItHint::CreateReplacement(CSRange, FixedCS->toString());
  } else {
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard)
                          << CS.toString() << /*conversion specifier*/1,
                         getLocationOfByte(CS.getStart()),
                         /*IsStringLocation*/true,
                         getSpecifierRange(startSpecifier, specifierLen));
  }
}

void CheckFormatHandler::HandlePosition(const char *startPos,
                                        unsigned posLen) {
  if (!S.getDiagnostics().isIgnored(
          diag::warn_format_non_standard_positional_arg, SourceLocation()))
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_positional_arg),
                         getLocationOfByte(startPos),
                         /*IsStringLocation*/ true,
                         getSpecifierRange(startPos, posLen));
}

void CheckFormatHandler::HandleInvalidPosition(
    const char *startSpecifier, unsigned specifierLen,
    analyze_format_string::PositionContext p) {
  if (!S.getDiagnostics().isIgnored(
          diag::warn_format_invalid_positional_specifier, SourceLocation()))
    EmitFormatDiagnostic(
        S.PDiag(diag::warn_format_invalid_positional_specifier) << (unsigned)p,
        getLocationOfByte(startSpecifier), /*IsStringLocation*/ true,
        getSpecifierRange(startSpecifier, specifierLen));
}

void CheckFormatHandler::HandleZeroPosition(const char *startPos,
                                            unsigned posLen) {
  if (!S.getDiagnostics().isIgnored(diag::warn_format_zero_positional_specifier,
                                    SourceLocation()))
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_zero_positional_specifier),
                         getLocationOfByte(startPos),
                         /*IsStringLocation*/ true,
                         getSpecifierRange(startPos, posLen));
}

void CheckFormatHandler::HandleNullChar(const char *nullCharacter) {
  if (!isa<ObjCStringLiteral>(OrigFormatExpr)) {
    // The presence of a null character is likely an error.
    EmitFormatDiagnostic(
      S.PDiag(diag::warn_printf_format_string_contains_null_char),
      getLocationOfByte(nullCharacter), /*IsStringLocation*/true,
      getFormatStringRange());
  }
}

// Note that this may return NULL if there was an error parsing or building
// one of the argument expressions.
const Expr *CheckFormatHandler::getDataArg(unsigned i) const {
  return Args[FirstDataArg + i];
}

void CheckFormatHandler::DoneProcessing() {
  // Does the number of data arguments exceed the number of
  // format conversions in the format string?
  if (HasFormatArguments()) {
    // Find any arguments that weren't covered.
    CoveredArgs.flip();
    signed notCoveredArg = CoveredArgs.find_first();
    if (notCoveredArg >= 0) {
      assert((unsigned)notCoveredArg < NumDataArgs);
      UncoveredArg.Update(notCoveredArg, OrigFormatExpr);
    } else {
      UncoveredArg.setAllCovered();
    }
  }
}

void UncoveredArgHandler::Diagnose(Sema &S, bool IsFunctionCall,
                                   const Expr *ArgExpr) {
  assert(hasUncoveredArg() && !DiagnosticExprs.empty() &&
         "Invalid state");

  if (!ArgExpr)
    return;

  SourceLocation Loc = ArgExpr->getBeginLoc();

  if (S.getSourceManager().isInSystemMacro(Loc))
    return;

  PartialDiagnostic PDiag = S.PDiag(diag::warn_printf_data_arg_not_used);
  for (auto E : DiagnosticExprs)
    PDiag << E->getSourceRange();

  CheckFormatHandler::EmitFormatDiagnostic(
                                  S, IsFunctionCall, DiagnosticExprs[0],
                                  PDiag, Loc, /*IsStringLocation*/false,
                                  DiagnosticExprs[0]->getSourceRange());
}

bool
CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex,
                                                     SourceLocation Loc,
                                                     const char *startSpec,
                                                     unsigned specifierLen,
                                                     const char *csStart,
                                                     unsigned csLen) {
  bool keepGoing = true;
  if (argIndex < NumDataArgs) {
    // Consider the argument coverered, even though the specifier doesn't
    // make sense.
    CoveredArgs.set(argIndex);
  }
  else {
    // If argIndex exceeds the number of data arguments we
    // don't issue a warning because that is just a cascade of warnings (and
    // they may have intended '%%' anyway). We don't want to continue processing
    // the format string after this point, however, as we will like just get
    // gibberish when trying to match arguments.
    keepGoing = false;
  }

  StringRef Specifier(csStart, csLen);

  // If the specifier in non-printable, it could be the first byte of a UTF-8
  // sequence. In that case, print the UTF-8 code point. If not, print the byte
  // hex value.
  std::string CodePointStr;
  if (!llvm::sys::locale::isPrint(*csStart)) {
    llvm::UTF32 CodePoint;
    const llvm::UTF8 **B = reinterpret_cast<const llvm::UTF8 **>(&csStart);
    const llvm::UTF8 *E =
        reinterpret_cast<const llvm::UTF8 *>(csStart + csLen);
    llvm::ConversionResult Result =
        llvm::convertUTF8Sequence(B, E, &CodePoint, llvm::strictConversion);

    if (Result != llvm::conversionOK) {
      unsigned char FirstChar = *csStart;
      CodePoint = (llvm::UTF32)FirstChar;
    }

    llvm::raw_string_ostream OS(CodePointStr);
    if (CodePoint < 256)
      OS << "\\x" << llvm::format("%02x", CodePoint);
    else if (CodePoint <= 0xFFFF)
      OS << "\\u" << llvm::format("%04x", CodePoint);
    else
      OS << "\\U" << llvm::format("%08x", CodePoint);
    Specifier = CodePointStr;
  }

  EmitFormatDiagnostic(
      S.PDiag(diag::warn_format_invalid_conversion) << Specifier, Loc,
      /*IsStringLocation*/ true, getSpecifierRange(startSpec, specifierLen));

  return keepGoing;
}

void
CheckFormatHandler::HandlePositionalNonpositionalArgs(SourceLocation Loc,
                                                      const char *startSpec,
                                                      unsigned specifierLen) {
  EmitFormatDiagnostic(
    S.PDiag(diag::warn_format_mix_positional_nonpositional_args),
    Loc, /*isStringLoc*/true, getSpecifierRange(startSpec, specifierLen));
}

bool
CheckFormatHandler::CheckNumArgs(
  const analyze_format_string::FormatSpecifier &FS,
  const analyze_format_string::ConversionSpecifier &CS,
  const char *startSpecifier, unsigned specifierLen, unsigned argIndex) {

  if (HasFormatArguments() && argIndex >= NumDataArgs) {
    PartialDiagnostic PDiag = FS.usesPositionalArg()
      ? (S.PDiag(diag::warn_printf_positional_arg_exceeds_data_args)
           << (argIndex+1) << NumDataArgs)
      : S.PDiag(diag::warn_printf_insufficient_data_args);
    EmitFormatDiagnostic(
      PDiag, getLocationOfByte(CS.getStart()), /*IsStringLocation*/true,
      getSpecifierRange(startSpecifier, specifierLen));

    // Since more arguments than conversion tokens are given, by extension
    // all arguments are covered, so mark this as so.
    UncoveredArg.setAllCovered();
    return false;
  }
  return true;
}

template<typename Range>
void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag,
                                              SourceLocation Loc,
                                              bool IsStringLocation,
                                              Range StringRange,
                                              ArrayRef<FixItHint> FixIt) {
  EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag,
                       Loc, IsStringLocation, StringRange, FixIt);
}

/// If the format string is not within the function call, emit a note
/// so that the function call and string are in diagnostic messages.
///
/// \param InFunctionCall if true, the format string is within the function
/// call and only one diagnostic message will be produced.  Otherwise, an
/// extra note will be emitted pointing to location of the format string.
///
/// \param ArgumentExpr the expression that is passed as the format string
/// argument in the function call.  Used for getting locations when two
/// diagnostics are emitted.
///
/// \param PDiag the callee should already have provided any strings for the
/// diagnostic message.  This function only adds locations and fixits
/// to diagnostics.
///
/// \param Loc primary location for diagnostic.  If two diagnostics are
/// required, one will be at Loc and a new SourceLocation will be created for
/// the other one.
///
/// \param IsStringLocation if true, Loc points to the format string should be
/// used for the note.  Otherwise, Loc points to the argument list and will
/// be used with PDiag.
///
/// \param StringRange some or all of the string to highlight.  This is
/// templated so it can accept either a CharSourceRange or a SourceRange.
///
/// \param FixIt optional fix it hint for the format string.
template <typename Range>
void CheckFormatHandler::EmitFormatDiagnostic(
    Sema &S, bool InFunctionCall, const Expr *ArgumentExpr,
    const PartialDiagnostic &PDiag, SourceLocation Loc, bool IsStringLocation,
    Range StringRange, ArrayRef<FixItHint> FixIt) {
  if (InFunctionCall) {
    const Sema::SemaDiagnosticBuilder &D = S.Diag(Loc, PDiag);
    D << StringRange;
    D << FixIt;
  } else {
    S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag)
      << ArgumentExpr->getSourceRange();

    const Sema::SemaDiagnosticBuilder &Note =
      S.Diag(IsStringLocation ? Loc : StringRange.getBegin(),
             diag::note_format_string_defined);

    Note << StringRange;
    Note << FixIt;
  }
}

//===--- CHECK: Printf format string checking -----------------------------===//

namespace {

class CheckPrintfHandler : public CheckFormatHandler {
public:
  CheckPrintfHandler(Sema &s, const FormatStringLiteral *fexpr,
                     const Expr *origFormatExpr, const FormatStringType type,
                     unsigned firstDataArg, unsigned numDataArgs, bool isObjC,
                     const char *beg, Sema::FormatArgumentPassingKind APK,
                     ArrayRef<const Expr *> Args, unsigned formatIdx,
                     bool inFunctionCall, VariadicCallType CallType,
                     llvm::SmallBitVector &CheckedVarArgs,
                     UncoveredArgHandler &UncoveredArg)
      : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg,
                           numDataArgs, beg, APK, Args, formatIdx,
                           inFunctionCall, CallType, CheckedVarArgs,
                           UncoveredArg) {}

  bool isObjCContext() const { return FSType == FormatStringType::NSString; }

  /// Returns true if '%@' specifiers are allowed in the format string.
  bool allowsObjCArg() const {
    return FSType == FormatStringType::NSString ||
           FSType == FormatStringType::OSLog ||
           FSType == FormatStringType::OSTrace;
  }

  bool HandleInvalidPrintfConversionSpecifier(
                                      const analyze_printf::PrintfSpecifier &FS,
                                      const char *startSpecifier,
                                      unsigned specifierLen) override;

  void handleInvalidMaskType(StringRef MaskType) override;

  bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
                             const char *startSpecifier, unsigned specifierLen,
                             const TargetInfo &Target) override;
  bool checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
                       const char *StartSpecifier,
                       unsigned SpecifierLen,
                       const Expr *E);

  bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k,
                    const char *startSpecifier, unsigned specifierLen);
  void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS,
                           const analyze_printf::OptionalAmount &Amt,
                           unsigned type,
                           const char *startSpecifier, unsigned specifierLen);
  void HandleFlag(const analyze_printf::PrintfSpecifier &FS,
                  const analyze_printf::OptionalFlag &flag,
                  const char *startSpecifier, unsigned specifierLen);
  void HandleIgnoredFlag(const analyze_printf::PrintfSpecifier &FS,
                         const analyze_printf::OptionalFlag &ignoredFlag,
                         const analyze_printf::OptionalFlag &flag,
                         const char *startSpecifier, unsigned specifierLen);
  bool checkForCStrMembers(const analyze_printf::ArgType &AT,
                           const Expr *E);

  void HandleEmptyObjCModifierFlag(const char *startFlag,
                                   unsigned flagLen) override;

  void HandleInvalidObjCModifierFlag(const char *startFlag,
                                            unsigned flagLen) override;

  void
  HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
                                       const char *flagsEnd,
                                       const char *conversionPosition) override;
};

/// Keeps around the information needed to verify that two specifiers are
/// compatible.
class EquatableFormatArgument {
public:
  enum SpecifierSensitivity : unsigned {
    SS_None,
    SS_Private,
    SS_Public,
    SS_Sensitive
  };

  enum FormatArgumentRole : unsigned {
    FAR_Data,
    FAR_FieldWidth,
    FAR_Precision,
    FAR_Auxiliary, // FreeBSD kernel %b and %D
  };

private:
  analyze_format_string::ArgType ArgType;
  analyze_format_string::LengthModifier::Kind LengthMod;
  StringRef SpecifierLetter;
  CharSourceRange Range;
  SourceLocation ElementLoc;
  FormatArgumentRole Role : 2;
  SpecifierSensitivity Sensitivity : 2; // only set for FAR_Data
  unsigned Position : 14;
  unsigned ModifierFor : 14; // not set for FAR_Data

  void EmitDiagnostic(Sema &S, PartialDiagnostic PDiag, const Expr *FmtExpr,
                      bool InFunctionCall) const;

public:
  EquatableFormatArgument(CharSourceRange Range, SourceLocation ElementLoc,
                          analyze_format_string::LengthModifier::Kind LengthMod,
                          StringRef SpecifierLetter,
                          analyze_format_string::ArgType ArgType,
                          FormatArgumentRole Role,
                          SpecifierSensitivity Sensitivity, unsigned Position,
                          unsigned ModifierFor)
      : ArgType(ArgType), LengthMod(LengthMod),
        SpecifierLetter(SpecifierLetter), Range(Range), ElementLoc(ElementLoc),
        Role(Role), Sensitivity(Sensitivity), Position(Position),
        ModifierFor(ModifierFor) {}

  unsigned getPosition() const { return Position; }
  SourceLocation getSourceLocation() const { return ElementLoc; }
  CharSourceRange getSourceRange() const { return Range; }
  analyze_format_string::LengthModifier getLengthModifier() const {
    return analyze_format_string::LengthModifier(nullptr, LengthMod);
  }
  void setModifierFor(unsigned V) { ModifierFor = V; }

  std::string buildFormatSpecifier() const {
    std::string result;
    llvm::raw_string_ostream(result)
        << getLengthModifier().toString() << SpecifierLetter;
    return result;
  }

  bool VerifyCompatible(Sema &S, const EquatableFormatArgument &Other,
                        const Expr *FmtExpr, bool InFunctionCall) const;
};

/// Turns format strings into lists of EquatableSpecifier objects.
class DecomposePrintfHandler : public CheckPrintfHandler {
  llvm::SmallVectorImpl<EquatableFormatArgument> &Specs;
  bool HadError;

  DecomposePrintfHandler(Sema &s, const FormatStringLiteral *fexpr,
                         const Expr *origFormatExpr,
                         const FormatStringType type, unsigned firstDataArg,
                         unsigned numDataArgs, bool isObjC, const char *beg,
                         Sema::FormatArgumentPassingKind APK,
                         ArrayRef<const Expr *> Args, unsigned formatIdx,
                         bool inFunctionCall, VariadicCallType CallType,
                         llvm::SmallBitVector &CheckedVarArgs,
                         UncoveredArgHandler &UncoveredArg,
                         llvm::SmallVectorImpl<EquatableFormatArgument> &Specs)
      : CheckPrintfHandler(s, fexpr, origFormatExpr, type, firstDataArg,
                           numDataArgs, isObjC, beg, APK, Args, formatIdx,
                           inFunctionCall, CallType, CheckedVarArgs,
                           UncoveredArg),
        Specs(Specs), HadError(false) {}

public:
  static bool
  GetSpecifiers(Sema &S, const FormatStringLiteral *FSL, const Expr *FmtExpr,
                FormatStringType type, bool IsObjC, bool InFunctionCall,
                llvm::SmallVectorImpl<EquatableFormatArgument> &Args);

  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
                                     const char *startSpecifier,
                                     unsigned specifierLen,
                                     const TargetInfo &Target) override;
};

} // namespace

bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier(
    const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier,
    unsigned specifierLen) {
  const analyze_printf::PrintfConversionSpecifier &CS =
    FS.getConversionSpecifier();

  return HandleInvalidConversionSpecifier(FS.getArgIndex(),
                                          getLocationOfByte(CS.getStart()),
                                          startSpecifier, specifierLen,
                                          CS.getStart(), CS.getLength());
}

void CheckPrintfHandler::handleInvalidMaskType(StringRef MaskType) {
  S.Diag(getLocationOfByte(MaskType.data()), diag::err_invalid_mask_type_size);
}

bool CheckPrintfHandler::HandleAmount(
    const analyze_format_string::OptionalAmount &Amt, unsigned k,
    const char *startSpecifier, unsigned specifierLen) {
  if (Amt.hasDataArgument()) {
    if (HasFormatArguments()) {
      unsigned argIndex = Amt.getArgIndex();
      if (argIndex >= NumDataArgs) {
        EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_missing_arg)
                                 << k,
                             getLocationOfByte(Amt.getStart()),
                             /*IsStringLocation*/ true,
                             getSpecifierRange(startSpecifier, specifierLen));
        // Don't do any more checking.  We will just emit
        // spurious errors.
        return false;
      }

      // Type check the data argument.  It should be an 'int'.
      // Although not in conformance with C99, we also allow the argument to be
      // an 'unsigned int' as that is a reasonably safe case.  GCC also
      // doesn't emit a warning for that case.
      CoveredArgs.set(argIndex);
      const Expr *Arg = getDataArg(argIndex);
      if (!Arg)
        return false;

      QualType T = Arg->getType();

      const analyze_printf::ArgType &AT = Amt.getArgType(S.Context);
      assert(AT.isValid());

      if (!AT.matchesType(S.Context, T)) {
        EmitFormatDiagnostic(S.PDiag(diag::warn_printf_asterisk_wrong_type)
                               << k << AT.getRepresentativeTypeName(S.Context)
                               << T << Arg->getSourceRange(),
                             getLocationOfByte(Amt.getStart()),
                             /*IsStringLocation*/true,
                             getSpecifierRange(startSpecifier, specifierLen));
        // Don't do any more checking.  We will just emit
        // spurious errors.
        return false;
      }
    }
  }
  return true;
}

void CheckPrintfHandler::HandleInvalidAmount(
                                      const analyze_printf::PrintfSpecifier &FS,
                                      const analyze_printf::OptionalAmount &Amt,
                                      unsigned type,
                                      const char *startSpecifier,
                                      unsigned specifierLen) {
  const analyze_printf::PrintfConversionSpecifier &CS =
    FS.getConversionSpecifier();

  FixItHint fixit =
    Amt.getHowSpecified() == analyze_printf::OptionalAmount::Constant
      ? FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(),
                                 Amt.getConstantLength()))
      : FixItHint();

  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_optional_amount)
                         << type << CS.toString(),
                       getLocationOfByte(Amt.getStart()),
                       /*IsStringLocation*/true,
                       getSpecifierRange(startSpecifier, specifierLen),
                       fixit);
}

void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS,
                                    const analyze_printf::OptionalFlag &flag,
                                    const char *startSpecifier,
                                    unsigned specifierLen) {
  // Warn about pointless flag with a fixit removal.
  const analyze_printf::PrintfConversionSpecifier &CS =
    FS.getConversionSpecifier();
  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_nonsensical_flag)
                         << flag.toString() << CS.toString(),
                       getLocationOfByte(flag.getPosition()),
                       /*IsStringLocation*/true,
                       getSpecifierRange(startSpecifier, specifierLen),
                       FixItHint::CreateRemoval(
                         getSpecifierRange(flag.getPosition(), 1)));
}

void CheckPrintfHandler::HandleIgnoredFlag(
                                const analyze_printf::PrintfSpecifier &FS,
                                const analyze_printf::OptionalFlag &ignoredFlag,
                                const analyze_printf::OptionalFlag &flag,
                                const char *startSpecifier,
                                unsigned specifierLen) {
  // Warn about ignored flag with a fixit removal.
  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_ignored_flag)
                         << ignoredFlag.toString() << flag.toString(),
                       getLocationOfByte(ignoredFlag.getPosition()),
                       /*IsStringLocation*/true,
                       getSpecifierRange(startSpecifier, specifierLen),
                       FixItHint::CreateRemoval(
                         getSpecifierRange(ignoredFlag.getPosition(), 1)));
}

void CheckPrintfHandler::HandleEmptyObjCModifierFlag(const char *startFlag,
                                                     unsigned flagLen) {
  // Warn about an empty flag.
  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_empty_objc_flag),
                       getLocationOfByte(startFlag),
                       /*IsStringLocation*/true,
                       getSpecifierRange(startFlag, flagLen));
}

void CheckPrintfHandler::HandleInvalidObjCModifierFlag(const char *startFlag,
                                                       unsigned flagLen) {
  // Warn about an invalid flag.
  auto Range = getSpecifierRange(startFlag, flagLen);
  StringRef flag(startFlag, flagLen);
  EmitFormatDiagnostic(S.PDiag(diag::warn_printf_invalid_objc_flag) << flag,
                      getLocationOfByte(startFlag),
                      /*IsStringLocation*/true,
                      Range, FixItHint::CreateRemoval(Range));
}

void CheckPrintfHandler::HandleObjCFlagsWithNonObjCConversion(
    const char *flagsStart, const char *flagsEnd, const char *conversionPosition) {
    // Warn about using '[...]' without a '@' conversion.
    auto Range = getSpecifierRange(flagsStart, flagsEnd - flagsStart + 1);
    auto diag = diag::warn_printf_ObjCflags_without_ObjCConversion;
    EmitFormatDiagnostic(S.PDiag(diag) << StringRef(conversionPosition, 1),
                         getLocationOfByte(conversionPosition),
                         /*IsStringLocation*/ true, Range,
                         FixItHint::CreateRemoval(Range));
}

void EquatableFormatArgument::EmitDiagnostic(Sema &S, PartialDiagnostic PDiag,
                                             const Expr *FmtExpr,
                                             bool InFunctionCall) const {
  CheckFormatHandler::EmitFormatDiagnostic(S, InFunctionCall, FmtExpr, PDiag,
                                           ElementLoc, true, Range);
}

bool EquatableFormatArgument::VerifyCompatible(
    Sema &S, const EquatableFormatArgument &Other, const Expr *FmtExpr,
    bool InFunctionCall) const {
  using MK = analyze_format_string::ArgType::MatchKind;
  if (Role != Other.Role) {
    // diagnose and stop
    EmitDiagnostic(
        S, S.PDiag(diag::warn_format_cmp_role_mismatch) << Role << Other.Role,
        FmtExpr, InFunctionCall);
    S.Diag(Other.ElementLoc, diag::note_format_cmp_with) << 0 << Other.Range;
    return false;
  }

  if (Role != FAR_Data) {
    if (ModifierFor != Other.ModifierFor) {
      // diagnose and stop
      EmitDiagnostic(S,
                     S.PDiag(diag::warn_format_cmp_modifierfor_mismatch)
                         << (ModifierFor + 1) << (Other.ModifierFor + 1),
                     FmtExpr, InFunctionCall);
      S.Diag(Other.ElementLoc, diag::note_format_cmp_with) << 0 << Other.Range;
      return false;
    }
    return true;
  }

  bool HadError = false;
  if (Sensitivity != Other.Sensitivity) {
    // diagnose and continue
    EmitDiagnostic(S,
                   S.PDiag(diag::warn_format_cmp_sensitivity_mismatch)
                       << Sensitivity << Other.Sensitivity,
                   FmtExpr, InFunctionCall);
    HadError = S.Diag(Other.ElementLoc, diag::note_format_cmp_with)
               << 0 << Other.Range;
  }

  switch (ArgType.matchesArgType(S.Context, Other.ArgType)) {
  case MK::Match:
    break;

  case MK::MatchPromotion:
    // Per consensus reached at https://discourse.llvm.org/t/-/83076/12,
    // MatchPromotion is treated as a failure by format_matches.
  case MK::NoMatch:
  case MK::NoMatchTypeConfusion:
  case MK::NoMatchPromotionTypeConfusion:
    EmitDiagnostic(S,
                   S.PDiag(diag::warn_format_cmp_specifier_mismatch)
                       << buildFormatSpecifier()
                       << Other.buildFormatSpecifier(),
                   FmtExpr, InFunctionCall);
    HadError = S.Diag(Other.ElementLoc, diag::note_format_cmp_with)
               << 0 << Other.Range;
    break;

  case MK::NoMatchPedantic:
    EmitDiagnostic(S,
                   S.PDiag(diag::warn_format_cmp_specifier_mismatch_pedantic)
                       << buildFormatSpecifier()
                       << Other.buildFormatSpecifier(),
                   FmtExpr, InFunctionCall);
    HadError = S.Diag(Other.ElementLoc, diag::note_format_cmp_with)
               << 0 << Other.Range;
    break;

  case MK::NoMatchSignedness:
    if (!S.getDiagnostics().isIgnored(
            diag::warn_format_conversion_argument_type_mismatch_signedness,
            ElementLoc)) {
      EmitDiagnostic(S,
                     S.PDiag(diag::warn_format_cmp_specifier_sign_mismatch)
                         << buildFormatSpecifier()
                         << Other.buildFormatSpecifier(),
                     FmtExpr, InFunctionCall);
      HadError = S.Diag(Other.ElementLoc, diag::note_format_cmp_with)
                 << 0 << Other.Range;
    }
    break;
  }
  return !HadError;
}

bool DecomposePrintfHandler::GetSpecifiers(
    Sema &S, const FormatStringLiteral *FSL, const Expr *FmtExpr,
    FormatStringType Type, bool IsObjC, bool InFunctionCall,
    llvm::SmallVectorImpl<EquatableFormatArgument> &Args) {
  StringRef Data = FSL->getString();
  const char *Str = Data.data();
  llvm::SmallBitVector BV;
  UncoveredArgHandler UA;
  const Expr *PrintfArgs[] = {FSL->getFormatString()};
  DecomposePrintfHandler H(S, FSL, FSL->getFormatString(), Type, 0, 0, IsObjC,
                           Str, Sema::FAPK_Elsewhere, PrintfArgs, 0,
                           InFunctionCall, VariadicCallType::DoesNotApply, BV,
                           UA, Args);

  if (!analyze_format_string::ParsePrintfString(
          H, Str, Str + Data.size(), S.getLangOpts(), S.Context.getTargetInfo(),
          Type == FormatStringType::FreeBSDKPrintf))
    H.DoneProcessing();
  if (H.HadError)
    return false;

  llvm::stable_sort(Args, [](const EquatableFormatArgument &A,
                             const EquatableFormatArgument &B) {
    return A.getPosition() < B.getPosition();
  });
  return true;
}

bool DecomposePrintfHandler::HandlePrintfSpecifier(
    const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier,
    unsigned specifierLen, const TargetInfo &Target) {
  if (!CheckPrintfHandler::HandlePrintfSpecifier(FS, startSpecifier,
                                                 specifierLen, Target)) {
    HadError = true;
    return false;
  }

  // Do not add any specifiers to the list for %%. This is possibly incorrect
  // if using a precision/width with a data argument, but that combination is
  // meaningless and we wouldn't know which format to attach the
  // precision/width to.
  const auto &CS = FS.getConversionSpecifier();
  if (CS.getKind() == analyze_format_string::ConversionSpecifier::PercentArg)
    return true;

  // have to patch these to have the right ModifierFor if they are used
  const unsigned Unset = ~0;
  unsigned FieldWidthIndex = Unset;
  unsigned PrecisionIndex = Unset;

  // field width?
  const auto &FieldWidth = FS.getFieldWidth();
  if (!FieldWidth.isInvalid() && FieldWidth.hasDataArgument()) {
    FieldWidthIndex = Specs.size();
    Specs.emplace_back(getSpecifierRange(startSpecifier, specifierLen),
                       getLocationOfByte(FieldWidth.getStart()),
                       analyze_format_string::LengthModifier::None, "*",
                       FieldWidth.getArgType(S.Context),
                       EquatableFormatArgument::FAR_FieldWidth,
                       EquatableFormatArgument::SS_None,
                       FieldWidth.usesPositionalArg()
                           ? FieldWidth.getPositionalArgIndex() - 1
                           : FieldWidthIndex,
                       0);
  }
  // precision?
  const auto &Precision = FS.getPrecision();
  if (!Precision.isInvalid() && Precision.hasDataArgument()) {
    PrecisionIndex = Specs.size();
    Specs.emplace_back(
        getSpecifierRange(startSpecifier, specifierLen),
        getLocationOfByte(Precision.getStart()),
        analyze_format_string::LengthModifier::None, ".*",
        Precision.getArgType(S.Context), EquatableFormatArgument::FAR_Precision,
        EquatableFormatArgument::SS_None,
        Precision.usesPositionalArg() ? Precision.getPositionalArgIndex() - 1
                                      : PrecisionIndex,
        0);
  }

  // this specifier
  unsigned SpecIndex =
      FS.usesPositionalArg() ? FS.getPositionalArgIndex() - 1 : Specs.size();
  if (FieldWidthIndex != Unset)
    Specs[FieldWidthIndex].setModifierFor(SpecIndex);
  if (PrecisionIndex != Unset)
    Specs[PrecisionIndex].setModifierFor(SpecIndex);

  EquatableFormatArgument::SpecifierSensitivity Sensitivity;
  if (FS.isPrivate())
    Sensitivity = EquatableFormatArgument::SS_Private;
  else if (FS.isPublic())
    Sensitivity = EquatableFormatArgument::SS_Public;
  else if (FS.isSensitive())
    Sensitivity = EquatableFormatArgument::SS_Sensitive;
  else
    Sensitivity = EquatableFormatArgument::SS_None;

  Specs.emplace_back(
      getSpecifierRange(startSpecifier, specifierLen),
      getLocationOfByte(CS.getStart()), FS.getLengthModifier().getKind(),
      CS.getCharacters(), FS.getArgType(S.Context, isObjCContext()),
      EquatableFormatArgument::FAR_Data, Sensitivity, SpecIndex, 0);

  // auxiliary argument?
  if (CS.getKind() == analyze_format_string::ConversionSpecifier::FreeBSDbArg ||
      CS.getKind() == analyze_format_string::ConversionSpecifier::FreeBSDDArg) {
    Specs.emplace_back(getSpecifierRange(startSpecifier, specifierLen),
                       getLocationOfByte(CS.getStart()),
                       analyze_format_string::LengthModifier::None,
                       CS.getCharacters(),
                       analyze_format_string::ArgType::CStrTy,
                       EquatableFormatArgument::FAR_Auxiliary, Sensitivity,
                       SpecIndex + 1, SpecIndex);
  }
  return true;
}

// Determines if the specified is a C++ class or struct containing
// a member with the specified name and kind (e.g. a CXXMethodDecl named
// "c_str()").
template<typename MemberKind>
static llvm::SmallPtrSet<MemberKind*, 1>
CXXRecordMembersNamed(StringRef Name, Sema &S, QualType Ty) {
  const RecordType *RT = Ty->getAs<RecordType>();
  llvm::SmallPtrSet<MemberKind*, 1> Results;

  if (!RT)
    return Results;
  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
  if (!RD || !RD->getDefinition())
    return Results;

  LookupResult R(S, &S.Context.Idents.get(Name), SourceLocation(),
                 Sema::LookupMemberName);
  R.suppressDiagnostics();

  // We just need to include all members of the right kind turned up by the
  // filter, at this point.
  if (S.LookupQualifiedName(R, RT->getDecl()))
    for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
      NamedDecl *decl = (*I)->getUnderlyingDecl();
      if (MemberKind *FK = dyn_cast<MemberKind>(decl))
        Results.insert(FK);
    }
  return Results;
}

/// Check if we could call '.c_str()' on an object.
///
/// FIXME: This returns the wrong results in some cases (if cv-qualifiers don't
/// allow the call, or if it would be ambiguous).
bool Sema::hasCStrMethod(const Expr *E) {
  using MethodSet = llvm::SmallPtrSet<CXXMethodDecl *, 1>;

  MethodSet Results =
      CXXRecordMembersNamed<CXXMethodDecl>("c_str", *this, E->getType());
  for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
       MI != ME; ++MI)
    if ((*MI)->getMinRequiredArguments() == 0)
      return true;
  return false;
}

// Check if a (w)string was passed when a (w)char* was needed, and offer a
// better diagnostic if so. AT is assumed to be valid.
// Returns true when a c_str() conversion method is found.
bool CheckPrintfHandler::checkForCStrMembers(
    const analyze_printf::ArgType &AT, const Expr *E) {
  using MethodSet = llvm::SmallPtrSet<CXXMethodDecl *, 1>;

  MethodSet Results =
      CXXRecordMembersNamed<CXXMethodDecl>("c_str", S, E->getType());

  for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
       MI != ME; ++MI) {
    const CXXMethodDecl *Method = *MI;
    if (Method->getMinRequiredArguments() == 0 &&
        AT.matchesType(S.Context, Method->getReturnType())) {
      // FIXME: Suggest parens if the expression needs them.
      SourceLocation EndLoc = S.getLocForEndOfToken(E->getEndLoc());
      S.Diag(E->getBeginLoc(), diag::note_printf_c_str)
          << "c_str()" << FixItHint::CreateInsertion(EndLoc, ".c_str()");
      return true;
    }
  }

  return false;
}

bool CheckPrintfHandler::HandlePrintfSpecifier(
    const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier,
    unsigned specifierLen, const TargetInfo &Target) {
  using namespace analyze_format_string;
  using namespace analyze_printf;

  const PrintfConversionSpecifier &CS = FS.getConversionSpecifier();

  if (FS.consumesDataArgument()) {
    if (atFirstArg) {
        atFirstArg = false;
        usesPositionalArgs = FS.usesPositionalArg();
    }
    else if (usesPositionalArgs != FS.usesPositionalArg()) {
      HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()),
                                        startSpecifier, specifierLen);
      return false;
    }
  }

  // First check if the field width, precision, and conversion specifier
  // have matching data arguments.
  if (!HandleAmount(FS.getFieldWidth(), /* field width */ 0,
                    startSpecifier, specifierLen)) {
    return false;
  }

  if (!HandleAmount(FS.getPrecision(), /* precision */ 1,
                    startSpecifier, specifierLen)) {
    return false;
  }

  if (!CS.consumesDataArgument()) {
    // FIXME: Technically specifying a precision or field width here
    // makes no sense.  Worth issuing a warning at some point.
    return true;
  }

  // Consume the argument.
  unsigned argIndex = FS.getArgIndex();
  if (argIndex < NumDataArgs) {
    // The check to see if the argIndex is valid will come later.
    // We set the bit here because we may exit early from this
    // function if we encounter some other error.
    CoveredArgs.set(argIndex);
  }

  // FreeBSD kernel extensions.
  if (CS.getKind() == ConversionSpecifier::FreeBSDbArg ||
      CS.getKind() == ConversionSpecifier::FreeBSDDArg) {
    // We need at least two arguments.
    if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex + 1))
      return false;

    if (HasFormatArguments()) {
      // Claim the second argument.
      CoveredArgs.set(argIndex + 1);

      // Type check the first argument (int for %b, pointer for %D)
      const Expr *Ex = getDataArg(argIndex);
      const analyze_printf::ArgType &AT =
          (CS.getKind() == ConversionSpecifier::FreeBSDbArg)
              ? ArgType(S.Context.IntTy)
              : ArgType::CPointerTy;
      if (AT.isValid() && !AT.matchesType(S.Context, Ex->getType()))
        EmitFormatDiagnostic(
            S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
                << AT.getRepresentativeTypeName(S.Context) << Ex->getType()
                << false << Ex->getSourceRange(),
            Ex->getBeginLoc(), /*IsStringLocation*/ false,
            getSpecifierRange(startSpecifier, specifierLen));

      // Type check the second argument (char * for both %b and %D)
      Ex = getDataArg(argIndex + 1);
      const analyze_printf::ArgType &AT2 = ArgType::CStrTy;
      if (AT2.isValid() && !AT2.matchesType(S.Context, Ex->getType()))
        EmitFormatDiagnostic(
            S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
                << AT2.getRepresentativeTypeName(S.Context) << Ex->getType()
                << false << Ex->getSourceRange(),
            Ex->getBeginLoc(), /*IsStringLocation*/ false,
            getSpecifierRange(startSpecifier, specifierLen));
    }
    return true;
  }

  // Check for using an Objective-C specific conversion specifier
  // in a non-ObjC literal.
  if (!allowsObjCArg() && CS.isObjCArg()) {
    return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
                                                  specifierLen);
  }

  // %P can only be used with os_log.
  if (FSType != FormatStringType::OSLog &&
      CS.getKind() == ConversionSpecifier::PArg) {
    return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
                                                  specifierLen);
  }

  // %n is not allowed with os_log.
  if (FSType == FormatStringType::OSLog &&
      CS.getKind() == ConversionSpecifier::nArg) {
    EmitFormatDiagnostic(S.PDiag(diag::warn_os_log_format_narg),
                         getLocationOfByte(CS.getStart()),
                         /*IsStringLocation*/ false,
                         getSpecifierRange(startSpecifier, specifierLen));

    return true;
  }

  // Only scalars are allowed for os_trace.
  if (FSType == FormatStringType::OSTrace &&
      (CS.getKind() == ConversionSpecifier::PArg ||
       CS.getKind() == ConversionSpecifier::sArg ||
       CS.getKind() == ConversionSpecifier::ObjCObjArg)) {
    return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier,
                                                  specifierLen);
  }

  // Check for use of public/private annotation outside of os_log().
  if (FSType != FormatStringType::OSLog) {
    if (FS.isPublic().isSet()) {
      EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation)
                               << "public",
                           getLocationOfByte(FS.isPublic().getPosition()),
                           /*IsStringLocation*/ false,
                           getSpecifierRange(startSpecifier, specifierLen));
    }
    if (FS.isPrivate().isSet()) {
      EmitFormatDiagnostic(S.PDiag(diag::warn_format_invalid_annotation)
                               << "private",
                           getLocationOfByte(FS.isPrivate().getPosition()),
                           /*IsStringLocation*/ false,
                           getSpecifierRange(startSpecifier, specifierLen));
    }
  }

  const llvm::Triple &Triple = Target.getTriple();
  if (CS.getKind() == ConversionSpecifier::nArg &&
      (Triple.isAndroid() || Triple.isOSFuchsia())) {
    EmitFormatDiagnostic(S.PDiag(diag::warn_printf_narg_not_supported),
                         getLocationOfByte(CS.getStart()),
                         /*IsStringLocation*/ false,
                         getSpecifierRange(startSpecifier, specifierLen));
  }

  // Check for invalid use of field width
  if (!FS.hasValidFieldWidth()) {
    HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0,
        startSpecifier, specifierLen);
  }

  // Check for invalid use of precision
  if (!FS.hasValidPrecision()) {
    HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1,
        startSpecifier, specifierLen);
  }

  // Precision is mandatory for %P specifier.
  if (CS.getKind() == ConversionSpecifier::PArg &&
      FS.getPrecision().getHowSpecified() == OptionalAmount::NotSpecified) {
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_P_no_precision),
                         getLocationOfByte(startSpecifier),
                         /*IsStringLocation*/ false,
                         getSpecifierRange(startSpecifier, specifierLen));
  }

  // Check each flag does not conflict with any other component.
  if (!FS.hasValidThousandsGroupingPrefix())
    HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen);
  if (!FS.hasValidLeadingZeros())
    HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen);
  if (!FS.hasValidPlusPrefix())
    HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen);
  if (!FS.hasValidSpacePrefix())
    HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen);
  if (!FS.hasValidAlternativeForm())
    HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen);
  if (!FS.hasValidLeftJustified())
    HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen);

  // Check that flags are not ignored by another flag
  if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+'
    HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(),
        startSpecifier, specifierLen);
  if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-'
    HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(),
            startSpecifier, specifierLen);

  // Check the length modifier is valid with the given conversion specifier.
  if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo(),
                                 S.getLangOpts()))
    HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
                                diag::warn_format_nonsensical_length);
  else if (!FS.hasStandardLengthModifier())
    HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen);
  else if (!FS.hasStandardLengthConversionCombination())
    HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
                                diag::warn_format_non_standard_conversion_spec);

  if (!FS.hasStandardConversionSpecifier(S.getLangOpts()))
    HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);

  // The remaining checks depend on the data arguments.
  if (!HasFormatArguments())
    return true;

  if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
    return false;

  const Expr *Arg = getDataArg(argIndex);
  if (!Arg)
    return true;

  return checkFormatExpr(FS, startSpecifier, specifierLen, Arg);
}

static bool requiresParensToAddCast(const Expr *E) {
  // FIXME: We should have a general way to reason about operator
  // precedence and whether parens are actually needed here.
  // Take care of a few common cases where they aren't.
  const Expr *Inside = E->IgnoreImpCasts();
  if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(Inside))
    Inside = POE->getSyntacticForm()->IgnoreImpCasts();

  switch (Inside->getStmtClass()) {
  case Stmt::ArraySubscriptExprClass:
  case Stmt::CallExprClass:
  case Stmt::CharacterLiteralClass:
  case Stmt::CXXBoolLiteralExprClass:
  case Stmt::DeclRefExprClass:
  case Stmt::FloatingLiteralClass:
  case Stmt::IntegerLiteralClass:
  case Stmt::MemberExprClass:
  case Stmt::ObjCArrayLiteralClass:
  case Stmt::ObjCBoolLiteralExprClass:
  case Stmt::ObjCBoxedExprClass:
  case Stmt::ObjCDictionaryLiteralClass:
  case Stmt::ObjCEncodeExprClass:
  case Stmt::ObjCIvarRefExprClass:
  case Stmt::ObjCMessageExprClass:
  case Stmt::ObjCPropertyRefExprClass:
  case Stmt::ObjCStringLiteralClass:
  case Stmt::ObjCSubscriptRefExprClass:
  case Stmt::ParenExprClass:
  case Stmt::StringLiteralClass:
  case Stmt::UnaryOperatorClass:
    return false;
  default:
    return true;
  }
}

static std::pair<QualType, StringRef>
shouldNotPrintDirectly(const ASTContext &Context,
                       QualType IntendedTy,
                       const Expr *E) {
  // Use a 'while' to peel off layers of typedefs.
  QualType TyTy = IntendedTy;
  while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) {
    StringRef Name = UserTy->getDecl()->getName();
    QualType CastTy = llvm::StringSwitch<QualType>(Name)
      .Case("CFIndex", Context.getNSIntegerType())
      .Case("NSInteger", Context.getNSIntegerType())
      .Case("NSUInteger", Context.getNSUIntegerType())
      .Case("SInt32", Context.IntTy)
      .Case("UInt32", Context.UnsignedIntTy)
      .Default(QualType());

    if (!CastTy.isNull())
      return std::make_pair(CastTy, Name);

    TyTy = UserTy->desugar();
  }

  // Strip parens if necessary.
  if (const ParenExpr *PE = dyn_cast<ParenExpr>(E))
    return shouldNotPrintDirectly(Context,
                                  PE->getSubExpr()->getType(),
                                  PE->getSubExpr());

  // If this is a conditional expression, then its result type is constructed
  // via usual arithmetic conversions and thus there might be no necessary
  // typedef sugar there.  Recurse to operands to check for NSInteger &
  // Co. usage condition.
  if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
    QualType TrueTy, FalseTy;
    StringRef TrueName, FalseName;

    std::tie(TrueTy, TrueName) =
      shouldNotPrintDirectly(Context,
                             CO->getTrueExpr()->getType(),
                             CO->getTrueExpr());
    std::tie(FalseTy, FalseName) =
      shouldNotPrintDirectly(Context,
                             CO->getFalseExpr()->getType(),
                             CO->getFalseExpr());

    if (TrueTy == FalseTy)
      return std::make_pair(TrueTy, TrueName);
    else if (TrueTy.isNull())
      return std::make_pair(FalseTy, FalseName);
    else if (FalseTy.isNull())
      return std::make_pair(TrueTy, TrueName);
  }

  return std::make_pair(QualType(), StringRef());
}

/// Return true if \p ICE is an implicit argument promotion of an arithmetic
/// type. Bit-field 'promotions' from a higher ranked type to a lower ranked
/// type do not count.
static bool
isArithmeticArgumentPromotion(Sema &S, const ImplicitCastExpr *ICE) {
  QualType From = ICE->getSubExpr()->getType();
  QualType To = ICE->getType();
  // It's an integer promotion if the destination type is the promoted
  // source type.
  if (ICE->getCastKind() == CK_IntegralCast &&
      S.Context.isPromotableIntegerType(From) &&
      S.Context.getPromotedIntegerType(From) == To)
    return true;
  // Look through vector types, since we do default argument promotion for
  // those in OpenCL.
  if (const auto *VecTy = From->getAs<ExtVectorType>())
    From = VecTy->getElementType();
  if (const auto *VecTy = To->getAs<ExtVectorType>())
    To = VecTy->getElementType();
  // It's a floating promotion if the source type is a lower rank.
  return ICE->getCastKind() == CK_FloatingCast &&
         S.Context.getFloatingTypeOrder(From, To) < 0;
}

static analyze_format_string::ArgType::MatchKind
handleFormatSignedness(analyze_format_string::ArgType::MatchKind Match,
                       DiagnosticsEngine &Diags, SourceLocation Loc) {
  if (Match == analyze_format_string::ArgType::NoMatchSignedness) {
    Match =
        Diags.isIgnored(
            diag::warn_format_conversion_argument_type_mismatch_signedness, Loc)
            ? analyze_format_string::ArgType::Match
            : analyze_format_string::ArgType::NoMatch;
  }
  return Match;
}

bool
CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS,
                                    const char *StartSpecifier,
                                    unsigned SpecifierLen,
                                    const Expr *E) {
  using namespace analyze_format_string;
  using namespace analyze_printf;

  // Now type check the data expression that matches the
  // format specifier.
  const analyze_printf::ArgType &AT = FS.getArgType(S.Context, isObjCContext());
  if (!AT.isValid())
    return true;

  QualType ExprTy = E->getType();
  while (const TypeOfExprType *TET = dyn_cast<TypeOfExprType>(ExprTy)) {
    ExprTy = TET->getUnderlyingExpr()->getType();
  }

  // When using the format attribute in C++, you can receive a function or an
  // array that will necessarily decay to a pointer when passed to the final
  // format consumer. Apply decay before type comparison.
  if (ExprTy->canDecayToPointerType())
    ExprTy = S.Context.getDecayedType(ExprTy);

  // Diagnose attempts to print a boolean value as a character. Unlike other
  // -Wformat diagnostics, this is fine from a type perspective, but it still
  // doesn't make sense.
  if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::cArg &&
      E->isKnownToHaveBooleanValue()) {
    const CharSourceRange &CSR =
        getSpecifierRange(StartSpecifier, SpecifierLen);
    SmallString<4> FSString;
    llvm::raw_svector_ostream os(FSString);
    FS.toString(os);
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_bool_as_character)
                             << FSString,
                         E->getExprLoc(), false, CSR);
    return true;
  }

  // Diagnose attempts to use '%P' with ObjC object types, which will result in
  // dumping raw class data (like is-a pointer), not actual data.
  if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::PArg &&
      ExprTy->isObjCObjectPointerType()) {
    const CharSourceRange &CSR =
        getSpecifierRange(StartSpecifier, SpecifierLen);
    EmitFormatDiagnostic(S.PDiag(diag::warn_format_P_with_objc_pointer),
                         E->getExprLoc(), false, CSR);
    return true;
  }

  ArgType::MatchKind ImplicitMatch = ArgType::NoMatch;
  ArgType::MatchKind Match = AT.matchesType(S.Context, ExprTy);
  ArgType::MatchKind OrigMatch = Match;

  Match = handleFormatSignedness(Match, S.getDiagnostics(), E->getExprLoc());
  if (Match == ArgType::Match)
    return true;

  // NoMatchPromotionTypeConfusion should be only returned in ImplictCastExpr
  assert(Match != ArgType::NoMatchPromotionTypeConfusion);

  // Look through argument promotions for our error message's reported type.
  // This includes the integral and floating promotions, but excludes array
  // and function pointer decay (seeing that an argument intended to be a
  // string has type 'char [6]' is probably more confusing than 'char *') and
  // certain bitfield promotions (bitfields can be 'demoted' to a lesser type).
  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
    if (isArithmeticArgumentPromotion(S, ICE)) {
      E = ICE->getSubExpr();
      ExprTy = E->getType();

      // Check if we didn't match because of an implicit cast from a 'char'
      // or 'short' to an 'int'.  This is done because printf is a varargs
      // function.
      if (ICE->getType() == S.Context.IntTy ||
          ICE->getType() == S.Context.UnsignedIntTy) {
        // All further checking is done on the subexpression
        ImplicitMatch = AT.matchesType(S.Context, ExprTy);
        if (OrigMatch == ArgType::NoMatchSignedness &&
            ImplicitMatch != ArgType::NoMatchSignedness)
          // If the original match was a signedness match this match on the
          // implicit cast type also need to be signedness match otherwise we
          // might introduce new unexpected warnings from -Wformat-signedness.
          return true;
        ImplicitMatch = handleFormatSignedness(
            ImplicitMatch, S.getDiagnostics(), E->getExprLoc());
        if (ImplicitMatch == ArgType::Match)
          return true;
      }
    }
  } else if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) {
    // Special case for 'a', which has type 'int' in C.
    // Note, however, that we do /not/ want to treat multibyte constants like
    // 'MooV' as characters! This form is deprecated but still exists. In
    // addition, don't treat expressions as of type 'char' if one byte length
    // modifier is provided.
    if (ExprTy == S.Context.IntTy &&
        FS.getLengthModifier().getKind() != LengthModifier::AsChar)
      if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue())) {
        ExprTy = S.Context.CharTy;
        // To improve check results, we consider a character literal in C
        // to be a 'char' rather than an 'int'. 'printf("%hd", 'a');' is
        // more likely a type confusion situation, so we will suggest to
        // use '%hhd' instead by discarding the MatchPromotion.
        if (Match == ArgType::MatchPromotion)
          Match = ArgType::NoMatch;
      }
  }
  if (Match == ArgType::MatchPromotion) {
    // WG14 N2562 only clarified promotions in *printf
    // For NSLog in ObjC, just preserve -Wformat behavior
    if (!S.getLangOpts().ObjC &&
        ImplicitMatch != ArgType::NoMatchPromotionTypeConfusion &&
        ImplicitMatch != ArgType::NoMatchTypeConfusion)
      return true;
    Match = ArgType::NoMatch;
  }
  if (ImplicitMatch == ArgType::NoMatchPedantic ||
      ImplicitMatch == ArgType::NoMatchTypeConfusion)
    Match = ImplicitMatch;
  assert(Match != ArgType::MatchPromotion);

  // Look through unscoped enums to their underlying type.
  bool IsEnum = false;
  bool IsScopedEnum = false;
  QualType IntendedTy = ExprTy;
  if (auto EnumTy = ExprTy->getAs<EnumType>()) {
    IntendedTy = EnumTy->getDecl()->getIntegerType();
    if (EnumTy->isUnscopedEnumerationType()) {
      ExprTy = IntendedTy;
      // This controls whether we're talking about the underlying type or not,
      // which we only want to do when it's an unscoped enum.
      IsEnum = true;
    } else {
      IsScopedEnum = true;
    }
  }

  // %C in an Objective-C context prints a unichar, not a wchar_t.
  // If the argument is an integer of some kind, believe the %C and suggest
  // a cast instead of changing the conversion specifier.
  if (isObjCContext() &&
      FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) {
    if (ExprTy->isIntegralOrUnscopedEnumerationType() &&
        !ExprTy->isCharType()) {
      // 'unichar' is defined as a typedef of unsigned short, but we should
      // prefer using the typedef if it is visible.
      IntendedTy = S.Context.UnsignedShortTy;

      // While we are here, check if the value is an IntegerLiteral that happens
      // to be within the valid range.
      if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(E)) {
        const llvm::APInt &V = IL->getValue();
        if (V.getActiveBits() <= S.Context.getTypeSize(IntendedTy))
          return true;
      }

      LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getBeginLoc(),
                          Sema::LookupOrdinaryName);
      if (S.LookupName(Result, S.getCurScope())) {
        NamedDecl *ND = Result.getFoundDecl();
        if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND))
          if (TD->getUnderlyingType() == IntendedTy)
            IntendedTy = S.Context.getTypedefType(TD);
      }
    }
  }

  // Special-case some of Darwin's platform-independence types by suggesting
  // casts to primitive types that are known to be large enough.
  bool ShouldNotPrintDirectly = false; StringRef CastTyName;
  if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {
    QualType CastTy;
    std::tie(CastTy, CastTyName) = shouldNotPrintDirectly(S.Context, IntendedTy, E);
    if (!CastTy.isNull()) {
      // %zi/%zu and %td/%tu are OK to use for NSInteger/NSUInteger of type int
      // (long in ASTContext). Only complain to pedants or when they're the
      // underlying type of a scoped enum (which always needs a cast).
      if (!IsScopedEnum &&
          (CastTyName == "NSInteger" || CastTyName == "NSUInteger") &&
          (AT.isSizeT() || AT.isPtrdiffT()) &&
          AT.matchesType(S.Context, CastTy))
        Match = ArgType::NoMatchPedantic;
      IntendedTy = CastTy;
      ShouldNotPrintDirectly = true;
    }
  }

  // We may be able to offer a FixItHint if it is a supported type.
  PrintfSpecifier fixedFS = FS;
  bool Success =
      fixedFS.fixType(IntendedTy, S.getLangOpts(), S.Context, isObjCContext());

  if (Success) {
    // Get the fix string from the fixed format specifier
    SmallString<16> buf;
    llvm::raw_svector_ostream os(buf);
    fixedFS.toString(os);

    CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen);

    if (IntendedTy == ExprTy && !ShouldNotPrintDirectly && !IsScopedEnum) {
      unsigned Diag;
      switch (Match) {
      case ArgType::Match:
      case ArgType::MatchPromotion:
      case ArgType::NoMatchPromotionTypeConfusion:
      case ArgType::NoMatchSignedness:
        llvm_unreachable("expected non-matching");
      case ArgType::NoMatchPedantic:
        Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
        break;
      case ArgType::NoMatchTypeConfusion:
        Diag = diag::warn_format_conversion_argument_type_mismatch_confusion;
        break;
      case ArgType::NoMatch:
        Diag = diag::warn_format_conversion_argument_type_mismatch;
        break;
      }

      // In this case, the specifier is wrong and should be changed to match
      // the argument.
      EmitFormatDiagnostic(S.PDiag(Diag)
                               << AT.getRepresentativeTypeName(S.Context)
                               << IntendedTy << IsEnum << E->getSourceRange(),
                           E->getBeginLoc(),
                           /*IsStringLocation*/ false, SpecRange,
                           FixItHint::CreateReplacement(SpecRange, os.str()));
    } else {
      // The canonical type for formatting this value is different from the
      // actual type of the expression. (This occurs, for example, with Darwin's
      // NSInteger on 32-bit platforms, where it is typedef'd as 'int', but
      // should be printed as 'long' for 64-bit compatibility.)
      // Rather than emitting a normal format/argument mismatch, we want to
      // add a cast to the recommended type (and correct the format string
      // if necessary). We should also do so for scoped enumerations.
      SmallString<16> CastBuf;
      llvm::raw_svector_ostream CastFix(CastBuf);
      CastFix << (S.LangOpts.CPlusPlus ? "static_cast<" : "(");
      IntendedTy.print(CastFix, S.Context.getPrintingPolicy());
      CastFix << (S.LangOpts.CPlusPlus ? ">" : ")");

      SmallVector<FixItHint,4> Hints;
      ArgType::MatchKind IntendedMatch = AT.matchesType(S.Context, IntendedTy);
      IntendedMatch = handleFormatSignedness(IntendedMatch, S.getDiagnostics(),
                                             E->getExprLoc());
      if ((IntendedMatch != ArgType::Match) || ShouldNotPrintDirectly)
        Hints.push_back(FixItHint::CreateReplacement(SpecRange, os.str()));

      if (const CStyleCastExpr *CCast = dyn_cast<CStyleCastExpr>(E)) {
        // If there's already a cast present, just replace it.
        SourceRange CastRange(CCast->getLParenLoc(), CCast->getRParenLoc());
        Hints.push_back(FixItHint::CreateReplacement(CastRange, CastFix.str()));

      } else if (!requiresParensToAddCast(E) && !S.LangOpts.CPlusPlus) {
        // If the expression has high enough precedence,
        // just write the C-style cast.
        Hints.push_back(
            FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str()));
      } else {
        // Otherwise, add parens around the expression as well as the cast.
        CastFix << "(";
        Hints.push_back(
            FixItHint::CreateInsertion(E->getBeginLoc(), CastFix.str()));

        // We don't use getLocForEndOfToken because it returns invalid source
        // locations for macro expansions (by design).
        SourceLocation EndLoc = S.SourceMgr.getSpellingLoc(E->getEndLoc());
        SourceLocation After = EndLoc.getLocWithOffset(
            Lexer::MeasureTokenLength(EndLoc, S.SourceMgr, S.LangOpts));
        Hints.push_back(FixItHint::CreateInsertion(After, ")"));
      }

      if (ShouldNotPrintDirectly && !IsScopedEnum) {
        // The expression has a type that should not be printed directly.
        // We extract the name from the typedef because we don't want to show
        // the underlying type in the diagnostic.
        StringRef Name;
        if (const auto *TypedefTy = ExprTy->getAs<TypedefType>())
          Name = TypedefTy->getDecl()->getName();
        else
          Name = CastTyName;
        unsigned Diag = Match == ArgType::NoMatchPedantic
                            ? diag::warn_format_argument_needs_cast_pedantic
                            : diag::warn_format_argument_needs_cast;
        EmitFormatDiagnostic(S.PDiag(Diag) << Name << IntendedTy << IsEnum
                                           << E->getSourceRange(),
                             E->getBeginLoc(), /*IsStringLocation=*/false,
                             SpecRange, Hints);
      } else {
        // In this case, the expression could be printed using a different
        // specifier, but we've decided that the specifier is probably correct
        // and we should cast instead. Just use the normal warning message.

        unsigned Diag =
            IsScopedEnum
                ? diag::warn_format_conversion_argument_type_mismatch_pedantic
                : diag::warn_format_conversion_argument_type_mismatch;

        EmitFormatDiagnostic(
            S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
                          << IsEnum << E->getSourceRange(),
            E->getBeginLoc(), /*IsStringLocation*/ false, SpecRange, Hints);
      }
    }
  } else {
    const CharSourceRange &CSR = getSpecifierRange(StartSpecifier,
                                                   SpecifierLen);
    // Since the warning for passing non-POD types to variadic functions
    // was deferred until now, we emit a warning for non-POD
    // arguments here.
    bool EmitTypeMismatch = false;
    switch (S.isValidVarArgType(ExprTy)) {
    case VarArgKind::Valid:
    case VarArgKind::ValidInCXX11: {
      unsigned Diag;
      switch (Match) {
      case ArgType::Match:
      case ArgType::MatchPromotion:
      case ArgType::NoMatchPromotionTypeConfusion:
      case ArgType::NoMatchSignedness:
        llvm_unreachable("expected non-matching");
      case ArgType::NoMatchPedantic:
        Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic;
        break;
      case ArgType::NoMatchTypeConfusion:
        Diag = diag::warn_format_conversion_argument_type_mismatch_confusion;
        break;
      case ArgType::NoMatch:
        Diag = diag::warn_format_conversion_argument_type_mismatch;
        break;
      }

      EmitFormatDiagnostic(
          S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context) << ExprTy
                        << IsEnum << CSR << E->getSourceRange(),
          E->getBeginLoc(), /*IsStringLocation*/ false, CSR);
      break;
    }
    case VarArgKind::Undefined:
    case VarArgKind::MSVCUndefined:
      if (CallType == VariadicCallType::DoesNotApply) {
        EmitTypeMismatch = true;
      } else {
        EmitFormatDiagnostic(
            S.PDiag(diag::warn_non_pod_vararg_with_format_string)
                << S.getLangOpts().CPlusPlus11 << ExprTy << CallType
                << AT.getRepresentativeTypeName(S.Context) << CSR
                << E->getSourceRange(),
            E->getBeginLoc(), /*IsStringLocation*/ false, CSR);
        checkForCStrMembers(AT, E);
      }
      break;

    case VarArgKind::Invalid:
      if (CallType == VariadicCallType::DoesNotApply)
        EmitTypeMismatch = true;
      else if (ExprTy->isObjCObjectType())
        EmitFormatDiagnostic(
            S.PDiag(diag::err_cannot_pass_objc_interface_to_vararg_format)
                << S.getLangOpts().CPlusPlus11 << ExprTy << CallType
                << AT.getRepresentativeTypeName(S.Context) << CSR
                << E->getSourceRange(),
            E->getBeginLoc(), /*IsStringLocation*/ false, CSR);
      else
        // FIXME: If this is an initializer list, suggest removing the braces
        // or inserting a cast to the target type.
        S.Diag(E->getBeginLoc(), diag::err_cannot_pass_to_vararg_format)
            << isa<InitListExpr>(E) << ExprTy << CallType
            << AT.getRepresentativeTypeName(S.Context) << E->getSourceRange();
      break;
    }

    if (EmitTypeMismatch) {
      // The function is not variadic, so we do not generate warnings about
      // being allowed to pass that object as a variadic argument. Instead,
      // since there are inherently no printf specifiers for types which cannot
      // be passed as variadic arguments, emit a plain old specifier mismatch
      // argument.
      EmitFormatDiagnostic(
          S.PDiag(diag::warn_format_conversion_argument_type_mismatch)
              << AT.getRepresentativeTypeName(S.Context) << ExprTy << false
              << E->getSourceRange(),
          E->getBeginLoc(), false, CSR);
    }

    assert(FirstDataArg + FS.getArgIndex() < CheckedVarArgs.size() &&
           "format string specifier index out of range");
    CheckedVarArgs[FirstDataArg + FS.getArgIndex()] = true;
  }

  return true;
}

//===--- CHECK: Scanf format string checking ------------------------------===//

namespace {

class CheckScanfHandler : public CheckFormatHandler {
public:
  CheckScanfHandler(Sema &s, const FormatStringLiteral *fexpr,
                    const Expr *origFormatExpr, FormatStringType type,
                    unsigned firstDataArg, unsigned numDataArgs,
                    const char *beg, Sema::FormatArgumentPassingKind APK,
                    ArrayRef<const Expr *> Args, unsigned formatIdx,
                    bool inFunctionCall, VariadicCallType CallType,
                    llvm::SmallBitVector &CheckedVarArgs,
                    UncoveredArgHandler &UncoveredArg)
      : CheckFormatHandler(s, fexpr, origFormatExpr, type, firstDataArg,
                           numDataArgs, beg, APK, Args, formatIdx,
                           inFunctionCall, CallType, CheckedVarArgs,
                           UncoveredArg) {}

  bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
                            const char *startSpecifier,
                            unsigned specifierLen) override;

  bool HandleInvalidScanfConversionSpecifier(
          const analyze_scanf::ScanfSpecifier &FS,
          const char *startSpecifier,
          unsigned specifierLen) override;

  void HandleIncompleteScanList(const char *start, const char *end) override;
};

} // namespace

void CheckScanfHandler::HandleIncompleteScanList(const char *start,
                                                 const char *end) {
  EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_scanlist_incomplete),
                       getLocationOfByte(end), /*IsStringLocation*/true,
                       getSpecifierRange(start, end - start));
}

bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier(
                                        const analyze_scanf::ScanfSpecifier &FS,
                                        const char *startSpecifier,
                                        unsigned specifierLen) {
  const analyze_scanf::ScanfConversionSpecifier &CS =
    FS.getConversionSpecifier();

  return HandleInvalidConversionSpecifier(FS.getArgIndex(),
                                          getLocationOfByte(CS.getStart()),
                                          startSpecifier, specifierLen,
                                          CS.getStart(), CS.getLength());
}

bool CheckScanfHandler::HandleScanfSpecifier(
                                       const analyze_scanf::ScanfSpecifier &FS,
                                       const char *startSpecifier,
                                       unsigned specifierLen) {
  using namespace analyze_scanf;
  using namespace analyze_format_string;

  const ScanfConversionSpecifier &CS = FS.getConversionSpecifier();

  // Handle case where '%' and '*' don't consume an argument.  These shouldn't
  // be used to decide if we are using positional arguments consistently.
  if (FS.consumesDataArgument()) {
    if (atFirstArg) {
      atFirstArg = false;
      usesPositionalArgs = FS.usesPositionalArg();
    }
    else if (usesPositionalArgs != FS.usesPositionalArg()) {
      HandlePositionalNonpositionalArgs(getLocationOfByte(CS.getStart()),
                                        startSpecifier, specifierLen);
      return false;
    }
  }

  // Check if the field with is non-zero.
  const OptionalAmount &Amt = FS.getFieldWidth();
  if (Amt.getHowSpecified() == OptionalAmount::Constant) {
    if (Amt.getConstantAmount() == 0) {
      const CharSourceRange &R = getSpecifierRange(Amt.getStart(),
                                                   Amt.getConstantLength());
      EmitFormatDiagnostic(S.PDiag(diag::warn_scanf_nonzero_width),
                           getLocationOfByte(Amt.getStart()),
                           /*IsStringLocation*/true, R,
                           FixItHint::CreateRemoval(R));
    }
  }

  if (!FS.consumesDataArgument()) {
    // FIXME: Technically specifying a precision or field width here
    // makes no sense.  Worth issuing a warning at some point.
    return true;
  }

  // Consume the argument.
  unsigned argIndex = FS.getArgIndex();
  if (argIndex < NumDataArgs) {
      // The check to see if the argIndex is valid will come later.
      // We set the bit here because we may exit early from this
      // function if we encounter some other error.
    CoveredArgs.set(argIndex);
  }

  // Check the length modifier is valid with the given conversion specifier.
  if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo(),
                                 S.getLangOpts()))
    HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
                                diag::warn_format_nonsensical_length);
  else if (!FS.hasStandardLengthModifier())
    HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen);
  else if (!FS.hasStandardLengthConversionCombination())
    HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen,
                                diag::warn_format_non_standard_conversion_spec);

  if (!FS.hasStandardConversionSpecifier(S.getLangOpts()))
    HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen);

  // The remaining checks depend on the data arguments.
  if (!HasFormatArguments())
    return true;

  if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex))
    return false;

  // Check that the argument type matches the format specifier.
  const Expr *Ex = getDataArg(argIndex);
  if (!Ex)
    return true;

  const analyze_format_string::ArgType &AT = FS.getArgType(S.Context);

  if (!AT.isValid()) {
    return true;
  }

  analyze_format_string::ArgType::MatchKind Match =
      AT.matchesType(S.Context, Ex->getType());
  Match = handleFormatSignedness(Match, S.getDiagnostics(), Ex->getExprLoc());
  bool Pedantic = Match == analyze_format_string::ArgType::NoMatchPedantic;
  if (Match == analyze_format_string::ArgType::Match)
    return true;

  ScanfSpecifier fixedFS = FS;
  bool Success = fixedFS.fixType(Ex->getType(), Ex->IgnoreImpCasts()->getType(),
                                 S.getLangOpts(), S.Context);

  unsigned Diag =
      Pedantic ? diag::warn_format_conversion_argument_type_mismatch_pedantic
               : diag::warn_format_conversion_argument_type_mismatch;

  if (Success) {
    // Get the fix string from the fixed format specifier.
    SmallString<128> buf;
    llvm::raw_svector_ostream os(buf);
    fixedFS.toString(os);

    EmitFormatDiagnostic(
        S.PDiag(Diag) << AT.getRepresentativeTypeName(S.Context)
                      << Ex->getType() << false << Ex->getSourceRange(),
        Ex->getBeginLoc(),
        /*IsStringLocation*/ false,
        getSpecifierRange(startSpecifier, specifierLen),
        FixItHint::CreateReplacement(
            getSpecifierRange(startSpecifier, specifierLen), os.str()));
  } else {
    EmitFormatDiagnostic(S.PDiag(Diag)
                             << AT.getRepresentativeTypeName(S.Context)
                             << Ex->getType() << false << Ex->getSourceRange(),
                         Ex->getBeginLoc(),
                         /*IsStringLocation*/ false,
                         getSpecifierRange(startSpecifier, specifierLen));
  }

  return true;
}

static bool CompareFormatSpecifiers(Sema &S, const StringLiteral *Ref,
                                    ArrayRef<EquatableFormatArgument> RefArgs,
                                    const StringLiteral *Fmt,
                                    ArrayRef<EquatableFormatArgument> FmtArgs,
                                    const Expr *FmtExpr, bool InFunctionCall) {
  bool HadError = false;
  auto FmtIter = FmtArgs.begin(), FmtEnd = FmtArgs.end();
  auto RefIter = RefArgs.begin(), RefEnd = RefArgs.end();
  while (FmtIter < FmtEnd && RefIter < RefEnd) {
    // In positional-style format strings, the same specifier can appear
    // multiple times (like %2$i %2$d). Specifiers in both RefArgs and FmtArgs
    // are sorted by getPosition(), and we process each range of equal
    // getPosition() values as one group.
    // RefArgs are taken from a string literal that was given to
    // attribute(format_matches), and if we got this far, we have already
    // verified that if it has positional specifiers that appear in multiple
    // locations, then they are all mutually compatible. What's left for us to
    // do is verify that all specifiers with the same position in FmtArgs are
    // compatible with the RefArgs specifiers. We check each specifier from
    // FmtArgs against the first member of the RefArgs group.
    for (; FmtIter < FmtEnd; ++FmtIter) {
      // Clang does not diagnose missing format specifiers in positional-style
      // strings (TODO: which it probably should do, as it is UB to skip over a
      // format argument). Skip specifiers if needed.
      if (FmtIter->getPosition() < RefIter->getPosition())
        continue;

      // Delimits a new getPosition() value.
      if (FmtIter->getPosition() > RefIter->getPosition())
        break;

      HadError |=
          !FmtIter->VerifyCompatible(S, *RefIter, FmtExpr, InFunctionCall);
    }

    // Jump RefIter to the start of the next group.
    RefIter = std::find_if(RefIter + 1, RefEnd, [=](const auto &Arg) {
      return Arg.getPosition() != RefIter->getPosition();
    });
  }

  if (FmtIter < FmtEnd) {
    CheckFormatHandler::EmitFormatDiagnostic(
        S, InFunctionCall, FmtExpr,
        S.PDiag(diag::warn_format_cmp_specifier_arity) << 1,
        FmtExpr->getBeginLoc(), false, FmtIter->getSourceRange());
    HadError = S.Diag(Ref->getBeginLoc(), diag::note_format_cmp_with) << 1;
  } else if (RefIter < RefEnd) {
    CheckFormatHandler::EmitFormatDiagnostic(
        S, InFunctionCall, FmtExpr,
        S.PDiag(diag::warn_format_cmp_specifier_arity) << 0,
        FmtExpr->getBeginLoc(), false, Fmt->getSourceRange());
    HadError = S.Diag(Ref->getBeginLoc(), diag::note_format_cmp_with)
               << 1 << RefIter->getSourceRange();
  }
  return !HadError;
}

static void CheckFormatString(
    Sema &S, const FormatStringLiteral *FExpr,
    const StringLiteral *ReferenceFormatString, const Expr *OrigFormatExpr,
    ArrayRef<const Expr *> Args, Sema::FormatArgumentPassingKind APK,
    unsigned format_idx, unsigned firstDataArg, FormatStringType Type,
    bool inFunctionCall, VariadicCallType CallType,
    llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
    bool IgnoreStringsWithoutSpecifiers) {
  // CHECK: is the format string a wide literal?
  if (!FExpr->isAscii() && !FExpr->isUTF8()) {
    CheckFormatHandler::EmitFormatDiagnostic(
        S, inFunctionCall, Args[format_idx],
        S.PDiag(diag::warn_format_string_is_wide_literal), FExpr->getBeginLoc(),
        /*IsStringLocation*/ true, OrigFormatExpr->getSourceRange());
    return;
  }

  // Str - The format string.  NOTE: this is NOT null-terminated!
  StringRef StrRef = FExpr->getString();
  const char *Str = StrRef.data();
  // Account for cases where the string literal is truncated in a declaration.
  const ConstantArrayType *T =
    S.Context.getAsConstantArrayType(FExpr->getType());
  assert(T && "String literal not of constant array type!");
  size_t TypeSize = T->getZExtSize();
  size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size());
  const unsigned numDataArgs = Args.size() - firstDataArg;

  if (IgnoreStringsWithoutSpecifiers &&
      !analyze_format_string::parseFormatStringHasFormattingSpecifiers(
          Str, Str + StrLen, S.getLangOpts(), S.Context.getTargetInfo()))
    return;

  // Emit a warning if the string literal is truncated and does not contain an
  // embedded null character.
  if (TypeSize <= StrRef.size() && !StrRef.substr(0, TypeSize).contains('\0')) {
    CheckFormatHandler::EmitFormatDiagnostic(
        S, inFunctionCall, Args[format_idx],
        S.PDiag(diag::warn_printf_format_string_not_null_terminated),
        FExpr->getBeginLoc(),
        /*IsStringLocation=*/true, OrigFormatExpr->getSourceRange());
    return;
  }

  // CHECK: empty format string?
  if (StrLen == 0 && numDataArgs > 0) {
    CheckFormatHandler::EmitFormatDiagnostic(
        S, inFunctionCall, Args[format_idx],
        S.PDiag(diag::warn_empty_format_string), FExpr->getBeginLoc(),
        /*IsStringLocation*/ true, OrigFormatExpr->getSourceRange());
    return;
  }

  if (Type == FormatStringType::Printf || Type == FormatStringType::NSString ||
      Type == FormatStringType::Kprintf ||
      Type == FormatStringType::FreeBSDKPrintf ||
      Type == FormatStringType::OSLog || Type == FormatStringType::OSTrace ||
      Type == FormatStringType::Syslog) {
    bool IsObjC =
        Type == FormatStringType::NSString || Type == FormatStringType::OSTrace;
    if (ReferenceFormatString == nullptr) {
      CheckPrintfHandler H(S, FExpr, OrigFormatExpr, Type, firstDataArg,
                           numDataArgs, IsObjC, Str, APK, Args, format_idx,
                           inFunctionCall, CallType, CheckedVarArgs,
                           UncoveredArg);

      if (!analyze_format_string::ParsePrintfString(
              H, Str, Str + StrLen, S.getLangOpts(), S.Context.getTargetInfo(),
              Type == FormatStringType::Kprintf ||
                  Type == FormatStringType::FreeBSDKPrintf))
        H.DoneProcessing();
    } else {
      S.CheckFormatStringsCompatible(
          Type, ReferenceFormatString, FExpr->getFormatString(),
          inFunctionCall ? nullptr : Args[format_idx]);
    }
  } else if (Type == FormatStringType::Scanf) {
    CheckScanfHandler H(S, FExpr, OrigFormatExpr, Type, firstDataArg,
                        numDataArgs, Str, APK, Args, format_idx, inFunctionCall,
                        CallType, CheckedVarArgs, UncoveredArg);

    if (!analyze_format_string::ParseScanfString(
            H, Str, Str + StrLen, S.getLangOpts(), S.Context.getTargetInfo()))
      H.DoneProcessing();
  } // TODO: handle other formats
}

bool Sema::CheckFormatStringsCompatible(
    FormatStringType Type, const StringLiteral *AuthoritativeFormatString,
    const StringLiteral *TestedFormatString, const Expr *FunctionCallArg) {
  if (Type != FormatStringType::Printf && Type != FormatStringType::NSString &&
      Type != FormatStringType::Kprintf &&
      Type != FormatStringType::FreeBSDKPrintf &&
      Type != FormatStringType::OSLog && Type != FormatStringType::OSTrace &&
      Type != FormatStringType::Syslog)
    return true;

  bool IsObjC =
      Type == FormatStringType::NSString || Type == FormatStringType::OSTrace;
  llvm::SmallVector<EquatableFormatArgument, 9> RefArgs, FmtArgs;
  FormatStringLiteral RefLit = AuthoritativeFormatString;
  FormatStringLiteral TestLit = TestedFormatString;
  const Expr *Arg;
  bool DiagAtStringLiteral;
  if (FunctionCallArg) {
    Arg = FunctionCallArg;
    DiagAtStringLiteral = false;
  } else {
    Arg = TestedFormatString;
    DiagAtStringLiteral = true;
  }
  if (DecomposePrintfHandler::GetSpecifiers(*this, &RefLit,
                                            AuthoritativeFormatString, Type,
                                            IsObjC, true, RefArgs) &&
      DecomposePrintfHandler::GetSpecifiers(*this, &TestLit, Arg, Type, IsObjC,
                                            DiagAtStringLiteral, FmtArgs)) {
    return CompareFormatSpecifiers(*this, AuthoritativeFormatString, RefArgs,
                                   TestedFormatString, FmtArgs, Arg,
                                   DiagAtStringLiteral);
  }
  return false;
}

bool Sema::ValidateFormatString(FormatStringType Type,
                                const StringLiteral *Str) {
  if (Type != FormatStringType::Printf && Type != FormatStringType::NSString &&
      Type != FormatStringType::Kprintf &&
      Type != FormatStringType::FreeBSDKPrintf &&
      Type != FormatStringType::OSLog && Type != FormatStringType::OSTrace &&
      Type != FormatStringType::Syslog)
    return true;

  FormatStringLiteral RefLit = Str;
  llvm::SmallVector<EquatableFormatArgument, 9> Args;
  bool IsObjC =
      Type == FormatStringType::NSString || Type == FormatStringType::OSTrace;
  if (!DecomposePrintfHandler::GetSpecifiers(*this, &RefLit, Str, Type, IsObjC,
                                             true, Args))
    return false;

  // Group arguments by getPosition() value, and check that each member of the
  // group is compatible with the first member. This verifies that when
  // positional arguments are used multiple times (such as %2$i %2$d), all uses
  // are mutually compatible. As an optimization, don't test the first member
  // against itself.
  bool HadError = false;
  auto Iter = Args.begin();
  auto End = Args.end();
  while (Iter != End) {
    const auto &FirstInGroup = *Iter;
    for (++Iter;
         Iter != End && Iter->getPosition() == FirstInGroup.getPosition();
         ++Iter) {
      HadError |= !Iter->VerifyCompatible(*this, FirstInGroup, Str, true);
    }
  }
  return !HadError;
}

bool Sema::FormatStringHasSArg(const StringLiteral *FExpr) {
  // Str - The format string.  NOTE: this is NOT null-terminated!
  StringRef StrRef = FExpr->getString();
  const char *Str = StrRef.data();
  // Account for cases where the string literal is truncated in a declaration.
  const ConstantArrayType *T = Context.getAsConstantArrayType(FExpr->getType());
  assert(T && "String literal not of constant array type!");
  size_t TypeSize = T->getZExtSize();
  size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size());
  return analyze_format_string::ParseFormatStringHasSArg(Str, Str + StrLen,
                                                         getLangOpts(),
                                                         Context.getTargetInfo());
}

//===--- CHECK: Warn on use of wrong absolute value function. -------------===//

// Returns the related absolute value function that is larger, of 0 if one
// does not exist.
static unsigned getLargerAbsoluteValueFunction(unsigned AbsFunction) {
  switch (AbsFunction) {
  default:
    return 0;

  case Builtin::BI__builtin_abs:
    return Builtin::BI__builtin_labs;
  case Builtin::BI__builtin_labs:
    return Builtin::BI__builtin_llabs;
  case Builtin::BI__builtin_llabs:
    return 0;

  case Builtin::BI__builtin_fabsf:
    return Builtin::BI__builtin_fabs;
  case Builtin::BI__builtin_fabs:
    return Builtin::BI__builtin_fabsl;
  case Builtin::BI__builtin_fabsl:
    return 0;

  case Builtin::BI__builtin_cabsf:
    return Builtin::BI__builtin_cabs;
  case Builtin::BI__builtin_cabs:
    return Builtin::BI__builtin_cabsl;
  case Builtin::BI__builtin_cabsl:
    return 0;

  case Builtin::BIabs:
    return Builtin::BIlabs;
  case Builtin::BIlabs:
    return Builtin::BIllabs;
  case Builtin::BIllabs:
    return 0;

  case Builtin::BIfabsf:
    return Builtin::BIfabs;
  case Builtin::BIfabs:
    return Builtin::BIfabsl;
  case Builtin::BIfabsl:
    return 0;

  case Builtin::BIcabsf:
   return Builtin::BIcabs;
  case Builtin::BIcabs:
    return Builtin::BIcabsl;
  case Builtin::BIcabsl:
    return 0;
  }
}

// Returns the argument type of the absolute value function.
static QualType getAbsoluteValueArgumentType(ASTContext &Context,
                                             unsigned AbsType) {
  if (AbsType == 0)
    return QualType();

  ASTContext::GetBuiltinTypeError Error = ASTContext::GE_None;
  QualType BuiltinType = Context.GetBuiltinType(AbsType, Error);
  if (Error != ASTContext::GE_None)
    return QualType();

  const FunctionProtoType *FT = BuiltinType->getAs<FunctionProtoType>();
  if (!FT)
    return QualType();

  if (FT->getNumParams() != 1)
    return QualType();

  return FT->getParamType(0);
}

// Returns the best absolute value function, or zero, based on type and
// current absolute value function.
static unsigned getBestAbsFunction(ASTContext &Context, QualType ArgType,
                                   unsigned AbsFunctionKind) {
  unsigned BestKind = 0;
  uint64_t ArgSize = Context.getTypeSize(ArgType);
  for (unsigned Kind = AbsFunctionKind; Kind != 0;
       Kind = getLargerAbsoluteValueFunction(Kind)) {
    QualType ParamType = getAbsoluteValueArgumentType(Context, Kind);
    if (Context.getTypeSize(ParamType) >= ArgSize) {
      if (BestKind == 0)
        BestKind = Kind;
      else if (Context.hasSameType(ParamType, ArgType)) {
        BestKind = Kind;
        break;
      }
    }
  }
  return BestKind;
}

enum AbsoluteValueKind {
  AVK_Integer,
  AVK_Floating,
  AVK_Complex
};

static AbsoluteValueKind getAbsoluteValueKind(QualType T) {
  if (T->isIntegralOrEnumerationType())
    return AVK_Integer;
  if (T->isRealFloatingType())
    return AVK_Floating;
  if (T->isAnyComplexType())
    return AVK_Complex;

  llvm_unreachable("Type not integer, floating, or complex");
}

// Changes the absolute value function to a different type.  Preserves whether
// the function is a builtin.
static unsigned changeAbsFunction(unsigned AbsKind,
                                  AbsoluteValueKind ValueKind) {
  switch (ValueKind) {
  case AVK_Integer:
    switch (AbsKind) {
    default:
      return 0;
    case Builtin::BI__builtin_fabsf:
    case Builtin::BI__builtin_fabs:
    case Builtin::BI__builtin_fabsl:
    case Builtin::BI__builtin_cabsf:
    case Builtin::BI__builtin_cabs:
    case Builtin::BI__builtin_cabsl:
      return Builtin::BI__builtin_abs;
    case Builtin::BIfabsf:
    case Builtin::BIfabs:
    case Builtin::BIfabsl:
    case Builtin::BIcabsf:
    case Builtin::BIcabs:
    case Builtin::BIcabsl:
      return Builtin::BIabs;
    }
  case AVK_Floating:
    switch (AbsKind) {
    default:
      return 0;
    case Builtin::BI__builtin_abs:
    case Builtin::BI__builtin_labs:
    case Builtin::BI__builtin_llabs:
    case Builtin::BI__builtin_cabsf:
    case Builtin::BI__builtin_cabs:
    case Builtin::BI__builtin_cabsl:
      return Builtin::BI__builtin_fabsf;
    case Builtin::BIabs:
    case Builtin::BIlabs:
    case Builtin::BIllabs:
    case Builtin::BIcabsf:
    case Builtin::BIcabs:
    case Builtin::BIcabsl:
      return Builtin::BIfabsf;
    }
  case AVK_Complex:
    switch (AbsKind) {
    default:
      return 0;
    case Builtin::BI__builtin_abs:
    case Builtin::BI__builtin_labs:
    case Builtin::BI__builtin_llabs:
    case Builtin::BI__builtin_fabsf:
    case Builtin::BI__builtin_fabs:
    case Builtin::BI__builtin_fabsl:
      return Builtin::BI__builtin_cabsf;
    case Builtin::BIabs:
    case Builtin::BIlabs:
    case Builtin::BIllabs:
    case Builtin::BIfabsf:
    case Builtin::BIfabs:
    case Builtin::BIfabsl:
      return Builtin::BIcabsf;
    }
  }
  llvm_unreachable("Unable to convert function");
}

static unsigned getAbsoluteValueFunctionKind(const FunctionDecl *FDecl) {
  const IdentifierInfo *FnInfo = FDecl->getIdentifier();
  if (!FnInfo)
    return 0;

  switch (FDecl->getBuiltinID()) {
  default:
    return 0;
  case Builtin::BI__builtin_abs:
  case Builtin::BI__builtin_fabs:
  case Builtin::BI__builtin_fabsf:
  case Builtin::BI__builtin_fabsl:
  case Builtin::BI__builtin_labs:
  case Builtin::BI__builtin_llabs:
  case Builtin::BI__builtin_cabs:
  case Builtin::BI__builtin_cabsf:
  case Builtin::BI__builtin_cabsl:
  case Builtin::BIabs:
  case Builtin::BIlabs:
  case Builtin::BIllabs:
  case Builtin::BIfabs:
  case Builtin::BIfabsf:
  case Builtin::BIfabsl:
  case Builtin::BIcabs:
  case Builtin::BIcabsf:
  case Builtin::BIcabsl:
    return FDecl->getBuiltinID();
  }
  llvm_unreachable("Unknown Builtin type");
}

// If the replacement is valid, emit a note with replacement function.
// Additionally, suggest including the proper header if not already included.
static void emitReplacement(Sema &S, SourceLocation Loc, SourceRange Range,
                            unsigned AbsKind, QualType ArgType) {
  bool EmitHeaderHint = true;
  const char *HeaderName = nullptr;
  std::string FunctionName;
  if (S.getLangOpts().CPlusPlus && !ArgType->isAnyComplexType()) {
    FunctionName = "std::abs";
    if (ArgType->isIntegralOrEnumerationType()) {
      HeaderName = "cstdlib";
    } else if (ArgType->isRealFloatingType()) {
      HeaderName = "cmath";
    } else {
      llvm_unreachable("Invalid Type");
    }

    // Lookup all std::abs
    if (NamespaceDecl *Std = S.getStdNamespace()) {
      LookupResult R(S, &S.Context.Idents.get("abs"), Loc, Sema::LookupAnyName);
      R.suppressDiagnostics();
      S.LookupQualifiedName(R, Std);

      for (const auto *I : R) {
        const FunctionDecl *FDecl = nullptr;
        if (const UsingShadowDecl *UsingD = dyn_cast<UsingShadowDecl>(I)) {
          FDecl = dyn_cast<FunctionDecl>(UsingD->getTargetDecl());
        } else {
          FDecl = dyn_cast<FunctionDecl>(I);
        }
        if (!FDecl)
          continue;

        // Found std::abs(), check that they are the right ones.
        if (FDecl->getNumParams() != 1)
          continue;

        // Check that the parameter type can handle the argument.
        QualType ParamType = FDecl->getParamDecl(0)->getType();
        if (getAbsoluteValueKind(ArgType) == getAbsoluteValueKind(ParamType) &&
            S.Context.getTypeSize(ArgType) <=
                S.Context.getTypeSize(ParamType)) {
          // Found a function, don't need the header hint.
          EmitHeaderHint = false;
          break;
        }
      }
    }
  } else {
    FunctionName = S.Context.BuiltinInfo.getName(AbsKind);
    HeaderName = S.Context.BuiltinInfo.getHeaderName(AbsKind);

    if (HeaderName) {
      DeclarationName DN(&S.Context.Idents.get(FunctionName));
      LookupResult R(S, DN, Loc, Sema::LookupAnyName);
      R.suppressDiagnostics();
      S.LookupName(R, S.getCurScope());

      if (R.isSingleResult()) {
        FunctionDecl *FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
        if (FD && FD->getBuiltinID() == AbsKind) {
          EmitHeaderHint = false;
        } else {
          return;
        }
      } else if (!R.empty()) {
        return;
      }
    }
  }

  S.Diag(Loc, diag::note_replace_abs_function)
      << FunctionName << FixItHint::CreateReplacement(Range, FunctionName);

  if (!HeaderName)
    return;

  if (!EmitHeaderHint)
    return;

  S.Diag(Loc, diag::note_include_header_or_declare) << HeaderName
                                                    << FunctionName;
}

template <std::size_t StrLen>
static bool IsStdFunction(const FunctionDecl *FDecl,
                          const char (&Str)[StrLen]) {
  if (!FDecl)
    return false;
  if (!FDecl->getIdentifier() || !FDecl->getIdentifier()->isStr(Str))
    return false;
  if (!FDecl->isInStdNamespace())
    return false;

  return true;
}

enum class MathCheck { NaN, Inf };
static bool IsInfOrNanFunction(StringRef calleeName, MathCheck Check) {
  auto MatchesAny = [&](std::initializer_list<llvm::StringRef> names) {
    return llvm::is_contained(names, calleeName);
  };

  switch (Check) {
  case MathCheck::NaN:
    return MatchesAny({"__builtin_nan", "__builtin_nanf", "__builtin_nanl",
                       "__builtin_nanf16", "__builtin_nanf128"});
  case MathCheck::Inf:
    return MatchesAny({"__builtin_inf", "__builtin_inff", "__builtin_infl",
                       "__builtin_inff16", "__builtin_inff128"});
  }
  llvm_unreachable("unknown MathCheck");
}

static bool IsInfinityFunction(const FunctionDecl *FDecl) {
  if (FDecl->getName() != "infinity")
    return false;

  if (const CXXMethodDecl *MDecl = dyn_cast<CXXMethodDecl>(FDecl)) {
    const CXXRecordDecl *RDecl = MDecl->getParent();
    if (RDecl->getName() != "numeric_limits")
      return false;

    if (const NamespaceDecl *NSDecl =
            dyn_cast<NamespaceDecl>(RDecl->getDeclContext()))
      return NSDecl->isStdNamespace();
  }

  return false;
}

void Sema::CheckInfNaNFunction(const CallExpr *Call,
                               const FunctionDecl *FDecl) {
  if (!FDecl->getIdentifier())
    return;

  FPOptions FPO = Call->getFPFeaturesInEffect(getLangOpts());
  if (FPO.getNoHonorNaNs() &&
      (IsStdFunction(FDecl, "isnan") || IsStdFunction(FDecl, "isunordered") ||
       IsInfOrNanFunction(FDecl->getName(), MathCheck::NaN))) {
    Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
        << 1 << 0 << Call->getSourceRange();
    return;
  }

  if (FPO.getNoHonorInfs() &&
      (IsStdFunction(FDecl, "isinf") || IsStdFunction(FDecl, "isfinite") ||
       IsInfinityFunction(FDecl) ||
       IsInfOrNanFunction(FDecl->getName(), MathCheck::Inf))) {
    Diag(Call->getBeginLoc(), diag::warn_fp_nan_inf_when_disabled)
        << 0 << 0 << Call->getSourceRange();
  }
}

void Sema::CheckAbsoluteValueFunction(const CallExpr *Call,
                                      const FunctionDecl *FDecl) {
  if (Call->getNumArgs() != 1)
    return;

  unsigned AbsKind = getAbsoluteValueFunctionKind(FDecl);
  bool IsStdAbs = IsStdFunction(FDecl, "abs");
  if (AbsKind == 0 && !IsStdAbs)
    return;

  QualType ArgType = Call->getArg(0)->IgnoreParenImpCasts()->getType();
  QualType ParamType = Call->getArg(0)->getType();

  // Unsigned types cannot be negative.  Suggest removing the absolute value
  // function call.
  if (ArgType->isUnsignedIntegerType()) {
    std::string FunctionName =
        IsStdAbs ? "std::abs" : Context.BuiltinInfo.getName(AbsKind);
    Diag(Call->getExprLoc(), diag::warn_unsigned_abs) << ArgType << ParamType;
    Diag(Call->getExprLoc(), diag::note_remove_abs)
        << FunctionName
        << FixItHint::CreateRemoval(Call->getCallee()->getSourceRange());
    return;
  }

  // Taking the absolute value of a pointer is very suspicious, they probably
  // wanted to index into an array, dereference a pointer, call a function, etc.
  if (ArgType->isPointerType() || ArgType->canDecayToPointerType()) {
    unsigned DiagType = 0;
    if (ArgType->isFunctionType())
      DiagType = 1;
    else if (ArgType->isArrayType())
      DiagType = 2;

    Diag(Call->getExprLoc(), diag::warn_pointer_abs) << DiagType << ArgType;
    return;
  }

  // std::abs has overloads which prevent most of the absolute value problems
  // from occurring.
  if (IsStdAbs)
    return;

  AbsoluteValueKind ArgValueKind = getAbsoluteValueKind(ArgType);
  AbsoluteValueKind ParamValueKind = getAbsoluteValueKind(ParamType);

  // The argument and parameter are the same kind.  Check if they are the right
  // size.
  if (ArgValueKind == ParamValueKind) {
    if (Context.getTypeSize(ArgType) <= Context.getTypeSize(ParamType))
      return;

    unsigned NewAbsKind = getBestAbsFunction(Context, ArgType, AbsKind);
    Diag(Call->getExprLoc(), diag::warn_abs_too_small)
        << FDecl << ArgType << ParamType;

    if (NewAbsKind == 0)
      return;

    emitReplacement(*this, Call->getExprLoc(),
                    Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
    return;
  }

  // ArgValueKind != ParamValueKind
  // The wrong type of absolute value function was used.  Attempt to find the
  // proper one.
  unsigned NewAbsKind = changeAbsFunction(AbsKind, ArgValueKind);
  NewAbsKind = getBestAbsFunction(Context, ArgType, NewAbsKind);
  if (NewAbsKind == 0)
    return;

  Diag(Call->getExprLoc(), diag::warn_wrong_absolute_value_type)
      << FDecl << ParamValueKind << ArgValueKind;

  emitReplacement(*this, Call->getExprLoc(),
                  Call->getCallee()->getSourceRange(), NewAbsKind, ArgType);
}

//===--- CHECK: Warn on use of std::max and unsigned zero. r---------------===//
void Sema::CheckMaxUnsignedZero(const CallExpr *Call,
                                const FunctionDecl *FDecl) {
  if (!Call || !FDecl) return;

  // Ignore template specializations and macros.
  if (inTemplateInstantiation()) return;
  if (Call->getExprLoc().isMacroID()) return;

  // Only care about the one template argument, two function parameter std::max
  if (Call->getNumArgs() != 2) return;
  if (!IsStdFunction(FDecl, "max")) return;
  const auto * ArgList = FDecl->getTemplateSpecializationArgs();
  if (!ArgList) return;
  if (ArgList->size() != 1) return;

  // Check that template type argument is unsigned integer.
  const auto& TA = ArgList->get(0);
  if (TA.getKind() != TemplateArgument::Type) return;
  QualType ArgType = TA.getAsType();
  if (!ArgType->isUnsignedIntegerType()) return;

  // See if either argument is a literal zero.
  auto IsLiteralZeroArg = [](const Expr* E) -> bool {
    const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E);
    if (!MTE) return false;
    const auto *Num = dyn_cast<IntegerLiteral>(MTE->getSubExpr());
    if (!Num) return false;
    if (Num->getValue() != 0) return false;
    return true;
  };

  const Expr *FirstArg = Call->getArg(0);
  const Expr *SecondArg = Call->getArg(1);
  const bool IsFirstArgZero = IsLiteralZeroArg(FirstArg);
  const bool IsSecondArgZero = IsLiteralZeroArg(SecondArg);

  // Only warn when exactly one argument is zero.
  if (IsFirstArgZero == IsSecondArgZero) return;

  SourceRange FirstRange = FirstArg->getSourceRange();
  SourceRange SecondRange = SecondArg->getSourceRange();

  SourceRange ZeroRange = IsFirstArgZero ? FirstRange : SecondRange;

  Diag(Call->getExprLoc(), diag::warn_max_unsigned_zero)
      << IsFirstArgZero << Call->getCallee()->getSourceRange() << ZeroRange;

  // Deduce what parts to remove so that "std::max(0u, foo)" becomes "(foo)".
  SourceRange RemovalRange;
  if (IsFirstArgZero) {
    RemovalRange = SourceRange(FirstRange.getBegin(),
                               SecondRange.getBegin().getLocWithOffset(-1));
  } else {
    RemovalRange = SourceRange(getLocForEndOfToken(FirstRange.getEnd()),
                               SecondRange.getEnd());
  }

  Diag(Call->getExprLoc(), diag::note_remove_max_call)
        << FixItHint::CreateRemoval(Call->getCallee()->getSourceRange())
        << FixItHint::CreateRemoval(RemovalRange);
}

//===--- CHECK: Standard memory functions ---------------------------------===//

/// Takes the expression passed to the size_t parameter of functions
/// such as memcmp, strncat, etc and warns if it's a comparison.
///
/// This is to catch typos like `if (memcmp(&a, &b, sizeof(a) > 0))`.
static bool CheckMemorySizeofForComparison(Sema &S, const Expr *E,
                                           const IdentifierInfo *FnName,
                                           SourceLocation FnLoc,
                                           SourceLocation RParenLoc) {
  const auto *Size = dyn_cast<BinaryOperator>(E);
  if (!Size)
    return false;

  // if E is binop and op is <=>, >, <, >=, <=, ==, &&, ||:
  if (!Size->isComparisonOp() && !Size->isLogicalOp())
    return false;

  SourceRange SizeRange = Size->getSourceRange();
  S.Diag(Size->getOperatorLoc(), diag::warn_memsize_comparison)
      << SizeRange << FnName;
  S.Diag(FnLoc, diag::note_memsize_comparison_paren)
      << FnName
      << FixItHint::CreateInsertion(
             S.getLocForEndOfToken(Size->getLHS()->getEndLoc()), ")")
      << FixItHint::CreateRemoval(RParenLoc);
  S.Diag(SizeRange.getBegin(), diag::note_memsize_comparison_cast_silence)
      << FixItHint::CreateInsertion(SizeRange.getBegin(), "(size_t)(")
      << FixItHint::CreateInsertion(S.getLocForEndOfToken(SizeRange.getEnd()),
                                    ")");

  return true;
}

/// Determine whether the given type is or contains a dynamic class type
/// (e.g., whether it has a vtable).
static const CXXRecordDecl *getContainedDynamicClass(QualType T,
                                                     bool &IsContained) {
  // Look through array types while ignoring qualifiers.
  const Type *Ty = T->getBaseElementTypeUnsafe();
  IsContained = false;

  const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
  RD = RD ? RD->getDefinition() : nullptr;
  if (!RD || RD->isInvalidDecl())
    return nullptr;

  if (RD->isDynamicClass())
    return RD;

  // Check all the fields.  If any bases were dynamic, the class is dynamic.
  // It's impossible for a class to transitively contain itself by value, so
  // infinite recursion is impossible.
  for (auto *FD : RD->fields()) {
    bool SubContained;
    if (const CXXRecordDecl *ContainedRD =
            getContainedDynamicClass(FD->getType(), SubContained)) {
      IsContained = true;
      return ContainedRD;
    }
  }

  return nullptr;
}

static const UnaryExprOrTypeTraitExpr *getAsSizeOfExpr(const Expr *E) {
  if (const auto *Unary = dyn_cast<UnaryExprOrTypeTraitExpr>(E))
    if (Unary->getKind() == UETT_SizeOf)
      return Unary;
  return nullptr;
}

/// If E is a sizeof expression, returns its argument expression,
/// otherwise returns NULL.
static const Expr *getSizeOfExprArg(const Expr *E) {
  if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E))
    if (!SizeOf->isArgumentType())
      return SizeOf->getArgumentExpr()->IgnoreParenImpCasts();
  return nullptr;
}

/// If E is a sizeof expression, returns its argument type.
static QualType getSizeOfArgType(const Expr *E) {
  if (const UnaryExprOrTypeTraitExpr *SizeOf = getAsSizeOfExpr(E))
    return SizeOf->getTypeOfArgument();
  return QualType();
}

namespace {

struct SearchNonTrivialToInitializeField
    : DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField> {
  using Super =
      DefaultInitializedTypeVisitor<SearchNonTrivialToInitializeField>;

  SearchNonTrivialToInitializeField(const Expr *E, Sema &S) : E(E), S(S) {}

  void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
                     SourceLocation SL) {
    if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
      asDerived().visitArray(PDIK, AT, SL);
      return;
    }

    Super::visitWithKind(PDIK, FT, SL);
  }

  void visitARCStrong(QualType FT, SourceLocation SL) {
    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
  }
  void visitARCWeak(QualType FT, SourceLocation SL) {
    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 1);
  }
  void visitStruct(QualType FT, SourceLocation SL) {
    for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
      visit(FD->getType(), FD->getLocation());
  }
  void visitArray(QualType::PrimitiveDefaultInitializeKind PDIK,
                  const ArrayType *AT, SourceLocation SL) {
    visit(getContext().getBaseElementType(AT), SL);
  }
  void visitTrivial(QualType FT, SourceLocation SL) {}

  static void diag(QualType RT, const Expr *E, Sema &S) {
    SearchNonTrivialToInitializeField(E, S).visitStruct(RT, SourceLocation());
  }

  ASTContext &getContext() { return S.getASTContext(); }

  const Expr *E;
  Sema &S;
};

struct SearchNonTrivialToCopyField
    : CopiedTypeVisitor<SearchNonTrivialToCopyField, false> {
  using Super = CopiedTypeVisitor<SearchNonTrivialToCopyField, false>;

  SearchNonTrivialToCopyField(const Expr *E, Sema &S) : E(E), S(S) {}

  void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
                     SourceLocation SL) {
    if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
      asDerived().visitArray(PCK, AT, SL);
      return;
    }

    Super::visitWithKind(PCK, FT, SL);
  }

  void visitARCStrong(QualType FT, SourceLocation SL) {
    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
  }
  void visitARCWeak(QualType FT, SourceLocation SL) {
    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
  }
  void visitPtrAuth(QualType FT, SourceLocation SL) {
    S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
  }
  void visitStruct(QualType FT, SourceLocation SL) {
    for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
      visit(FD->getType(), FD->getLocation());
  }
  void visitArray(QualType::PrimitiveCopyKind PCK, const ArrayType *AT,
                  SourceLocation SL) {
    visit(getContext().getBaseElementType(AT), SL);
  }
  void preVisit(QualType::PrimitiveCopyKind PCK, QualType FT,
                SourceLocation SL) {}
  void visitTrivial(QualType FT, SourceLocation SL) {}
  void visitVolatileTrivial(QualType FT, SourceLocation SL) {}

  static void diag(QualType RT, const Expr *E, Sema &S) {
    SearchNonTrivialToCopyField(E, S).visitStruct(RT, SourceLocation());
  }

  ASTContext &getContext() { return S.getASTContext(); }

  const Expr *E;
  Sema &S;
};

}

/// Detect if \c SizeofExpr is likely to calculate the sizeof an object.
static bool doesExprLikelyComputeSize(const Expr *SizeofExpr) {
  SizeofExpr = SizeofExpr->IgnoreParenImpCasts();

  if (const auto *BO = dyn_cast<BinaryOperator>(SizeofExpr)) {
    if (BO->getOpcode() != BO_Mul && BO->getOpcode() != BO_Add)
      return false;

    return doesExprLikelyComputeSize(BO->getLHS()) ||
           doesExprLikelyComputeSize(BO->getRHS());
  }

  return getAsSizeOfExpr(SizeofExpr) != nullptr;
}

/// Check if the ArgLoc originated from a macro passed to the call at CallLoc.
///
/// \code
///   #define MACRO 0
///   foo(MACRO);
///   foo(0);
/// \endcode
///
/// This should return true for the first call to foo, but not for the second
/// (regardless of whether foo is a macro or function).
static bool isArgumentExpandedFromMacro(SourceManager &SM,
                                        SourceLocation CallLoc,
                                        SourceLocation ArgLoc) {
  if (!CallLoc.isMacroID())
    return SM.getFileID(CallLoc) != SM.getFileID(ArgLoc);

  return SM.getFileID(SM.getImmediateMacroCallerLoc(CallLoc)) !=
         SM.getFileID(SM.getImmediateMacroCallerLoc(ArgLoc));
}

/// Diagnose cases like 'memset(buf, sizeof(buf), 0)', which should have the
/// last two arguments transposed.
static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call) {
  if (BId != Builtin::BImemset && BId != Builtin::BIbzero)
    return;

  const Expr *SizeArg =
    Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts();

  auto isLiteralZero = [](const Expr *E) {
    return (isa<IntegerLiteral>(E) &&
            cast<IntegerLiteral>(E)->getValue() == 0) ||
           (isa<CharacterLiteral>(E) &&
            cast<CharacterLiteral>(E)->getValue() == 0);
  };

  // If we're memsetting or bzeroing 0 bytes, then this is likely an error.
  SourceLocation CallLoc = Call->getRParenLoc();
  SourceManager &SM = S.getSourceManager();
  if (isLiteralZero(SizeArg) &&
      !isArgumentExpandedFromMacro(SM, CallLoc, SizeArg->getExprLoc())) {

    SourceLocation DiagLoc = SizeArg->getExprLoc();

    // Some platforms #define bzero to __builtin_memset. See if this is the
    // case, and if so, emit a better diagnostic.
    if (BId == Builtin::BIbzero ||
        (CallLoc.isMacroID() && Lexer::getImmediateMacroName(
                                    CallLoc, SM, S.getLangOpts()) == "bzero")) {
      S.Diag(DiagLoc, diag::warn_suspicious_bzero_size);
      S.Diag(DiagLoc, diag::note_suspicious_bzero_size_silence);
    } else if (!isLiteralZero(Call->getArg(1)->IgnoreImpCasts())) {
      S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 0;
      S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 0;
    }
    return;
  }

  // If the second argument to a memset is a sizeof expression and the third
  // isn't, this is also likely an error. This should catch
  // 'memset(buf, sizeof(buf), 0xff)'.
  if (BId == Builtin::BImemset &&
      doesExprLikelyComputeSize(Call->getArg(1)) &&
      !doesExprLikelyComputeSize(Call->getArg(2))) {
    SourceLocation DiagLoc = Call->getArg(1)->getExprLoc();
    S.Diag(DiagLoc, diag::warn_suspicious_sizeof_memset) << 1;
    S.Diag(DiagLoc, diag::note_suspicious_sizeof_memset_silence) << 1;
    return;
  }
}

void Sema::CheckMemaccessArguments(const CallExpr *Call,
                                   unsigned BId,
                                   IdentifierInfo *FnName) {
  assert(BId != 0);

  // It is possible to have a non-standard definition of memset.  Validate
  // we have enough arguments, and if not, abort further checking.
  unsigned ExpectedNumArgs =
      (BId == Builtin::BIstrndup || BId == Builtin::BIbzero ? 2 : 3);
  if (Call->getNumArgs() < ExpectedNumArgs)
    return;

  unsigned LastArg = (BId == Builtin::BImemset || BId == Builtin::BIbzero ||
                      BId == Builtin::BIstrndup ? 1 : 2);
  unsigned LenArg =
      (BId == Builtin::BIbzero || BId == Builtin::BIstrndup ? 1 : 2);
  const Expr *LenExpr = Call->getArg(LenArg)->IgnoreParenImpCasts();

  if (CheckMemorySizeofForComparison(*this, LenExpr, FnName,
                                     Call->getBeginLoc(), Call->getRParenLoc()))
    return;

  // Catch cases like 'memset(buf, sizeof(buf), 0)'.
  CheckMemaccessSize(*this, BId, Call);

  // We have special checking when the length is a sizeof expression.
  QualType SizeOfArgTy = getSizeOfArgType(LenExpr);
  const Expr *SizeOfArg = getSizeOfExprArg(LenExpr);
  llvm::FoldingSetNodeID SizeOfArgID;

  // Although widely used, 'bzero' is not a standard function. Be more strict
  // with the argument types before allowing diagnostics and only allow the
  // form bzero(ptr, sizeof(...)).
  QualType FirstArgTy = Call->getArg(0)->IgnoreParenImpCasts()->getType();
  if (BId == Builtin::BIbzero && !FirstArgTy->getAs<PointerType>())
    return;

  for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) {
    const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts();
    SourceRange ArgRange = Call->getArg(ArgIdx)->getSourceRange();

    QualType DestTy = Dest->getType();
    QualType PointeeTy;
    if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
      PointeeTy = DestPtrTy->getPointeeType();

      // Never warn about void type pointers. This can be used to suppress
      // false positives.
      if (PointeeTy->isVoidType())
        continue;

      // Catch "memset(p, 0, sizeof(p))" -- needs to be sizeof(*p). Do this by
      // actually comparing the expressions for equality. Because computing the
      // expression IDs can be expensive, we only do this if the diagnostic is
      // enabled.
      if (SizeOfArg &&
          !Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess,
                           SizeOfArg->getExprLoc())) {
        // We only compute IDs for expressions if the warning is enabled, and
        // cache the sizeof arg's ID.
        if (SizeOfArgID == llvm::FoldingSetNodeID())
          SizeOfArg->Profile(SizeOfArgID, Context, true);
        llvm::FoldingSetNodeID DestID;
        Dest->Profile(DestID, Context, true);
        if (DestID == SizeOfArgID) {
          // TODO: For strncpy() and friends, this could suggest sizeof(dst)
          //       over sizeof(src) as well.
          unsigned ActionIdx = 0; // Default is to suggest dereferencing.
          StringRef ReadableName = FnName->getName();

          if (const UnaryOperator *UnaryOp = dyn_cast<UnaryOperator>(Dest))
            if (UnaryOp->getOpcode() == UO_AddrOf)
              ActionIdx = 1; // If its an address-of operator, just remove it.
          if (!PointeeTy->isIncompleteType() &&
              (Context.getTypeSize(PointeeTy) == Context.getCharWidth()))
            ActionIdx = 2; // If the pointee's size is sizeof(char),
                           // suggest an explicit length.

          // If the function is defined as a builtin macro, do not show macro
          // expansion.
          SourceLocation SL = SizeOfArg->getExprLoc();
          SourceRange DSR = Dest->getSourceRange();
          SourceRange SSR = SizeOfArg->getSourceRange();
          SourceManager &SM = getSourceManager();

          if (SM.isMacroArgExpansion(SL)) {
            ReadableName = Lexer::getImmediateMacroName(SL, SM, LangOpts);
            SL = SM.getSpellingLoc(SL);
            DSR = SourceRange(SM.getSpellingLoc(DSR.getBegin()),
                             SM.getSpellingLoc(DSR.getEnd()));
            SSR = SourceRange(SM.getSpellingLoc(SSR.getBegin()),
                             SM.getSpellingLoc(SSR.getEnd()));
          }

          DiagRuntimeBehavior(SL, SizeOfArg,
                              PDiag(diag::warn_sizeof_pointer_expr_memaccess)
                                << ReadableName
                                << PointeeTy
                                << DestTy
                                << DSR
                                << SSR);
          DiagRuntimeBehavior(SL, SizeOfArg,
                         PDiag(diag::warn_sizeof_pointer_expr_memaccess_note)
                                << ActionIdx
                                << SSR);

          break;
        }
      }

      // Also check for cases where the sizeof argument is the exact same
      // type as the memory argument, and where it points to a user-defined
      // record type.
      if (SizeOfArgTy != QualType()) {
        if (PointeeTy->isRecordType() &&
            Context.typesAreCompatible(SizeOfArgTy, DestTy)) {
          DiagRuntimeBehavior(LenExpr->getExprLoc(), Dest,
                              PDiag(diag::warn_sizeof_pointer_type_memaccess)
                                << FnName << SizeOfArgTy << ArgIdx
                                << PointeeTy << Dest->getSourceRange()
                                << LenExpr->getSourceRange());
          break;
        }
      }
    } else if (DestTy->isArrayType()) {
      PointeeTy = DestTy;
    }

    if (PointeeTy == QualType())
      continue;

    // Always complain about dynamic classes.
    bool IsContained;
    if (const CXXRecordDecl *ContainedRD =
            getContainedDynamicClass(PointeeTy, IsContained)) {

      unsigned OperationType = 0;
      const bool IsCmp = BId == Builtin::BImemcmp || BId == Builtin::BIbcmp;
      // "overwritten" if we're warning about the destination for any call
      // but memcmp; otherwise a verb appropriate to the call.
      if (ArgIdx != 0 || IsCmp) {
        if (BId == Builtin::BImemcpy)
          OperationType = 1;
        else if(BId == Builtin::BImemmove)
          OperationType = 2;
        else if (IsCmp)
          OperationType = 3;
      }

      DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
                          PDiag(diag::warn_dyn_class_memaccess)
                              << (IsCmp ? ArgIdx + 2 : ArgIdx) << FnName
                              << IsContained << ContainedRD << OperationType
                              << Call->getCallee()->getSourceRange());
    } else if (PointeeTy.hasNonTrivialObjCLifetime() &&
             BId != Builtin::BImemset)
      DiagRuntimeBehavior(
        Dest->getExprLoc(), Dest,
        PDiag(diag::warn_arc_object_memaccess)
          << ArgIdx << FnName << PointeeTy
          << Call->getCallee()->getSourceRange());
    else if (const auto *RT = PointeeTy->getAs<RecordType>()) {

      // FIXME: Do not consider incomplete types even though they may be
      // completed later. GCC does not diagnose such code, but we may want to
      // consider diagnosing it in the future, perhaps under a different, but
      // related, diagnostic group.
      bool NonTriviallyCopyableCXXRecord =
          getLangOpts().CPlusPlus && !RT->isIncompleteType() &&
          !RT->desugar().isTriviallyCopyableType(Context);

      if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
          RT->getDecl()->isNonTrivialToPrimitiveDefaultInitialize()) {
        DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
                            PDiag(diag::warn_cstruct_memaccess)
                                << ArgIdx << FnName << PointeeTy << 0);
        SearchNonTrivialToInitializeField::diag(PointeeTy, Dest, *this);
      } else if ((BId == Builtin::BImemset || BId == Builtin::BIbzero) &&
                 NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
        // FIXME: Limiting this warning to dest argument until we decide
        // whether it's valid for source argument too.
        DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
                            PDiag(diag::warn_cxxstruct_memaccess)
                                << FnName << PointeeTy);
      } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
                 RT->getDecl()->isNonTrivialToPrimitiveCopy()) {
        DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
                            PDiag(diag::warn_cstruct_memaccess)
                                << ArgIdx << FnName << PointeeTy << 1);
        SearchNonTrivialToCopyField::diag(PointeeTy, Dest, *this);
      } else if ((BId == Builtin::BImemcpy || BId == Builtin::BImemmove) &&
                 NonTriviallyCopyableCXXRecord && ArgIdx == 0) {
        // FIXME: Limiting this warning to dest argument until we decide
        // whether it's valid for source argument too.
        DiagRuntimeBehavior(Dest->getExprLoc(), Dest,
                            PDiag(diag::warn_cxxstruct_memaccess)
                                << FnName << PointeeTy);
      } else {
        continue;
      }
    } else
      continue;

    DiagRuntimeBehavior(
      Dest->getExprLoc(), Dest,
      PDiag(diag::note_bad_memaccess_silence)
        << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)"));
    break;
  }
}

// A little helper routine: ignore addition and subtraction of integer literals.
// This intentionally does not ignore all integer constant expressions because
// we don't want to remove sizeof().
static const Expr *ignoreLiteralAdditions(const Expr *Ex, ASTContext &Ctx) {
  Ex = Ex->IgnoreParenCasts();

  while (true) {
    const BinaryOperator * BO = dyn_cast<BinaryOperator>(Ex);
    if (!BO || !BO->isAdditiveOp())
      break;

    const Expr *RHS = BO->getRHS()->IgnoreParenCasts();
    const Expr *LHS = BO->getLHS()->IgnoreParenCasts();

    if (isa<IntegerLiteral>(RHS))
      Ex = LHS;
    else if (isa<IntegerLiteral>(LHS))
      Ex = RHS;
    else
      break;
  }

  return Ex;
}

static bool isConstantSizeArrayWithMoreThanOneElement(QualType Ty,
                                                      ASTContext &Context) {
  // Only handle constant-sized or VLAs, but not flexible members.
  if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(Ty)) {
    // Only issue the FIXIT for arrays of size > 1.
    if (CAT->getZExtSize() <= 1)
      return false;
  } else if (!Ty->isVariableArrayType()) {
    return false;
  }
  return true;
}

void Sema::CheckStrlcpycatArguments(const CallExpr *Call,
                                    IdentifierInfo *FnName) {

  // Don't crash if the user has the wrong number of arguments
  unsigned NumArgs = Call->getNumArgs();
  if ((NumArgs != 3) && (NumArgs != 4))
    return;

  const Expr *SrcArg = ignoreLiteralAdditions(Call->getArg(1), Context);
  const Expr *SizeArg = ignoreLiteralAdditions(Call->getArg(2), Context);
  const Expr *CompareWithSrc = nullptr;

  if (CheckMemorySizeofForComparison(*this, SizeArg, FnName,
                                     Call->getBeginLoc(), Call->getRParenLoc()))
    return;

  // Look for 'strlcpy(dst, x, sizeof(x))'
  if (const Expr *Ex = getSizeOfExprArg(SizeArg))
    CompareWithSrc = Ex;
  else {
    // Look for 'strlcpy(dst, x, strlen(x))'
    if (const CallExpr *SizeCall = dyn_cast<CallExpr>(SizeArg)) {
      if (SizeCall->getBuiltinCallee() == Builtin::BIstrlen &&
          SizeCall->getNumArgs() == 1)
        CompareWithSrc = ignoreLiteralAdditions(SizeCall->getArg(0), Context);
    }
  }

  if (!CompareWithSrc)
    return;

  // Determine if the argument to sizeof/strlen is equal to the source
  // argument.  In principle there's all kinds of things you could do
  // here, for instance creating an == expression and evaluating it with
  // EvaluateAsBooleanCondition, but this uses a more direct technique:
  const DeclRefExpr *SrcArgDRE = dyn_cast<DeclRefExpr>(SrcArg);
  if (!SrcArgDRE)
    return;

  const DeclRefExpr *CompareWithSrcDRE = dyn_cast<DeclRefExpr>(CompareWithSrc);
  if (!CompareWithSrcDRE ||
      SrcArgDRE->getDecl() != CompareWithSrcDRE->getDecl())
    return;

  const Expr *OriginalSizeArg = Call->getArg(2);
  Diag(CompareWithSrcDRE->getBeginLoc(), diag::warn_strlcpycat_wrong_size)
      << OriginalSizeArg->getSourceRange() << FnName;

  // Output a FIXIT hint if the destination is an array (rather than a
  // pointer to an array).  This could be enhanced to handle some
  // pointers if we know the actual size, like if DstArg is 'array+2'
  // we could say 'sizeof(array)-2'.
  const Expr *DstArg = Call->getArg(0)->IgnoreParenImpCasts();
  if (!isConstantSizeArrayWithMoreThanOneElement(DstArg->getType(), Context))
    return;

  SmallString<128> sizeString;
  llvm::raw_svector_ostream OS(sizeString);
  OS << "sizeof(";
  DstArg->printPretty(OS, nullptr, getPrintingPolicy());
  OS << ")";

  Diag(OriginalSizeArg->getBeginLoc(), diag::note_strlcpycat_wrong_size)
      << FixItHint::CreateReplacement(OriginalSizeArg->getSourceRange(),
                                      OS.str());
}

/// Check if two expressions refer to the same declaration.
static bool referToTheSameDecl(const Expr *E1, const Expr *E2) {
  if (const DeclRefExpr *D1 = dyn_cast_or_null<DeclRefExpr>(E1))
    if (const DeclRefExpr *D2 = dyn_cast_or_null<DeclRefExpr>(E2))
      return D1->getDecl() == D2->getDecl();
  return false;
}

static const Expr *getStrlenExprArg(const Expr *E) {
  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
    const FunctionDecl *FD = CE->getDirectCallee();
    if (!FD || FD->getMemoryFunctionKind() != Builtin::BIstrlen)
      return nullptr;
    return CE->getArg(0)->IgnoreParenCasts();
  }
  return nullptr;
}

void Sema::CheckStrncatArguments(const CallExpr *CE,
                                 const IdentifierInfo *FnName) {
  // Don't crash if the user has the wrong number of arguments.
  if (CE->getNumArgs() < 3)
    return;
  const Expr *DstArg = CE->getArg(0)->IgnoreParenCasts();
  const Expr *SrcArg = CE->getArg(1)->IgnoreParenCasts();
  const Expr *LenArg = CE->getArg(2)->IgnoreParenCasts();

  if (CheckMemorySizeofForComparison(*this, LenArg, FnName, CE->getBeginLoc(),
                                     CE->getRParenLoc()))
    return;

  // Identify common expressions, which are wrongly used as the size argument
  // to strncat and may lead to buffer overflows.
  unsigned PatternType = 0;
  if (const Expr *SizeOfArg = getSizeOfExprArg(LenArg)) {
    // - sizeof(dst)
    if (referToTheSameDecl(SizeOfArg, DstArg))
      PatternType = 1;
    // - sizeof(src)
    else if (referToTheSameDecl(SizeOfArg, SrcArg))
      PatternType = 2;
  } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(LenArg)) {
    if (BE->getOpcode() == BO_Sub) {
      const Expr *L = BE->getLHS()->IgnoreParenCasts();
      const Expr *R = BE->getRHS()->IgnoreParenCasts();
      // - sizeof(dst) - strlen(dst)
      if (referToTheSameDecl(DstArg, getSizeOfExprArg(L)) &&
          referToTheSameDecl(DstArg, getStrlenExprArg(R)))
        PatternType = 1;
      // - sizeof(src) - (anything)
      else if (referToTheSameDecl(SrcArg, getSizeOfExprArg(L)))
        PatternType = 2;
    }
  }

  if (PatternType == 0)
    return;

  // Generate the diagnostic.
  SourceLocation SL = LenArg->getBeginLoc();
  SourceRange SR = LenArg->getSourceRange();
  SourceManager &SM = getSourceManager();

  // If the function is defined as a builtin macro, do not show macro expansion.
  if (SM.isMacroArgExpansion(SL)) {
    SL = SM.getSpellingLoc(SL);
    SR = SourceRange(SM.getSpellingLoc(SR.getBegin()),
                     SM.getSpellingLoc(SR.getEnd()));
  }

  // Check if the destination is an array (rather than a pointer to an array).
  QualType DstTy = DstArg->getType();
  bool isKnownSizeArray = isConstantSizeArrayWithMoreThanOneElement(DstTy,
                                                                    Context);
  if (!isKnownSizeArray) {
    if (PatternType == 1)
      Diag(SL, diag::warn_strncat_wrong_size) << SR;
    else
      Diag(SL, diag::warn_strncat_src_size) << SR;
    return;
  }

  if (PatternType == 1)
    Diag(SL, diag::warn_strncat_large_size) << SR;
  else
    Diag(SL, diag::warn_strncat_src_size) << SR;

  SmallString<128> sizeString;
  llvm::raw_svector_ostream OS(sizeString);
  OS << "sizeof(";
  DstArg->printPretty(OS, nullptr, getPrintingPolicy());
  OS << ") - ";
  OS << "strlen(";
  DstArg->printPretty(OS, nullptr, getPrintingPolicy());
  OS << ") - 1";

  Diag(SL, diag::note_strncat_wrong_size)
    << FixItHint::CreateReplacement(SR, OS.str());
}

namespace {
void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
                                const UnaryOperator *UnaryExpr, const Decl *D) {
  if (isa<FieldDecl, FunctionDecl, VarDecl>(D)) {
    S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
        << CalleeName << 0 /*object: */ << cast<NamedDecl>(D);
    return;
  }
}

void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
                                 const UnaryOperator *UnaryExpr) {
  if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr())) {
    const Decl *D = Lvalue->getDecl();
    if (const auto *DD = dyn_cast<DeclaratorDecl>(D)) {
      if (!DD->getType()->isReferenceType())
        return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
    }
  }

  if (const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->getSubExpr()))
    return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr,
                                      Lvalue->getMemberDecl());
}

void CheckFreeArgumentsPlus(Sema &S, const std::string &CalleeName,
                            const UnaryOperator *UnaryExpr) {
  const auto *Lambda = dyn_cast<LambdaExpr>(
      UnaryExpr->getSubExpr()->IgnoreImplicitAsWritten()->IgnoreParens());
  if (!Lambda)
    return;

  S.Diag(Lambda->getBeginLoc(), diag::warn_free_nonheap_object)
      << CalleeName << 2 /*object: lambda expression*/;
}

void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName,
                                  const DeclRefExpr *Lvalue) {
  const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl());
  if (Var == nullptr)
    return;

  S.Diag(Lvalue->getBeginLoc(), diag::warn_free_nonheap_object)
      << CalleeName << 0 /*object: */ << Var;
}

void CheckFreeArgumentsCast(Sema &S, const std::string &CalleeName,
                            const CastExpr *Cast) {
  SmallString<128> SizeString;
  llvm::raw_svector_ostream OS(SizeString);

  clang::CastKind Kind = Cast->getCastKind();
  if (Kind == clang::CK_BitCast &&
      !Cast->getSubExpr()->getType()->isFunctionPointerType())
    return;
  if (Kind == clang::CK_IntegralToPointer &&
      !isa<IntegerLiteral>(
          Cast->getSubExpr()->IgnoreParenImpCasts()->IgnoreParens()))
    return;

  switch (Cast->getCastKind()) {
  case clang::CK_BitCast:
  case clang::CK_IntegralToPointer:
  case clang::CK_FunctionToPointerDecay:
    OS << '\'';
    Cast->printPretty(OS, nullptr, S.getPrintingPolicy());
    OS << '\'';
    break;
  default:
    return;
  }

  S.Diag(Cast->getBeginLoc(), diag::warn_free_nonheap_object)
      << CalleeName << 0 /*object: */ << OS.str();
}
} // namespace

void Sema::CheckFreeArguments(const CallExpr *E) {
  const std::string CalleeName =
      cast<FunctionDecl>(E->getCalleeDecl())->getQualifiedNameAsString();

  { // Prefer something that doesn't involve a cast to make things simpler.
    const Expr *Arg = E->getArg(0)->IgnoreParenCasts();
    if (const auto *UnaryExpr = dyn_cast<UnaryOperator>(Arg))
      switch (UnaryExpr->getOpcode()) {
      case UnaryOperator::Opcode::UO_AddrOf:
        return CheckFreeArgumentsAddressof(*this, CalleeName, UnaryExpr);
      case UnaryOperator::Opcode::UO_Plus:
        return CheckFreeArgumentsPlus(*this, CalleeName, UnaryExpr);
      default:
        break;
      }

    if (const auto *Lvalue = dyn_cast<DeclRefExpr>(Arg))
      if (Lvalue->getType()->isArrayType())
        return CheckFreeArgumentsStackArray(*this, CalleeName, Lvalue);

    if (const auto *Label = dyn_cast<AddrLabelExpr>(Arg)) {
      Diag(Label->getBeginLoc(), diag::warn_free_nonheap_object)
          << CalleeName << 0 /*object: */ << Label->getLabel()->getIdentifier();
      return;
    }

    if (isa<BlockExpr>(Arg)) {
      Diag(Arg->getBeginLoc(), diag::warn_free_nonheap_object)
          << CalleeName << 1 /*object: block*/;
      return;
    }
  }
  // Maybe the cast was important, check after the other cases.
  if (const auto *Cast = dyn_cast<CastExpr>(E->getArg(0)))
    return CheckFreeArgumentsCast(*this, CalleeName, Cast);
}

void
Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
                         SourceLocation ReturnLoc,
                         bool isObjCMethod,
                         const AttrVec *Attrs,
                         const FunctionDecl *FD) {
  // Check if the return value is null but should not be.
  if (((Attrs && hasSpecificAttr<ReturnsNonNullAttr>(*Attrs)) ||
       (!isObjCMethod && isNonNullType(lhsType))) &&
      CheckNonNullExpr(*this, RetValExp))
    Diag(ReturnLoc, diag::warn_null_ret)
      << (isObjCMethod ? 1 : 0) << RetValExp->getSourceRange();

  // C++11 [basic.stc.dynamic.allocation]p4:
  //   If an allocation function declared with a non-throwing
  //   exception-specification fails to allocate storage, it shall return
  //   a null pointer. Any other allocation function that fails to allocate
  //   storage shall indicate failure only by throwing an exception [...]
  if (FD) {
    OverloadedOperatorKind Op = FD->getOverloadedOperator();
    if (Op == OO_New || Op == OO_Array_New) {
      const FunctionProtoType *Proto
        = FD->getType()->castAs<FunctionProtoType>();
      if (!Proto->isNothrow(/*ResultIfDependent*/true) &&
          CheckNonNullExpr(*this, RetValExp))
        Diag(ReturnLoc, diag::warn_operator_new_returns_null)
          << FD << getLangOpts().CPlusPlus11;
    }
  }

  if (RetValExp && RetValExp->getType()->isWebAssemblyTableType()) {
    Diag(ReturnLoc, diag::err_wasm_table_art) << 1;
  }

  // PPC MMA non-pointer types are not allowed as return type. Checking the type
  // here prevent the user from using a PPC MMA type as trailing return type.
  if (Context.getTargetInfo().getTriple().isPPC64())
    PPC().CheckPPCMMAType(RetValExp->getType(), ReturnLoc);
}

void Sema::CheckFloatComparison(SourceLocation Loc, const Expr *LHS,
                                const Expr *RHS, BinaryOperatorKind Opcode) {
  if (!BinaryOperator::isEqualityOp(Opcode))
    return;

  // Match and capture subexpressions such as "(float) X == 0.1".
  const FloatingLiteral *FPLiteral;
  const CastExpr *FPCast;
  auto getCastAndLiteral = [&FPLiteral, &FPCast](const Expr *L, const Expr *R) {
    FPLiteral = dyn_cast<FloatingLiteral>(L->IgnoreParens());
    FPCast = dyn_cast<CastExpr>(R->IgnoreParens());
    return FPLiteral && FPCast;
  };

  if (getCastAndLiteral(LHS, RHS) || getCastAndLiteral(RHS, LHS)) {
    auto *SourceTy = FPCast->getSubExpr()->getType()->getAs<BuiltinType>();
    auto *TargetTy = FPLiteral->getType()->getAs<BuiltinType>();
    if (SourceTy && TargetTy && SourceTy->isFloatingPoint() &&
        TargetTy->isFloatingPoint()) {
      bool Lossy;
      llvm::APFloat TargetC = FPLiteral->getValue();
      TargetC.convert(Context.getFloatTypeSemantics(QualType(SourceTy, 0)),
                      llvm::APFloat::rmNearestTiesToEven, &Lossy);
      if (Lossy) {
        // If the literal cannot be represented in the source type, then a
        // check for == is always false and check for != is always true.
        Diag(Loc, diag::warn_float_compare_literal)
            << (Opcode == BO_EQ) << QualType(SourceTy, 0)
            << LHS->getSourceRange() << RHS->getSourceRange();
        return;
      }
    }
  }

  // Match a more general floating-point equality comparison (-Wfloat-equal).
  const Expr *LeftExprSansParen = LHS->IgnoreParenImpCasts();
  const Expr *RightExprSansParen = RHS->IgnoreParenImpCasts();

  // Special case: check for x == x (which is OK).
  // Do not emit warnings for such cases.
  if (const auto *DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen))
    if (const auto *DRR = dyn_cast<DeclRefExpr>(RightExprSansParen))
      if (DRL->getDecl() == DRR->getDecl())
        return;

  // Special case: check for comparisons against literals that can be exactly
  //  represented by APFloat.  In such cases, do not emit a warning.  This
  //  is a heuristic: often comparison against such literals are used to
  //  detect if a value in a variable has not changed.  This clearly can
  //  lead to false negatives.
  if (const auto *FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) {
    if (FLL->isExact())
      return;
  } else if (const auto *FLR = dyn_cast<FloatingLiteral>(RightExprSansParen))
    if (FLR->isExact())
      return;

  // Check for comparisons with builtin types.
  if (const auto *CL = dyn_cast<CallExpr>(LeftExprSansParen);
      CL && CL->getBuiltinCallee())
    return;

  if (const auto *CR = dyn_cast<CallExpr>(RightExprSansParen);
      CR && CR->getBuiltinCallee())
    return;

  // Emit the diagnostic.
  Diag(Loc, diag::warn_floatingpoint_eq)
    << LHS->getSourceRange() << RHS->getSourceRange();
}

//===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===//
//===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===//

namespace {

/// Structure recording the 'active' range of an integer-valued
/// expression.
struct IntRange {
  /// The number of bits active in the int. Note that this includes exactly one
  /// sign bit if !NonNegative.
  unsigned Width;

  /// True if the int is known not to have negative values. If so, all leading
  /// bits before Width are known zero, otherwise they are known to be the
  /// same as the MSB within Width.
  bool NonNegative;

  IntRange(unsigned Width, bool NonNegative)
      : Width(Width), NonNegative(NonNegative) {}

  /// Number of bits excluding the sign bit.
  unsigned valueBits() const {
    return NonNegative ? Width : Width - 1;
  }

  /// Returns the range of the bool type.
  static IntRange forBoolType() {
    return IntRange(1, true);
  }

  /// Returns the range of an opaque value of the given integral type.
  static IntRange forValueOfType(ASTContext &C, QualType T) {
    return forValueOfCanonicalType(C,
                          T->getCanonicalTypeInternal().getTypePtr());
  }

  /// Returns the range of an opaque value of a canonical integral type.
  static IntRange forValueOfCanonicalType(ASTContext &C, const Type *T) {
    assert(T->isCanonicalUnqualified());

    if (const auto *VT = dyn_cast<VectorType>(T))
      T = VT->getElementType().getTypePtr();
    if (const auto *CT = dyn_cast<ComplexType>(T))
      T = CT->getElementType().getTypePtr();
    if (const auto *AT = dyn_cast<AtomicType>(T))
      T = AT->getValueType().getTypePtr();

    if (!C.getLangOpts().CPlusPlus) {
      // For enum types in C code, use the underlying datatype.
      if (const auto *ET = dyn_cast<EnumType>(T))
        T = ET->getDecl()->getIntegerType().getDesugaredType(C).getTypePtr();
    } else if (const auto *ET = dyn_cast<EnumType>(T)) {
      // For enum types in C++, use the known bit width of the enumerators.
      EnumDecl *Enum = ET->getDecl();
      // In C++11, enums can have a fixed underlying type. Use this type to
      // compute the range.
      if (Enum->isFixed()) {
        return IntRange(C.getIntWidth(QualType(T, 0)),
                        !ET->isSignedIntegerOrEnumerationType());
      }

      unsigned NumPositive = Enum->getNumPositiveBits();
      unsigned NumNegative = Enum->getNumNegativeBits();

      if (NumNegative == 0)
        return IntRange(NumPositive, true/*NonNegative*/);
      else
        return IntRange(std::max(NumPositive + 1, NumNegative),
                        false/*NonNegative*/);
    }

    if (const auto *EIT = dyn_cast<BitIntType>(T))
      return IntRange(EIT->getNumBits(), EIT->isUnsigned());

    const BuiltinType *BT = cast<BuiltinType>(T);
    assert(BT->isInteger());

    return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
  }

  /// Returns the "target" range of a canonical integral type, i.e.
  /// the range of values expressible in the type.
  ///
  /// This matches forValueOfCanonicalType except that enums have the
  /// full range of their type, not the range of their enumerators.
  static IntRange forTargetOfCanonicalType(ASTContext &C, const Type *T) {
    assert(T->isCanonicalUnqualified());

    if (const VectorType *VT = dyn_cast<VectorType>(T))
      T = VT->getElementType().getTypePtr();
    if (const ComplexType *CT = dyn_cast<ComplexType>(T))
      T = CT->getElementType().getTypePtr();
    if (const AtomicType *AT = dyn_cast<AtomicType>(T))
      T = AT->getValueType().getTypePtr();
    if (const EnumType *ET = dyn_cast<EnumType>(T))
      T = C.getCanonicalType(ET->getDecl()->getIntegerType()).getTypePtr();

    if (const auto *EIT = dyn_cast<BitIntType>(T))
      return IntRange(EIT->getNumBits(), EIT->isUnsigned());

    const BuiltinType *BT = cast<BuiltinType>(T);
    assert(BT->isInteger());

    return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger());
  }

  /// Returns the supremum of two ranges: i.e. their conservative merge.
  static IntRange join(IntRange L, IntRange R) {
    bool Unsigned = L.NonNegative && R.NonNegative;
    return IntRange(std::max(L.valueBits(), R.valueBits()) + !Unsigned,
                    L.NonNegative && R.NonNegative);
  }

  /// Return the range of a bitwise-AND of the two ranges.
  static IntRange bit_and(IntRange L, IntRange R) {
    unsigned Bits = std::max(L.Width, R.Width);
    bool NonNegative = false;
    if (L.NonNegative) {
      Bits = std::min(Bits, L.Width);
      NonNegative = true;
    }
    if (R.NonNegative) {
      Bits = std::min(Bits, R.Width);
      NonNegative = true;
    }
    return IntRange(Bits, NonNegative);
  }

  /// Return the range of a sum of the two ranges.
  static IntRange sum(IntRange L, IntRange R) {
    bool Unsigned = L.NonNegative && R.NonNegative;
    return IntRange(std::max(L.valueBits(), R.valueBits()) + 1 + !Unsigned,
                    Unsigned);
  }

  /// Return the range of a difference of the two ranges.
  static IntRange difference(IntRange L, IntRange R) {
    // We need a 1-bit-wider range if:
    //   1) LHS can be negative: least value can be reduced.
    //   2) RHS can be negative: greatest value can be increased.
    bool CanWiden = !L.NonNegative || !R.NonNegative;
    bool Unsigned = L.NonNegative && R.Width == 0;
    return IntRange(std::max(L.valueBits(), R.valueBits()) + CanWiden +
                        !Unsigned,
                    Unsigned);
  }

  /// Return the range of a product of the two ranges.
  static IntRange product(IntRange L, IntRange R) {
    // If both LHS and RHS can be negative, we can form
    //   -2^L * -2^R = 2^(L + R)
    // which requires L + R + 1 value bits to represent.
    bool CanWiden = !L.NonNegative && !R.NonNegative;
    bool Unsigned = L.NonNegative && R.NonNegative;
    return IntRange(L.valueBits() + R.valueBits() + CanWiden + !Unsigned,
                    Unsigned);
  }

  /// Return the range of a remainder operation between the two ranges.
  static IntRange rem(IntRange L, IntRange R) {
    // The result of a remainder can't be larger than the result of
    // either side. The sign of the result is the sign of the LHS.
    bool Unsigned = L.NonNegative;
    return IntRange(std::min(L.valueBits(), R.valueBits()) + !Unsigned,
                    Unsigned);
  }
};

} // namespace

static IntRange GetValueRange(llvm::APSInt &value, unsigned MaxWidth) {
  if (value.isSigned() && value.isNegative())
    return IntRange(value.getSignificantBits(), false);

  if (value.getBitWidth() > MaxWidth)
    value = value.trunc(MaxWidth);

  // isNonNegative() just checks the sign bit without considering
  // signedness.
  return IntRange(value.getActiveBits(), true);
}

static IntRange GetValueRange(APValue &result, QualType Ty, unsigned MaxWidth) {
  if (result.isInt())
    return GetValueRange(result.getInt(), MaxWidth);

  if (result.isVector()) {
    IntRange R = GetValueRange(result.getVectorElt(0), Ty, MaxWidth);
    for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) {
      IntRange El = GetValueRange(result.getVectorElt(i), Ty, MaxWidth);
      R = IntRange::join(R, El);
    }
    return R;
  }

  if (result.isComplexInt()) {
    IntRange R = GetValueRange(result.getComplexIntReal(), MaxWidth);
    IntRange I = GetValueRange(result.getComplexIntImag(), MaxWidth);
    return IntRange::join(R, I);
  }

  // This can happen with lossless casts to intptr_t of "based" lvalues.
  // Assume it might use arbitrary bits.
  // FIXME: The only reason we need to pass the type in here is to get
  // the sign right on this one case.  It would be nice if APValue
  // preserved this.
  assert(result.isLValue() || result.isAddrLabelDiff());
  return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType());
}

static QualType GetExprType(const Expr *E) {
  QualType Ty = E->getType();
  if (const auto *AtomicRHS = Ty->getAs<AtomicType>())
    Ty = AtomicRHS->getValueType();
  return Ty;
}

/// Attempts to estimate an approximate range for the given integer expression.
/// Returns a range if successful, otherwise it returns \c std::nullopt if a
/// reliable estimation cannot be determined.
///
/// \param MaxWidth The width to which the value will be truncated.
/// \param InConstantContext If \c true, interpret the expression within a
///        constant context.
/// \param Approximate If \c true, provide a likely range of values by assuming
///        that arithmetic on narrower types remains within those types.
///        If \c false, return a range that includes all possible values
///        resulting from the expression.
/// \returns A range of values that the expression might take, or
///          std::nullopt if a reliable estimation cannot be determined.
static std::optional<IntRange> TryGetExprRange(ASTContext &C, const Expr *E,
                                               unsigned MaxWidth,
                                               bool InConstantContext,
                                               bool Approximate) {
  E = E->IgnoreParens();

  // Try a full evaluation first.
  Expr::EvalResult result;
  if (E->EvaluateAsRValue(result, C, InConstantContext))
    return GetValueRange(result.Val, GetExprType(E), MaxWidth);

  // I think we only want to look through implicit casts here; if the
  // user has an explicit widening cast, we should treat the value as
  // being of the new, wider type.
  if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) {
    if (CE->getCastKind() == CK_NoOp || CE->getCastKind() == CK_LValueToRValue)
      return TryGetExprRange(C, CE->getSubExpr(), MaxWidth, InConstantContext,
                             Approximate);

    IntRange OutputTypeRange = IntRange::forValueOfType(C, GetExprType(CE));

    bool isIntegerCast = CE->getCastKind() == CK_IntegralCast ||
                         CE->getCastKind() == CK_BooleanToSignedIntegral;

    // Assume that non-integer casts can span the full range of the type.
    if (!isIntegerCast)
      return OutputTypeRange;

    std::optional<IntRange> SubRange = TryGetExprRange(
        C, CE->getSubExpr(), std::min(MaxWidth, OutputTypeRange.Width),
        InConstantContext, Approximate);
    if (!SubRange)
      return std::nullopt;

    // Bail out if the subexpr's range is as wide as the cast type.
    if (SubRange->Width >= OutputTypeRange.Width)
      return OutputTypeRange;

    // Otherwise, we take the smaller width, and we're non-negative if
    // either the output type or the subexpr is.
    return IntRange(SubRange->Width,
                    SubRange->NonNegative || OutputTypeRange.NonNegative);
  }

  if (const auto *CO = dyn_cast<ConditionalOperator>(E)) {
    // If we can fold the condition, just take that operand.
    bool CondResult;
    if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C))
      return TryGetExprRange(
          C, CondResult ? CO->getTrueExpr() : CO->getFalseExpr(), MaxWidth,
          InConstantContext, Approximate);

    // Otherwise, conservatively merge.
    // TryGetExprRange requires an integer expression, but a throw expression
    // results in a void type.
    Expr *TrueExpr = CO->getTrueExpr();
    if (TrueExpr->getType()->isVoidType())
      return std::nullopt;

    std::optional<IntRange> L =
        TryGetExprRange(C, TrueExpr, MaxWidth, InConstantContext, Approximate);
    if (!L)
      return std::nullopt;

    Expr *FalseExpr = CO->getFalseExpr();
    if (FalseExpr->getType()->isVoidType())
      return std::nullopt;

    std::optional<IntRange> R =
        TryGetExprRange(C, FalseExpr, MaxWidth, InConstantContext, Approximate);
    if (!R)
      return std::nullopt;

    return IntRange::join(*L, *R);
  }

  if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
    IntRange (*Combine)(IntRange, IntRange) = IntRange::join;

    switch (BO->getOpcode()) {
    case BO_Cmp:
      llvm_unreachable("builtin <=> should have class type");

    // Boolean-valued operations are single-bit and positive.
    case BO_LAnd:
    case BO_LOr:
    case BO_LT:
    case BO_GT:
    case BO_LE:
    case BO_GE:
    case BO_EQ:
    case BO_NE:
      return IntRange::forBoolType();

    // The type of the assignments is the type of the LHS, so the RHS
    // is not necessarily the same type.
    case BO_MulAssign:
    case BO_DivAssign:
    case BO_RemAssign:
    case BO_AddAssign:
    case BO_SubAssign:
    case BO_XorAssign:
    case BO_OrAssign:
      // TODO: bitfields?
      return IntRange::forValueOfType(C, GetExprType(E));

    // Simple assignments just pass through the RHS, which will have
    // been coerced to the LHS type.
    case BO_Assign:
      // TODO: bitfields?
      return TryGetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext,
                             Approximate);

    // Operations with opaque sources are black-listed.
    case BO_PtrMemD:
    case BO_PtrMemI:
      return IntRange::forValueOfType(C, GetExprType(E));

    // Bitwise-and uses the *infinum* of the two source ranges.
    case BO_And:
    case BO_AndAssign:
      Combine = IntRange::bit_and;
      break;

    // Left shift gets black-listed based on a judgement call.
    case BO_Shl:
      // ...except that we want to treat '1 << (blah)' as logically
      // positive.  It's an important idiom.
      if (IntegerLiteral *I
            = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) {
        if (I->getValue() == 1) {
          IntRange R = IntRange::forValueOfType(C, GetExprType(E));
          return IntRange(R.Width, /*NonNegative*/ true);
        }
      }
      [[fallthrough]];

    case BO_ShlAssign:
      return IntRange::forValueOfType(C, GetExprType(E));

    // Right shift by a constant can narrow its left argument.
    case BO_Shr:
    case BO_ShrAssign: {
      std::optional<IntRange> L = TryGetExprRange(
          C, BO->getLHS(), MaxWidth, InConstantContext, Approximate);
      if (!L)
        return std::nullopt;

      // If the shift amount is a positive constant, drop the width by
      // that much.
      if (std::optional<llvm::APSInt> shift =
              BO->getRHS()->getIntegerConstantExpr(C)) {
        if (shift->isNonNegative()) {
          if (shift->uge(L->Width))
            L->Width = (L->NonNegative ? 0 : 1);
          else
            L->Width -= shift->getZExtValue();
        }
      }

      return L;
    }

    // Comma acts as its right operand.
    case BO_Comma:
      return TryGetExprRange(C, BO->getRHS(), MaxWidth, InConstantContext,
                             Approximate);

    case BO_Add:
      if (!Approximate)
        Combine = IntRange::sum;
      break;

    case BO_Sub:
      if (BO->getLHS()->getType()->isPointerType())
        return IntRange::forValueOfType(C, GetExprType(E));
      if (!Approximate)
        Combine = IntRange::difference;
      break;

    case BO_Mul:
      if (!Approximate)
        Combine = IntRange::product;
      break;

    // The width of a division result is mostly determined by the size
    // of the LHS.
    case BO_Div: {
      // Don't 'pre-truncate' the operands.
      unsigned opWidth = C.getIntWidth(GetExprType(E));
      std::optional<IntRange> L = TryGetExprRange(
          C, BO->getLHS(), opWidth, InConstantContext, Approximate);
      if (!L)
        return std::nullopt;

      // If the divisor is constant, use that.
      if (std::optional<llvm::APSInt> divisor =
              BO->getRHS()->getIntegerConstantExpr(C)) {
        unsigned log2 = divisor->logBase2(); // floor(log_2(divisor))
        if (log2 >= L->Width)
          L->Width = (L->NonNegative ? 0 : 1);
        else
          L->Width = std::min(L->Width - log2, MaxWidth);
        return L;
      }

      // Otherwise, just use the LHS's width.
      // FIXME: This is wrong if the LHS could be its minimal value and the RHS
      // could be -1.
      std::optional<IntRange> R = TryGetExprRange(
          C, BO->getRHS(), opWidth, InConstantContext, Approximate);
      if (!R)
        return std::nullopt;

      return IntRange(L->Width, L->NonNegative && R->NonNegative);
    }

    case BO_Rem:
      Combine = IntRange::rem;
      break;

    // The default behavior is okay for these.
    case BO_Xor:
    case BO_Or:
      break;
    }

    // Combine the two ranges, but limit the result to the type in which we
    // performed the computation.
    QualType T = GetExprType(E);
    unsigned opWidth = C.getIntWidth(T);
    std::optional<IntRange> L = TryGetExprRange(C, BO->getLHS(), opWidth,
                                                InConstantContext, Approximate);
    if (!L)
      return std::nullopt;

    std::optional<IntRange> R = TryGetExprRange(C, BO->getRHS(), opWidth,
                                                InConstantContext, Approximate);
    if (!R)
      return std::nullopt;

    IntRange C = Combine(*L, *R);
    C.NonNegative |= T->isUnsignedIntegerOrEnumerationType();
    C.Width = std::min(C.Width, MaxWidth);
    return C;
  }

  if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
    switch (UO->getOpcode()) {
    // Boolean-valued operations are white-listed.
    case UO_LNot:
      return IntRange::forBoolType();

    // Operations with opaque sources are black-listed.
    case UO_Deref:
    case UO_AddrOf: // should be impossible
      return IntRange::forValueOfType(C, GetExprType(E));

    case UO_Minus: {
      if (E->getType()->isUnsignedIntegerType()) {
        return TryGetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
                               Approximate);
      }

      std::optional<IntRange> SubRange = TryGetExprRange(
          C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);

      if (!SubRange)
        return std::nullopt;

      // If the range was previously non-negative, we need an extra bit for the
      // sign bit. If the range was not non-negative, we need an extra bit
      // because the negation of the most-negative value is one bit wider than
      // that value.
      return IntRange(SubRange->Width + 1, false);
    }

    case UO_Not: {
      if (E->getType()->isUnsignedIntegerType()) {
        return TryGetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
                               Approximate);
      }

      std::optional<IntRange> SubRange = TryGetExprRange(
          C, UO->getSubExpr(), MaxWidth, InConstantContext, Approximate);

      if (!SubRange)
        return std::nullopt;

      // The width increments by 1 if the sub-expression cannot be negative
      // since it now can be.
      return IntRange(SubRange->Width + (int)SubRange->NonNegative, false);
    }

    default:
      return TryGetExprRange(C, UO->getSubExpr(), MaxWidth, InConstantContext,
                             Approximate);
    }
  }

  if (const auto *OVE = dyn_cast<OpaqueValueExpr>(E))
    return TryGetExprRange(C, OVE->getSourceExpr(), MaxWidth, InConstantContext,
                           Approximate);

  if (const auto *BitField = E->getSourceBitField())
    return IntRange(BitField->getBitWidthValue(),
                    BitField->getType()->isUnsignedIntegerOrEnumerationType());

  if (GetExprType(E)->isVoidType())
    return std::nullopt;

  return IntRange::forValueOfType(C, GetExprType(E));
}

static std::optional<IntRange> TryGetExprRange(ASTContext &C, const Expr *E,
                                               bool InConstantContext,
                                               bool Approximate) {
  return TryGetExprRange(C, E, C.getIntWidth(GetExprType(E)), InConstantContext,
                         Approximate);
}

/// Checks whether the given value, which currently has the given
/// source semantics, has the same value when coerced through the
/// target semantics.
static bool IsSameFloatAfterCast(const llvm::APFloat &value,
                                 const llvm::fltSemantics &Src,
                                 const llvm::fltSemantics &Tgt) {
  llvm::APFloat truncated = value;

  bool ignored;
  truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored);
  truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored);

  return truncated.bitwiseIsEqual(value);
}

/// Checks whether the given value, which currently has the given
/// source semantics, has the same value when coerced through the
/// target semantics.
///
/// The value might be a vector of floats (or a complex number).
static bool IsSameFloatAfterCast(const APValue &value,
                                 const llvm::fltSemantics &Src,
                                 const llvm::fltSemantics &Tgt) {
  if (value.isFloat())
    return IsSameFloatAfterCast(value.getFloat(), Src, Tgt);

  if (value.isVector()) {
    for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i)
      if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt))
        return false;
    return true;
  }

  assert(value.isComplexFloat());
  return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) &&
          IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt));
}

static void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC,
                                       bool IsListInit = false);

static bool IsEnumConstOrFromMacro(Sema &S, const Expr *E) {
  // Suppress cases where we are comparing against an enum constant.
  if (const auto *DR = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
    if (isa<EnumConstantDecl>(DR->getDecl()))
      return true;

  // Suppress cases where the value is expanded from a macro, unless that macro
  // is how a language represents a boolean literal. This is the case in both C
  // and Objective-C.
  SourceLocation BeginLoc = E->getBeginLoc();
  if (BeginLoc.isMacroID()) {
    StringRef MacroName = Lexer::getImmediateMacroName(
        BeginLoc, S.getSourceManager(), S.getLangOpts());
    return MacroName != "YES" && MacroName != "NO" &&
           MacroName != "true" && MacroName != "false";
  }

  return false;
}

static bool isKnownToHaveUnsignedValue(const Expr *E) {
  return E->getType()->isIntegerType() &&
         (!E->getType()->isSignedIntegerType() ||
          !E->IgnoreParenImpCasts()->getType()->isSignedIntegerType());
}

namespace {
/// The promoted range of values of a type. In general this has the
/// following structure:
///
///     |-----------| . . . |-----------|
///     ^           ^       ^           ^
///    Min       HoleMin  HoleMax      Max
///
/// ... where there is only a hole if a signed type is promoted to unsigned
/// (in which case Min and Max are the smallest and largest representable
/// values).
struct PromotedRange {
  // Min, or HoleMax if there is a hole.
  llvm::APSInt PromotedMin;
  // Max, or HoleMin if there is a hole.
  llvm::APSInt PromotedMax;

  PromotedRange(IntRange R, unsigned BitWidth, bool Unsigned) {
    if (R.Width == 0)
      PromotedMin = PromotedMax = llvm::APSInt(BitWidth, Unsigned);
    else if (R.Width >= BitWidth && !Unsigned) {
      // Promotion made the type *narrower*. This happens when promoting
      // a < 32-bit unsigned / <= 32-bit signed bit-field to 'signed int'.
      // Treat all values of 'signed int' as being in range for now.
      PromotedMin = llvm::APSInt::getMinValue(BitWidth, Unsigned);
      PromotedMax = llvm::APSInt::getMaxValue(BitWidth, Unsigned);
    } else {
      PromotedMin = llvm::APSInt::getMinValue(R.Width, R.NonNegative)
                        .extOrTrunc(BitWidth);
      PromotedMin.setIsUnsigned(Unsigned);

      PromotedMax = llvm::APSInt::getMaxValue(R.Width, R.NonNegative)
                        .extOrTrunc(BitWidth);
      PromotedMax.setIsUnsigned(Unsigned);
    }
  }

  // Determine whether this range is contiguous (has no hole).
  bool isContiguous() const { return PromotedMin <= PromotedMax; }

  // Where a constant value is within the range.
  enum ComparisonResult {
    LT = 0x1,
    LE = 0x2,
    GT = 0x4,
    GE = 0x8,
    EQ = 0x10,
    NE = 0x20,
    InRangeFlag = 0x40,

    Less = LE | LT | NE,
    Min = LE | InRangeFlag,
    InRange = InRangeFlag,
    Max = GE | InRangeFlag,
    Greater = GE | GT | NE,

    OnlyValue = LE | GE | EQ | InRangeFlag,
    InHole = NE
  };

  ComparisonResult compare(const llvm::APSInt &Value) const {
    assert(Value.getBitWidth() == PromotedMin.getBitWidth() &&
           Value.isUnsigned() == PromotedMin.isUnsigned());
    if (!isContiguous()) {
      assert(Value.isUnsigned() && "discontiguous range for signed compare");
      if (Value.isMinValue()) return Min;
      if (Value.isMaxValue()) return Max;
      if (Value >= PromotedMin) return InRange;
      if (Value <= PromotedMax) return InRange;
      return InHole;
    }

    switch (llvm::APSInt::compareValues(Value, PromotedMin)) {
    case -1: return Less;
    case 0: return PromotedMin == PromotedMax ? OnlyValue : Min;
    case 1:
      switch (llvm::APSInt::compareValues(Value, PromotedMax)) {
      case -1: return InRange;
      case 0: return Max;
      case 1: return Greater;
      }
    }

    llvm_unreachable("impossible compare result");
  }

  static std::optional<StringRef>
  constantValue(BinaryOperatorKind Op, ComparisonResult R, bool ConstantOnRHS) {
    if (Op == BO_Cmp) {
      ComparisonResult LTFlag = LT, GTFlag = GT;
      if (ConstantOnRHS) std::swap(LTFlag, GTFlag);

      if (R & EQ) return StringRef("'std::strong_ordering::equal'");
      if (R & LTFlag) return StringRef("'std::strong_ordering::less'");
      if (R & GTFlag) return StringRef("'std::strong_ordering::greater'");
      return std::nullopt;
    }

    ComparisonResult TrueFlag, FalseFlag;
    if (Op == BO_EQ) {
      TrueFlag = EQ;
      FalseFlag = NE;
    } else if (Op == BO_NE) {
      TrueFlag = NE;
      FalseFlag = EQ;
    } else {
      if ((Op == BO_LT || Op == BO_GE) ^ ConstantOnRHS) {
        TrueFlag = LT;
        FalseFlag = GE;
      } else {
        TrueFlag = GT;
        FalseFlag = LE;
      }
      if (Op == BO_GE || Op == BO_LE)
        std::swap(TrueFlag, FalseFlag);
    }
    if (R & TrueFlag)
      return StringRef("true");
    if (R & FalseFlag)
      return StringRef("false");
    return std::nullopt;
  }
};
}

static bool HasEnumType(const Expr *E) {
  // Strip off implicit integral promotions.
  while (const auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
    if (ICE->getCastKind() != CK_IntegralCast &&
        ICE->getCastKind() != CK_NoOp)
      break;
    E = ICE->getSubExpr();
  }

  return E->getType()->isEnumeralType();
}

static int classifyConstantValue(Expr *Constant) {
  // The values of this enumeration are used in the diagnostics
  // diag::warn_out_of_range_compare and diag::warn_tautological_bool_compare.
  enum ConstantValueKind {
    Miscellaneous = 0,
    LiteralTrue,
    LiteralFalse
  };
  if (auto *BL = dyn_cast<CXXBoolLiteralExpr>(Constant))
    return BL->getValue() ? ConstantValueKind::LiteralTrue
                          : ConstantValueKind::LiteralFalse;
  return ConstantValueKind::Miscellaneous;
}

static bool CheckTautologicalComparison(Sema &S, BinaryOperator *E,
                                        Expr *Constant, Expr *Other,
                                        const llvm::APSInt &Value,
                                        bool RhsConstant) {
  if (S.inTemplateInstantiation())
    return false;

  Expr *OriginalOther = Other;

  Constant = Constant->IgnoreParenImpCasts();
  Other = Other->IgnoreParenImpCasts();

  // Suppress warnings on tautological comparisons between values of the same
  // enumeration type. There are only two ways we could warn on this:
  //  - If the constant is outside the range of representable values of
  //    the enumeration. In such a case, we should warn about the cast
  //    to enumeration type, not about the comparison.
  //  - If the constant is the maximum / minimum in-range value. For an
  //    enumeratin type, such comparisons can be meaningful and useful.
  if (Constant->getType()->isEnumeralType() &&
      S.Context.hasSameUnqualifiedType(Constant->getType(), Other->getType()))
    return false;

  std::optional<IntRange> OtherValueRange = TryGetExprRange(
      S.Context, Other, S.isConstantEvaluatedContext(), /*Approximate=*/false);
  if (!OtherValueRange)
    return false;

  QualType OtherT = Other->getType();
  if (const auto *AT = OtherT->getAs<AtomicType>())
    OtherT = AT->getValueType();
  IntRange OtherTypeRange = IntRange::forValueOfType(S.Context, OtherT);

  // Special case for ObjC BOOL on targets where its a typedef for a signed char
  // (Namely, macOS). FIXME: IntRange::forValueOfType should do this.
  bool IsObjCSignedCharBool = S.getLangOpts().ObjC &&
                              S.ObjC().NSAPIObj->isObjCBOOLType(OtherT) &&
                              OtherT->isSpecificBuiltinType(BuiltinType::SChar);

  // Whether we're treating Other as being a bool because of the form of
  // expression despite it having another type (typically 'int' in C).
  bool OtherIsBooleanDespiteType =
      !OtherT->isBooleanType() && Other->isKnownToHaveBooleanValue();
  if (OtherIsBooleanDespiteType || IsObjCSignedCharBool)
    OtherTypeRange = *OtherValueRange = IntRange::forBoolType();

  // Check if all values in the range of possible values of this expression
  // lead to the same comparison outcome.
  PromotedRange OtherPromotedValueRange(*OtherValueRange, Value.getBitWidth(),
                                        Value.isUnsigned());
  auto Cmp = OtherPromotedValueRange.compare(Value);
  auto Result = PromotedRange::constantValue(E->getOpcode(), Cmp, RhsConstant);
  if (!Result)
    return false;

  // Also consider the range determined by the type alone. This allows us to
  // classify the warning under the proper diagnostic group.
  bool TautologicalTypeCompare = false;
  {
    PromotedRange OtherPromotedTypeRange(OtherTypeRange, Value.getBitWidth(),
                                         Value.isUnsigned());
    auto TypeCmp = OtherPromotedTypeRange.compare(Value);
    if (auto TypeResult = PromotedRange::constantValue(E->getOpcode(), TypeCmp,
                                                       RhsConstant)) {
      TautologicalTypeCompare = true;
      Cmp = TypeCmp;
      Result = TypeResult;
    }
  }

  // Don't warn if the non-constant operand actually always evaluates to the
  // same value.
  if (!TautologicalTypeCompare && OtherValueRange->Width == 0)
    return false;

  // Suppress the diagnostic for an in-range comparison if the constant comes
  // from a macro or enumerator. We don't want to diagnose
  //
  //   some_long_value <= INT_MAX
  //
  // when sizeof(int) == sizeof(long).
  bool InRange = Cmp & PromotedRange::InRangeFlag;
  if (InRange && IsEnumConstOrFromMacro(S, Constant))
    return false;

  // A comparison of an unsigned bit-field against 0 is really a type problem,
  // even though at the type level the bit-field might promote to 'signed int'.
  if (Other->refersToBitField() && InRange && Value == 0 &&
      Other->getType()->isUnsignedIntegerOrEnumerationType())
    TautologicalTypeCompare = true;

  // If this is a comparison to an enum constant, include that
  // constant in the diagnostic.
  const EnumConstantDecl *ED = nullptr;
  if (const auto *DR = dyn_cast<DeclRefExpr>(Constant))
    ED = dyn_cast<EnumConstantDecl>(DR->getDecl());

  // Should be enough for uint128 (39 decimal digits)
  SmallString<64> PrettySourceValue;
  llvm::raw_svector_ostream OS(PrettySourceValue);
  if (ED) {
    OS << '\'' << *ED << "' (" << Value << ")";
  } else if (auto *BL = dyn_cast<ObjCBoolLiteralExpr>(
               Constant->IgnoreParenImpCasts())) {
    OS << (BL->getValue() ? "YES" : "NO");
  } else {
    OS << Value;
  }

  if (!TautologicalTypeCompare) {
    S.Diag(E->getOperatorLoc(), diag::warn_tautological_compare_value_range)
        << RhsConstant << OtherValueRange->Width << OtherValueRange->NonNegative
        << E->getOpcodeStr() << OS.str() << *Result
        << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
    return true;
  }

  if (IsObjCSignedCharBool) {
    S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
                          S.PDiag(diag::warn_tautological_compare_objc_bool)
                              << OS.str() << *Result);
    return true;
  }

  // FIXME: We use a somewhat different formatting for the in-range cases and
  // cases involving boolean values for historical reasons. We should pick a
  // consistent way of presenting these diagnostics.
  if (!InRange || Other->isKnownToHaveBooleanValue()) {

    S.DiagRuntimeBehavior(
        E->getOperatorLoc(), E,
        S.PDiag(!InRange ? diag::warn_out_of_range_compare
                         : diag::warn_tautological_bool_compare)
            << OS.str() << classifyConstantValue(Constant) << OtherT
            << OtherIsBooleanDespiteType << *Result
            << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange());
  } else {
    bool IsCharTy = OtherT.withoutLocalFastQualifiers() == S.Context.CharTy;
    unsigned Diag =
        (isKnownToHaveUnsignedValue(OriginalOther) && Value == 0)
            ? (HasEnumType(OriginalOther)
                   ? diag::warn_unsigned_enum_always_true_comparison
                   : IsCharTy ? diag::warn_unsigned_char_always_true_comparison
                              : diag::warn_unsigned_always_true_comparison)
            : diag::warn_tautological_constant_compare;

    S.Diag(E->getOperatorLoc(), Diag)
        << RhsConstant << OtherT << E->getOpcodeStr() << OS.str() << *Result
        << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
  }

  return true;
}

/// Analyze the operands of the given comparison.  Implements the
/// fallback case from AnalyzeComparison.
static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) {
  AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
  AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());
}

/// Implements -Wsign-compare.
///
/// \param E the binary operator to check for warnings
static void AnalyzeComparison(Sema &S, BinaryOperator *E) {
  // The type the comparison is being performed in.
  QualType T = E->getLHS()->getType();

  // Only analyze comparison operators where both sides have been converted to
  // the same type.
  if (!S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()))
    return AnalyzeImpConvsInComparison(S, E);

  // Don't analyze value-dependent comparisons directly.
  if (E->isValueDependent())
    return AnalyzeImpConvsInComparison(S, E);

  Expr *LHS = E->getLHS();
  Expr *RHS = E->getRHS();

  if (T->isIntegralType(S.Context)) {
    std::optional<llvm::APSInt> RHSValue =
        RHS->getIntegerConstantExpr(S.Context);
    std::optional<llvm::APSInt> LHSValue =
        LHS->getIntegerConstantExpr(S.Context);

    // We don't care about expressions whose result is a constant.
    if (RHSValue && LHSValue)
      return AnalyzeImpConvsInComparison(S, E);

    // We only care about expressions where just one side is literal
    if ((bool)RHSValue ^ (bool)LHSValue) {
      // Is the constant on the RHS or LHS?
      const bool RhsConstant = (bool)RHSValue;
      Expr *Const = RhsConstant ? RHS : LHS;
      Expr *Other = RhsConstant ? LHS : RHS;
      const llvm::APSInt &Value = RhsConstant ? *RHSValue : *LHSValue;

      // Check whether an integer constant comparison results in a value
      // of 'true' or 'false'.
      if (CheckTautologicalComparison(S, E, Const, Other, Value, RhsConstant))
        return AnalyzeImpConvsInComparison(S, E);
    }
  }

  if (!T->hasUnsignedIntegerRepresentation()) {
    // We don't do anything special if this isn't an unsigned integral
    // comparison:  we're only interested in integral comparisons, and
    // signed comparisons only happen in cases we don't care to warn about.
    return AnalyzeImpConvsInComparison(S, E);
  }

  LHS = LHS->IgnoreParenImpCasts();
  RHS = RHS->IgnoreParenImpCasts();

  if (!S.getLangOpts().CPlusPlus) {
    // Avoid warning about comparison of integers with different signs when
    // RHS/LHS has a `typeof(E)` type whose sign is different from the sign of
    // the type of `E`.
    if (const auto *TET = dyn_cast<TypeOfExprType>(LHS->getType()))
      LHS = TET->getUnderlyingExpr()->IgnoreParenImpCasts();
    if (const auto *TET = dyn_cast<TypeOfExprType>(RHS->getType()))
      RHS = TET->getUnderlyingExpr()->IgnoreParenImpCasts();
  }

  // Check to see if one of the (unmodified) operands is of different
  // signedness.
  Expr *signedOperand, *unsignedOperand;
  if (LHS->getType()->hasSignedIntegerRepresentation()) {
    assert(!RHS->getType()->hasSignedIntegerRepresentation() &&
           "unsigned comparison between two signed integer expressions?");
    signedOperand = LHS;
    unsignedOperand = RHS;
  } else if (RHS->getType()->hasSignedIntegerRepresentation()) {
    signedOperand = RHS;
    unsignedOperand = LHS;
  } else {
    return AnalyzeImpConvsInComparison(S, E);
  }

  // Otherwise, calculate the effective range of the signed operand.
  std::optional<IntRange> signedRange =
      TryGetExprRange(S.Context, signedOperand, S.isConstantEvaluatedContext(),
                      /*Approximate=*/true);
  if (!signedRange)
    return;

  // Go ahead and analyze implicit conversions in the operands.  Note
  // that we skip the implicit conversions on both sides.
  AnalyzeImplicitConversions(S, LHS, E->getOperatorLoc());
  AnalyzeImplicitConversions(S, RHS, E->getOperatorLoc());

  // If the signed range is non-negative, -Wsign-compare won't fire.
  if (signedRange->NonNegative)
    return;

  // For (in)equality comparisons, if the unsigned operand is a
  // constant which cannot collide with a overflowed signed operand,
  // then reinterpreting the signed operand as unsigned will not
  // change the result of the comparison.
  if (E->isEqualityOp()) {
    unsigned comparisonWidth = S.Context.getIntWidth(T);
    std::optional<IntRange> unsignedRange = TryGetExprRange(
        S.Context, unsignedOperand, S.isConstantEvaluatedContext(),
        /*Approximate=*/true);
    if (!unsignedRange)
      return;

    // We should never be unable to prove that the unsigned operand is
    // non-negative.
    assert(unsignedRange->NonNegative && "unsigned range includes negative?");

    if (unsignedRange->Width < comparisonWidth)
      return;
  }

  S.DiagRuntimeBehavior(E->getOperatorLoc(), E,
                        S.PDiag(diag::warn_mixed_sign_comparison)
                            << LHS->getType() << RHS->getType()
                            << LHS->getSourceRange() << RHS->getSourceRange());
}

/// Analyzes an attempt to assign the given value to a bitfield.
///
/// Returns true if there was something fishy about the attempt.
static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
                                      SourceLocation InitLoc) {
  assert(Bitfield->isBitField());
  if (Bitfield->isInvalidDecl())
    return false;

  // White-list bool bitfields.
  QualType BitfieldType = Bitfield->getType();
  if (BitfieldType->isBooleanType())
     return false;

  if (BitfieldType->isEnumeralType()) {
    EnumDecl *BitfieldEnumDecl = BitfieldType->castAs<EnumType>()->getDecl();
    // If the underlying enum type was not explicitly specified as an unsigned
    // type and the enum contain only positive values, MSVC++ will cause an
    // inconsistency by storing this as a signed type.
    if (S.getLangOpts().CPlusPlus11 &&
        !BitfieldEnumDecl->getIntegerTypeSourceInfo() &&
        BitfieldEnumDecl->getNumPositiveBits() > 0 &&
        BitfieldEnumDecl->getNumNegativeBits() == 0) {
      S.Diag(InitLoc, diag::warn_no_underlying_type_specified_for_enum_bitfield)
          << BitfieldEnumDecl;
    }
  }

  // Ignore value- or type-dependent expressions.
  if (Bitfield->getBitWidth()->isValueDependent() ||
      Bitfield->getBitWidth()->isTypeDependent() ||
      Init->isValueDependent() ||
      Init->isTypeDependent())
    return false;

  Expr *OriginalInit = Init->IgnoreParenImpCasts();
  unsigned FieldWidth = Bitfield->getBitWidthValue();

  Expr::EvalResult Result;
  if (!OriginalInit->EvaluateAsInt(Result, S.Context,
                                   Expr::SE_AllowSideEffects)) {
    // The RHS is not constant.  If the RHS has an enum type, make sure the
    // bitfield is wide enough to hold all the values of the enum without
    // truncation.
    const auto *EnumTy = OriginalInit->getType()->getAs<EnumType>();
    const PreferredTypeAttr *PTAttr = nullptr;
    if (!EnumTy) {
      PTAttr = Bitfield->getAttr<PreferredTypeAttr>();
      if (PTAttr)
        EnumTy = PTAttr->getType()->getAs<EnumType>();
    }
    if (EnumTy) {
      EnumDecl *ED = EnumTy->getDecl();
      bool SignedBitfield = BitfieldType->isSignedIntegerOrEnumerationType();

      // Enum types are implicitly signed on Windows, so check if there are any
      // negative enumerators to see if the enum was intended to be signed or
      // not.
      bool SignedEnum = ED->getNumNegativeBits() > 0;

      // Check for surprising sign changes when assigning enum values to a
      // bitfield of different signedness.  If the bitfield is signed and we
      // have exactly the right number of bits to store this unsigned enum,
      // suggest changing the enum to an unsigned type. This typically happens
      // on Windows where unfixed enums always use an underlying type of 'int'.
      unsigned DiagID = 0;
      if (SignedEnum && !SignedBitfield) {
        DiagID =
            PTAttr == nullptr
                ? diag::warn_unsigned_bitfield_assigned_signed_enum
                : diag::
                      warn_preferred_type_unsigned_bitfield_assigned_signed_enum;
      } else if (SignedBitfield && !SignedEnum &&
                 ED->getNumPositiveBits() == FieldWidth) {
        DiagID =
            PTAttr == nullptr
                ? diag::warn_signed_bitfield_enum_conversion
                : diag::warn_preferred_type_signed_bitfield_enum_conversion;
      }
      if (DiagID) {
        S.Diag(InitLoc, DiagID) << Bitfield << ED;
        TypeSourceInfo *TSI = Bitfield->getTypeSourceInfo();
        SourceRange TypeRange =
            TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange();
        S.Diag(Bitfield->getTypeSpecStartLoc(), diag::note_change_bitfield_sign)
            << SignedEnum << TypeRange;
        if (PTAttr)
          S.Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
              << ED;
      }

      // Compute the required bitwidth. If the enum has negative values, we need
      // one more bit than the normal number of positive bits to represent the
      // sign bit.
      unsigned BitsNeeded = SignedEnum ? std::max(ED->getNumPositiveBits() + 1,
                                                  ED->getNumNegativeBits())
                                       : ED->getNumPositiveBits();

      // Check the bitwidth.
      if (BitsNeeded > FieldWidth) {
        Expr *WidthExpr = Bitfield->getBitWidth();
        auto DiagID =
            PTAttr == nullptr
                ? diag::warn_bitfield_too_small_for_enum
                : diag::warn_preferred_type_bitfield_too_small_for_enum;
        S.Diag(InitLoc, DiagID) << Bitfield << ED;
        S.Diag(WidthExpr->getExprLoc(), diag::note_widen_bitfield)
            << BitsNeeded << ED << WidthExpr->getSourceRange();
        if (PTAttr)
          S.Diag(PTAttr->getLocation(), diag::note_bitfield_preferred_type)
              << ED;
      }
    }

    return false;
  }

  llvm::APSInt Value = Result.Val.getInt();

  unsigned OriginalWidth = Value.getBitWidth();

  // In C, the macro 'true' from stdbool.h will evaluate to '1'; To reduce
  // false positives where the user is demonstrating they intend to use the
  // bit-field as a Boolean, check to see if the value is 1 and we're assigning
  // to a one-bit bit-field to see if the value came from a macro named 'true'.
  bool OneAssignedToOneBitBitfield = FieldWidth == 1 && Value == 1;
  if (OneAssignedToOneBitBitfield && !S.LangOpts.CPlusPlus) {
    SourceLocation MaybeMacroLoc = OriginalInit->getBeginLoc();
    if (S.SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
        S.findMacroSpelling(MaybeMacroLoc, "true"))
      return false;
  }

  if (!Value.isSigned() || Value.isNegative())
    if (UnaryOperator *UO = dyn_cast<UnaryOperator>(OriginalInit))
      if (UO->getOpcode() == UO_Minus || UO->getOpcode() == UO_Not)
        OriginalWidth = Value.getSignificantBits();

  if (OriginalWidth <= FieldWidth)
    return false;

  // Compute the value which the bitfield will contain.
  llvm::APSInt TruncatedValue = Value.trunc(FieldWidth);
  TruncatedValue.setIsSigned(BitfieldType->isSignedIntegerType());

  // Check whether the stored value is equal to the original value.
  TruncatedValue = TruncatedValue.extend(OriginalWidth);
  if (llvm::APSInt::isSameValue(Value, TruncatedValue))
    return false;

  std::string PrettyValue = toString(Value, 10);
  std::string PrettyTrunc = toString(TruncatedValue, 10);

  S.Diag(InitLoc, OneAssignedToOneBitBitfield
                      ? diag::warn_impcast_single_bit_bitield_precision_constant
                      : diag::warn_impcast_bitfield_precision_constant)
      << PrettyValue << PrettyTrunc << OriginalInit->getType()
      << Init->getSourceRange();

  return true;
}

/// Analyze the given simple or compound assignment for warning-worthy
/// operations.
static void AnalyzeAssignment(Sema &S, BinaryOperator *E) {
  // Just recurse on the LHS.
  AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());

  // We want to recurse on the RHS as normal unless we're assigning to
  // a bitfield.
  if (FieldDecl *Bitfield = E->getLHS()->getSourceBitField()) {
    if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(),
                                  E->getOperatorLoc())) {
      // Recurse, ignoring any implicit conversions on the RHS.
      return AnalyzeImplicitConversions(S, E->getRHS()->IgnoreParenImpCasts(),
                                        E->getOperatorLoc());
    }
  }

  AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());

  // Diagnose implicitly sequentially-consistent atomic assignment.
  if (E->getLHS()->getType()->isAtomicType())
    S.Diag(E->getRHS()->getBeginLoc(), diag::warn_atomic_implicit_seq_cst);
}

/// Diagnose an implicit cast;  purely a helper for CheckImplicitConversion.
static void DiagnoseImpCast(Sema &S, const Expr *E, QualType SourceType,
                            QualType T, SourceLocation CContext, unsigned diag,
                            bool PruneControlFlow = false) {
  // For languages like HLSL and OpenCL, implicit conversion diagnostics listing
  // address space annotations isn't really useful. The warnings aren't because
  // you're converting a `private int` to `unsigned int`, it is because you're
  // conerting `int` to `unsigned int`.
  if (SourceType.hasAddressSpace())
    SourceType = S.getASTContext().removeAddrSpaceQualType(SourceType);
  if (T.hasAddressSpace())
    T = S.getASTContext().removeAddrSpaceQualType(T);
  if (PruneControlFlow) {
    S.DiagRuntimeBehavior(E->getExprLoc(), E,
                          S.PDiag(diag)
                              << SourceType << T << E->getSourceRange()
                              << SourceRange(CContext));
    return;
  }
  S.Diag(E->getExprLoc(), diag)
    << SourceType << T << E->getSourceRange() << SourceRange(CContext);
}

/// Diagnose an implicit cast;  purely a helper for CheckImplicitConversion.
static void DiagnoseImpCast(Sema &S, const Expr *E, QualType T,
                            SourceLocation CContext, unsigned diag,
                            bool PruneControlFlow = false) {
  DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, PruneControlFlow);
}

/// Diagnose an implicit cast from a floating point value to an integer value.
static void DiagnoseFloatingImpCast(Sema &S, const Expr *E, QualType T,
                                    SourceLocation CContext) {
  bool IsBool = T->isSpecificBuiltinType(BuiltinType::Bool);
  bool PruneWarnings = S.inTemplateInstantiation();

  const Expr *InnerE = E->IgnoreParenImpCasts();
  // We also want to warn on, e.g., "int i = -1.234"
  if (const auto *UOp = dyn_cast<UnaryOperator>(InnerE))
    if (UOp->getOpcode() == UO_Minus || UOp->getOpcode() == UO_Plus)
      InnerE = UOp->getSubExpr()->IgnoreParenImpCasts();

  bool IsLiteral = isa<FloatingLiteral>(E) || isa<FloatingLiteral>(InnerE);

  llvm::APFloat Value(0.0);
  bool IsConstant =
    E->EvaluateAsFloat(Value, S.Context, Expr::SE_AllowSideEffects);
  if (!IsConstant) {
    if (S.ObjC().isSignedCharBool(T)) {
      return S.ObjC().adornBoolConversionDiagWithTernaryFixit(
          E, S.Diag(CContext, diag::warn_impcast_float_to_objc_signed_char_bool)
                 << E->getType());
    }

    return DiagnoseImpCast(S, E, T, CContext,
                           diag::warn_impcast_float_integer, PruneWarnings);
  }

  bool isExact = false;

  llvm::APSInt IntegerValue(S.Context.getIntWidth(T),
                            T->hasUnsignedIntegerRepresentation());
  llvm::APFloat::opStatus Result = Value.convertToInteger(
      IntegerValue, llvm::APFloat::rmTowardZero, &isExact);

  // FIXME: Force the precision of the source value down so we don't print
  // digits which are usually useless (we don't really care here if we
  // truncate a digit by accident in edge cases).  Ideally, APFloat::toString
  // would automatically print the shortest representation, but it's a bit
  // tricky to implement.
  SmallString<16> PrettySourceValue;
  unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics());
  precision = (precision * 59 + 195) / 196;
  Value.toString(PrettySourceValue, precision);

  if (S.ObjC().isSignedCharBool(T) && IntegerValue != 0 && IntegerValue != 1) {
    return S.ObjC().adornBoolConversionDiagWithTernaryFixit(
        E, S.Diag(CContext, diag::warn_impcast_constant_value_to_objc_bool)
               << PrettySourceValue);
  }

  if (Result == llvm::APFloat::opOK && isExact) {
    if (IsLiteral) return;
    return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer,
                           PruneWarnings);
  }

  // Conversion of a floating-point value to a non-bool integer where the
  // integral part cannot be represented by the integer type is undefined.
  if (!IsBool && Result == llvm::APFloat::opInvalidOp)
    return DiagnoseImpCast(
        S, E, T, CContext,
        IsLiteral ? diag::warn_impcast_literal_float_to_integer_out_of_range
                  : diag::warn_impcast_float_to_integer_out_of_range,
        PruneWarnings);

  unsigned DiagID = 0;
  if (IsLiteral) {
    // Warn on floating point literal to integer.
    DiagID = diag::warn_impcast_literal_float_to_integer;
  } else if (IntegerValue == 0) {
    if (Value.isZero()) {  // Skip -0.0 to 0 conversion.
      return DiagnoseImpCast(S, E, T, CContext,
                             diag::warn_impcast_float_integer, PruneWarnings);
    }
    // Warn on non-zero to zero conversion.
    DiagID = diag::warn_impcast_float_to_integer_zero;
  } else {
    if (IntegerValue.isUnsigned()) {
      if (!IntegerValue.isMaxValue()) {
        return DiagnoseImpCast(S, E, T, CContext,
                               diag::warn_impcast_float_integer, PruneWarnings);
      }
    } else {  // IntegerValue.isSigned()
      if (!IntegerValue.isMaxSignedValue() &&
          !IntegerValue.isMinSignedValue()) {
        return DiagnoseImpCast(S, E, T, CContext,
                               diag::warn_impcast_float_integer, PruneWarnings);
      }
    }
    // Warn on evaluatable floating point expression to integer conversion.
    DiagID = diag::warn_impcast_float_to_integer;
  }

  SmallString<16> PrettyTargetValue;
  if (IsBool)
    PrettyTargetValue = Value.isZero() ? "false" : "true";
  else
    IntegerValue.toString(PrettyTargetValue);

  if (PruneWarnings) {
    S.DiagRuntimeBehavior(E->getExprLoc(), E,
                          S.PDiag(DiagID)
                              << E->getType() << T.getUnqualifiedType()
                              << PrettySourceValue << PrettyTargetValue
                              << E->getSourceRange() << SourceRange(CContext));
  } else {
    S.Diag(E->getExprLoc(), DiagID)
        << E->getType() << T.getUnqualifiedType() << PrettySourceValue
        << PrettyTargetValue << E->getSourceRange() << SourceRange(CContext);
  }
}

static void CheckCommaOperand(Sema &S, Expr *E, QualType T, SourceLocation CC,
                              bool ExtraCheckForImplicitConversion) {
  E = E->IgnoreParenImpCasts();
  AnalyzeImplicitConversions(S, E, CC);

  if (ExtraCheckForImplicitConversion && E->getType() != T)
    S.CheckImplicitConversion(E, T, CC);
}

/// Analyze the given compound assignment for the possible losing of
/// floating-point precision.
static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) {
  assert(isa<CompoundAssignOperator>(E) &&
         "Must be compound assignment operation");
  // Recurse on the LHS and RHS in here
  AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc());
  AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc());

  if (E->getLHS()->getType()->isAtomicType())
    S.Diag(E->getOperatorLoc(), diag::warn_atomic_implicit_seq_cst);

  // Now check the outermost expression
  const auto *ResultBT = E->getLHS()->getType()->getAs<BuiltinType>();
  const auto *RBT = cast<CompoundAssignOperator>(E)
                        ->getComputationResultType()
                        ->getAs<BuiltinType>();

  // The below checks assume source is floating point.
  if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return;

  // If source is floating point but target is an integer.
  if (ResultBT->isInteger())
    return DiagnoseImpCast(S, E, E->getRHS()->getType(), E->getLHS()->getType(),
                           E->getExprLoc(), diag::warn_impcast_float_integer);

  if (!ResultBT->isFloatingPoint())
    return;

  // If both source and target are floating points, warn about losing precision.
  int Order = S.getASTContext().getFloatingTypeSemanticOrder(
      QualType(ResultBT, 0), QualType(RBT, 0));
  if (Order < 0 && !S.SourceMgr.isInSystemMacro(E->getOperatorLoc()))
    // warn about dropping FP rank.
    DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(),
                    diag::warn_impcast_float_result_precision);
}

static std::string PrettyPrintInRange(const llvm::APSInt &Value,
                                      IntRange Range) {
  if (!Range.Width) return "0";

  llvm::APSInt ValueInRange = Value;
  ValueInRange.setIsSigned(!Range.NonNegative);
  ValueInRange = ValueInRange.trunc(Range.Width);
  return toString(ValueInRange, 10);
}

static bool IsImplicitBoolFloatConversion(Sema &S, const Expr *Ex,
                                          bool ToBool) {
  if (!isa<ImplicitCastExpr>(Ex))
    return false;

  const Expr *InnerE = Ex->IgnoreParenImpCasts();
  const Type *Target = S.Context.getCanonicalType(Ex->getType()).getTypePtr();
  const Type *Source =
    S.Context.getCanonicalType(InnerE->getType()).getTypePtr();
  if (Target->isDependentType())
    return false;

  const auto *FloatCandidateBT =
      dyn_cast<BuiltinType>(ToBool ? Source : Target);
  const Type *BoolCandidateType = ToBool ? Target : Source;

  return (BoolCandidateType->isSpecificBuiltinType(BuiltinType::Bool) &&
          FloatCandidateBT && (FloatCandidateBT->isFloatingPoint()));
}

static void CheckImplicitArgumentConversions(Sema &S, const CallExpr *TheCall,
                                             SourceLocation CC) {
  for (unsigned I = 0, N = TheCall->getNumArgs(); I < N; ++I) {
    const Expr *CurrA = TheCall->getArg(I);
    if (!IsImplicitBoolFloatConversion(S, CurrA, true))
      continue;

    bool IsSwapped = ((I > 0) && IsImplicitBoolFloatConversion(
                                     S, TheCall->getArg(I - 1), false));
    IsSwapped |= ((I < (N - 1)) && IsImplicitBoolFloatConversion(
                                       S, TheCall->getArg(I + 1), false));
    if (IsSwapped) {
      // Warn on this floating-point to bool conversion.
      DiagnoseImpCast(S, CurrA->IgnoreParenImpCasts(),
                      CurrA->getType(), CC,
                      diag::warn_impcast_floating_point_to_bool);
    }
  }
}

static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T,
                                   SourceLocation CC) {
  // Don't warn on functions which have return type nullptr_t.
  if (isa<CallExpr>(E))
    return;

  // Check for NULL (GNUNull) or nullptr (CXX11_nullptr).
  const Expr *NewE = E->IgnoreParenImpCasts();
  bool IsGNUNullExpr = isa<GNUNullExpr>(NewE);
  bool HasNullPtrType = NewE->getType()->isNullPtrType();
  if (!IsGNUNullExpr && !HasNullPtrType)
    return;

  // Return if target type is a safe conversion.
  if (T->isAnyPointerType() || T->isBlockPointerType() ||
      T->isMemberPointerType() || !T->isScalarType() || T->isNullPtrType())
    return;

  if (S.Diags.isIgnored(diag::warn_impcast_null_pointer_to_integer,
                        E->getExprLoc()))
    return;

  SourceLocation Loc = E->getSourceRange().getBegin();

  // Venture through the macro stacks to get to the source of macro arguments.
  // The new location is a better location than the complete location that was
  // passed in.
  Loc = S.SourceMgr.getTopMacroCallerLoc(Loc);
  CC = S.SourceMgr.getTopMacroCallerLoc(CC);

  // __null is usually wrapped in a macro.  Go up a macro if that is the case.
  if (IsGNUNullExpr && Loc.isMacroID()) {
    StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics(
        Loc, S.SourceMgr, S.getLangOpts());
    if (MacroName == "NULL")
      Loc = S.SourceMgr.getImmediateExpansionRange(Loc).getBegin();
  }

  // Only warn if the null and context location are in the same macro expansion.
  if (S.SourceMgr.getFileID(Loc) != S.SourceMgr.getFileID(CC))
    return;

  S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer)
      << HasNullPtrType << T << SourceRange(CC)
      << FixItHint::CreateReplacement(Loc,
                                      S.getFixItZeroLiteralForType(T, Loc));
}

// Helper function to filter out cases for constant width constant conversion.
// Don't warn on char array initialization or for non-decimal values.
static bool isSameWidthConstantConversion(Sema &S, Expr *E, QualType T,
                                          SourceLocation CC) {
  // If initializing from a constant, and the constant starts with '0',
  // then it is a binary, octal, or hexadecimal.  Allow these constants
  // to fill all the bits, even if there is a sign change.
  if (auto *IntLit = dyn_cast<IntegerLiteral>(E->IgnoreParenImpCasts())) {
    const char FirstLiteralCharacter =
        S.getSourceManager().getCharacterData(IntLit->getBeginLoc())[0];
    if (FirstLiteralCharacter == '0')
      return false;
  }

  // If the CC location points to a '{', and the type is char, then assume
  // assume it is an array initialization.
  if (CC.isValid() && T->isCharType()) {
    const char FirstContextCharacter =
        S.getSourceManager().getCharacterData(CC)[0];
    if (FirstContextCharacter == '{')
      return false;
  }

  return true;
}

static const IntegerLiteral *getIntegerLiteral(Expr *E) {
  const auto *IL = dyn_cast<IntegerLiteral>(E);
  if (!IL) {
    if (auto *UO = dyn_cast<UnaryOperator>(E)) {
      if (UO->getOpcode() == UO_Minus)
        return dyn_cast<IntegerLiteral>(UO->getSubExpr());
    }
  }

  return IL;
}

static void DiagnoseIntInBoolContext(Sema &S, Expr *E) {
  E = E->IgnoreParenImpCasts();
  SourceLocation ExprLoc = E->getExprLoc();

  if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
    BinaryOperator::Opcode Opc = BO->getOpcode();
    Expr::EvalResult Result;
    // Do not diagnose unsigned shifts.
    if (Opc == BO_Shl) {
      const auto *LHS = getIntegerLiteral(BO->getLHS());
      const auto *RHS = getIntegerLiteral(BO->getRHS());
      if (LHS && LHS->getValue() == 0)
        S.Diag(ExprLoc, diag::warn_left_shift_always) << 0;
      else if (!E->isValueDependent() && LHS && RHS &&
               RHS->getValue().isNonNegative() &&
               E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects))
        S.Diag(ExprLoc, diag::warn_left_shift_always)
            << (Result.Val.getInt() != 0);
      else if (E->getType()->isSignedIntegerType())
        S.Diag(ExprLoc, diag::warn_left_shift_in_bool_context)
            << FixItHint::CreateInsertion(E->getBeginLoc(), "(")
            << FixItHint::CreateInsertion(S.getLocForEndOfToken(E->getEndLoc()),
                                          ") != 0");
    }
  }

  if (const auto *CO = dyn_cast<ConditionalOperator>(E)) {
    const auto *LHS = getIntegerLiteral(CO->getTrueExpr());
    const auto *RHS = getIntegerLiteral(CO->getFalseExpr());
    if (!LHS || !RHS)
      return;
    if ((LHS->getValue() == 0 || LHS->getValue() == 1) &&
        (RHS->getValue() == 0 || RHS->getValue() == 1))
      // Do not diagnose common idioms.
      return;
    if (LHS->getValue() != 0 && RHS->getValue() != 0)
      S.Diag(ExprLoc, diag::warn_integer_constants_in_conditional_always_true);
  }
}

static void DiagnoseMixedUnicodeImplicitConversion(Sema &S, const Type *Source,
                                                   const Type *Target, Expr *E,
                                                   QualType T,
                                                   SourceLocation CC) {
  assert(Source->isUnicodeCharacterType() && Target->isUnicodeCharacterType() &&
         Source != Target);
  Expr::EvalResult Result;
  if (E->EvaluateAsInt(Result, S.getASTContext(), Expr::SE_AllowSideEffects,
                       S.isConstantEvaluatedContext())) {
    llvm::APSInt Value(32);
    Value = Result.Val.getInt();
    bool IsASCII = Value <= 0x7F;
    bool IsBMP = Value <= 0xD7FF || (Value >= 0xE000 && Value <= 0xFFFF);
    bool ConversionPreservesSemantics =
        IsASCII || (!Source->isChar8Type() && !Target->isChar8Type() && IsBMP);

    if (!ConversionPreservesSemantics) {
      auto IsSingleCodeUnitCP = [](const QualType &T,
                                   const llvm::APSInt &Value) {
        if (T->isChar8Type())
          return llvm::IsSingleCodeUnitUTF8Codepoint(Value.getExtValue());
        if (T->isChar16Type())
          return llvm::IsSingleCodeUnitUTF16Codepoint(Value.getExtValue());
        assert(T->isChar32Type());
        return llvm::IsSingleCodeUnitUTF32Codepoint(Value.getExtValue());
      };

      S.Diag(CC, diag::warn_impcast_unicode_char_type_constant)
          << E->getType() << T
          << IsSingleCodeUnitCP(E->getType().getUnqualifiedType(), Value)
          << FormatUTFCodeUnitAsCodepoint(Value.getExtValue(), E->getType());
    }
  } else {
    bool LosesPrecision = S.getASTContext().getIntWidth(E->getType()) >
                          S.getASTContext().getIntWidth(T);
    DiagnoseImpCast(S, E, T, CC,
                    LosesPrecision ? diag::warn_impcast_unicode_precision
                                   : diag::warn_impcast_unicode_char_type);
  }
}

void Sema::CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC,
                                   bool *ICContext, bool IsListInit) {
  if (E->isTypeDependent() || E->isValueDependent()) return;

  const Type *Source = Context.getCanonicalType(E->getType()).getTypePtr();
  const Type *Target = Context.getCanonicalType(T).getTypePtr();
  if (Source == Target) return;
  if (Target->isDependentType()) return;

  // If the conversion context location is invalid don't complain. We also
  // don't want to emit a warning if the issue occurs from the expansion of
  // a system macro. The problem is that 'getSpellingLoc()' is slow, so we
  // delay this check as long as possible. Once we detect we are in that
  // scenario, we just return.
  if (CC.isInvalid())
    return;

  if (Source->isAtomicType())
    Diag(E->getExprLoc(), diag::warn_atomic_implicit_seq_cst);

  // Diagnose implicit casts to bool.
  if (Target->isSpecificBuiltinType(BuiltinType::Bool)) {
    if (isa<StringLiteral>(E))
      // Warn on string literal to bool.  Checks for string literals in logical
      // and expressions, for instance, assert(0 && "error here"), are
      // prevented by a check in AnalyzeImplicitConversions().
      return DiagnoseImpCast(*this, E, T, CC,
                             diag::warn_impcast_string_literal_to_bool);
    if (isa<ObjCStringLiteral>(E) || isa<ObjCArrayLiteral>(E) ||
        isa<ObjCDictionaryLiteral>(E) || isa<ObjCBoxedExpr>(E)) {
      // This covers the literal expressions that evaluate to Objective-C
      // objects.
      return DiagnoseImpCast(*this, E, T, CC,
                             diag::warn_impcast_objective_c_literal_to_bool);
    }
    if (Source->isPointerType() || Source->canDecayToPointerType()) {
      // Warn on pointer to bool conversion that is always true.
      DiagnoseAlwaysNonNullPointer(E, Expr::NPCK_NotNull, /*IsEqual*/ false,
                                   SourceRange(CC));
    }
  }

  // If the we're converting a constant to an ObjC BOOL on a platform where BOOL
  // is a typedef for signed char (macOS), then that constant value has to be 1
  // or 0.
  if (ObjC().isSignedCharBool(T) && Source->isIntegralType(Context)) {
    Expr::EvalResult Result;
    if (E->EvaluateAsInt(Result, getASTContext(), Expr::SE_AllowSideEffects)) {
      if (Result.Val.getInt() != 1 && Result.Val.getInt() != 0) {
        ObjC().adornBoolConversionDiagWithTernaryFixit(
            E, Diag(CC, diag::warn_impcast_constant_value_to_objc_bool)
                   << toString(Result.Val.getInt(), 10));
      }
      return;
    }
  }

  // Check implicit casts from Objective-C collection literals to specialized
  // collection types, e.g., NSArray<NSString *> *.
  if (auto *ArrayLiteral = dyn_cast<ObjCArrayLiteral>(E))
    ObjC().checkArrayLiteral(QualType(Target, 0), ArrayLiteral);
  else if (auto *DictionaryLiteral = dyn_cast<ObjCDictionaryLiteral>(E))
    ObjC().checkDictionaryLiteral(QualType(Target, 0), DictionaryLiteral);

  // Strip vector types.
  if (isa<VectorType>(Source)) {
    if (Target->isSveVLSBuiltinType() &&
        (Context.areCompatibleSveTypes(QualType(Target, 0),
                                       QualType(Source, 0)) ||
         Context.areLaxCompatibleSveTypes(QualType(Target, 0),
                                          QualType(Source, 0))))
      return;

    if (Target->isRVVVLSBuiltinType() &&
        (Context.areCompatibleRVVTypes(QualType(Target, 0),
                                       QualType(Source, 0)) ||
         Context.areLaxCompatibleRVVTypes(QualType(Target, 0),
                                          QualType(Source, 0))))
      return;

    if (!isa<VectorType>(Target)) {
      if (SourceMgr.isInSystemMacro(CC))
        return;
      return DiagnoseImpCast(*this, E, T, CC, diag::warn_impcast_vector_scalar);
    } else if (getLangOpts().HLSL &&
               Target->castAs<VectorType>()->getNumElements() <
                   Source->castAs<VectorType>()->getNumElements()) {
      // Diagnose vector truncation but don't return. We may also want to
      // diagnose an element conversion.
      DiagnoseImpCast(*this, E, T, CC,
                      diag::warn_hlsl_impcast_vector_truncation);
    }

    // If the vector cast is cast between two vectors of the same size, it is
    // a bitcast, not a conversion, except under HLSL where it is a conversion.
    if (!getLangOpts().HLSL &&
        Context.getTypeSize(Source) == Context.getTypeSize(Target))
      return;

    Source = cast<VectorType>(Source)->getElementType().getTypePtr();
    Target = cast<VectorType>(Target)->getElementType().getTypePtr();
  }
  if (auto VecTy = dyn_cast<VectorType>(Target))
    Target = VecTy->getElementType().getTypePtr();

  // Strip complex types.
  if (isa<ComplexType>(Source)) {
    if (!isa<ComplexType>(Target)) {
      if (SourceMgr.isInSystemMacro(CC) || Target->isBooleanType())
        return;

      return DiagnoseImpCast(*this, E, T, CC,
                             getLangOpts().CPlusPlus
                                 ? diag::err_impcast_complex_scalar
                                 : diag::warn_impcast_complex_scalar);
    }

    Source = cast<ComplexType>(Source)->getElementType().getTypePtr();
    Target = cast<ComplexType>(Target)->getElementType().getTypePtr();
  }

  const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source);
  const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target);

  // Strip SVE vector types
  if (SourceBT && SourceBT->isSveVLSBuiltinType()) {
    // Need the original target type for vector type checks
    const Type *OriginalTarget = Context.getCanonicalType(T).getTypePtr();
    // Handle conversion from scalable to fixed when msve-vector-bits is
    // specified
    if (Context.areCompatibleSveTypes(QualType(OriginalTarget, 0),
                                      QualType(Source, 0)) ||
        Context.areLaxCompatibleSveTypes(QualType(OriginalTarget, 0),
                                         QualType(Source, 0)))
      return;

    // If the vector cast is cast between two vectors of the same size, it is
    // a bitcast, not a conversion.
    if (Context.getTypeSize(Source) == Context.getTypeSize(Target))
      return;

    Source = SourceBT->getSveEltType(Context).getTypePtr();
  }

  if (TargetBT && TargetBT->isSveVLSBuiltinType())
    Target = TargetBT->getSveEltType(Context).getTypePtr();

  // If the source is floating point...
  if (SourceBT && SourceBT->isFloatingPoint()) {
    // ...and the target is floating point...
    if (TargetBT && TargetBT->isFloatingPoint()) {
      // ...then warn if we're dropping FP rank.

      int Order = getASTContext().getFloatingTypeSemanticOrder(
          QualType(SourceBT, 0), QualType(TargetBT, 0));
      if (Order > 0) {
        // Don't warn about float constants that are precisely
        // representable in the target type.
        Expr::EvalResult result;
        if (E->EvaluateAsRValue(result, Context)) {
          // Value might be a float, a float vector, or a float complex.
          if (IsSameFloatAfterCast(
                  result.Val,
                  Context.getFloatTypeSemantics(QualType(TargetBT, 0)),
                  Context.getFloatTypeSemantics(QualType(SourceBT, 0))))
            return;
        }

        if (SourceMgr.isInSystemMacro(CC))
          return;

        DiagnoseImpCast(*this, E, T, CC, diag::warn_impcast_float_precision);
      }
      // ... or possibly if we're increasing rank, too
      else if (Order < 0) {
        if (SourceMgr.isInSystemMacro(CC))
          return;

        DiagnoseImpCast(*this, E, T, CC, diag::warn_impcast_double_promotion);
      }
      return;
    }

    // If the target is integral, always warn.
    if (TargetBT && TargetBT->isInteger()) {
      if (SourceMgr.isInSystemMacro(CC))
        return;

      DiagnoseFloatingImpCast(*this, E, T, CC);
    }

    // Detect the case where a call result is converted from floating-point to
    // to bool, and the final argument to the call is converted from bool, to
    // discover this typo:
    //
    //    bool b = fabs(x < 1.0);  // should be "bool b = fabs(x) < 1.0;"
    //
    // FIXME: This is an incredibly special case; is there some more general
    // way to detect this class of misplaced-parentheses bug?
    if (Target->isBooleanType() && isa<CallExpr>(E)) {
      // Check last argument of function call to see if it is an
      // implicit cast from a type matching the type the result
      // is being cast to.
      CallExpr *CEx = cast<CallExpr>(E);
      if (unsigned NumArgs = CEx->getNumArgs()) {
        Expr *LastA = CEx->getArg(NumArgs - 1);
        Expr *InnerE = LastA->IgnoreParenImpCasts();
        if (isa<ImplicitCastExpr>(LastA) &&
            InnerE->getType()->isBooleanType()) {
          // Warn on this floating-point to bool conversion
          DiagnoseImpCast(*this, E, T, CC,
                          diag::warn_impcast_floating_point_to_bool);
        }
      }
    }
    return;
  }

  // Valid casts involving fixed point types should be accounted for here.
  if (Source->isFixedPointType()) {
    if (Target->isUnsaturatedFixedPointType()) {
      Expr::EvalResult Result;
      if (E->EvaluateAsFixedPoint(Result, Context, Expr::SE_AllowSideEffects,
                                  isConstantEvaluatedContext())) {
        llvm::APFixedPoint Value = Result.Val.getFixedPoint();
        llvm::APFixedPoint MaxVal = Context.getFixedPointMax(T);
        llvm::APFixedPoint MinVal = Context.getFixedPointMin(T);
        if (Value > MaxVal || Value < MinVal) {
          DiagRuntimeBehavior(E->getExprLoc(), E,
                              PDiag(diag::warn_impcast_fixed_point_range)
                                  << Value.toString() << T
                                  << E->getSourceRange()
                                  << clang::SourceRange(CC));
          return;
        }
      }
    } else if (Target->isIntegerType()) {
      Expr::EvalResult Result;
      if (!isConstantEvaluatedContext() &&
          E->EvaluateAsFixedPoint(Result, Context, Expr::SE_AllowSideEffects)) {
        llvm::APFixedPoint FXResult = Result.Val.getFixedPoint();

        bool Overflowed;
        llvm::APSInt IntResult = FXResult.convertToInt(
            Context.getIntWidth(T), Target->isSignedIntegerOrEnumerationType(),
            &Overflowed);

        if (Overflowed) {
          DiagRuntimeBehavior(E->getExprLoc(), E,
                              PDiag(diag::warn_impcast_fixed_point_range)
                                  << FXResult.toString() << T
                                  << E->getSourceRange()
                                  << clang::SourceRange(CC));
          return;
        }
      }
    }
  } else if (Target->isUnsaturatedFixedPointType()) {
    if (Source->isIntegerType()) {
      Expr::EvalResult Result;
      if (!isConstantEvaluatedContext() &&
          E->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects)) {
        llvm::APSInt Value = Result.Val.getInt();

        bool Overflowed;
        llvm::APFixedPoint IntResult = llvm::APFixedPoint::getFromIntValue(
            Value, Context.getFixedPointSemantics(T), &Overflowed);

        if (Overflowed) {
          DiagRuntimeBehavior(E->getExprLoc(), E,
                              PDiag(diag::warn_impcast_fixed_point_range)
                                  << toString(Value, /*Radix=*/10) << T
                                  << E->getSourceRange()
                                  << clang::SourceRange(CC));
          return;
        }
      }
    }
  }

  // If we are casting an integer type to a floating point type without
  // initialization-list syntax, we might lose accuracy if the floating
  // point type has a narrower significand than the integer type.
  if (SourceBT && TargetBT && SourceBT->isIntegerType() &&
      TargetBT->isFloatingType() && !IsListInit) {
    // Determine the number of precision bits in the source integer type.
    std::optional<IntRange> SourceRange =
        TryGetExprRange(Context, E, isConstantEvaluatedContext(),
                        /*Approximate=*/true);
    if (!SourceRange)
      return;
    unsigned int SourcePrecision = SourceRange->Width;

    // Determine the number of precision bits in the
    // target floating point type.
    unsigned int TargetPrecision = llvm::APFloatBase::semanticsPrecision(
        Context.getFloatTypeSemantics(QualType(TargetBT, 0)));

    if (SourcePrecision > 0 && TargetPrecision > 0 &&
        SourcePrecision > TargetPrecision) {

      if (std::optional<llvm::APSInt> SourceInt =
              E->getIntegerConstantExpr(Context)) {
        // If the source integer is a constant, convert it to the target
        // floating point type. Issue a warning if the value changes
        // during the whole conversion.
        llvm::APFloat TargetFloatValue(
            Context.getFloatTypeSemantics(QualType(TargetBT, 0)));
        llvm::APFloat::opStatus ConversionStatus =
            TargetFloatValue.convertFromAPInt(
                *SourceInt, SourceBT->isSignedInteger(),
                llvm::APFloat::rmNearestTiesToEven);

        if (ConversionStatus != llvm::APFloat::opOK) {
          SmallString<32> PrettySourceValue;
          SourceInt->toString(PrettySourceValue, 10);
          SmallString<32> PrettyTargetValue;
          TargetFloatValue.toString(PrettyTargetValue, TargetPrecision);

          DiagRuntimeBehavior(
              E->getExprLoc(), E,
              PDiag(diag::warn_impcast_integer_float_precision_constant)
                  << PrettySourceValue << PrettyTargetValue << E->getType() << T
                  << E->getSourceRange() << clang::SourceRange(CC));
        }
      } else {
        // Otherwise, the implicit conversion may lose precision.
        DiagnoseImpCast(*this, E, T, CC,
                        diag::warn_impcast_integer_float_precision);
      }
    }
  }

  DiagnoseNullConversion(*this, E, T, CC);

  DiscardMisalignedMemberAddress(Target, E);

  if (Source->isUnicodeCharacterType() && Target->isUnicodeCharacterType()) {
    DiagnoseMixedUnicodeImplicitConversion(*this, Source, Target, E, T, CC);
    return;
  }

  if (Target->isBooleanType())
    DiagnoseIntInBoolContext(*this, E);

  if (!Source->isIntegerType() || !Target->isIntegerType())
    return;

  // TODO: remove this early return once the false positives for constant->bool
  // in templates, macros, etc, are reduced or removed.
  if (Target->isSpecificBuiltinType(BuiltinType::Bool))
    return;

  if (ObjC().isSignedCharBool(T) && !Source->isCharType() &&
      !E->isKnownToHaveBooleanValue(/*Semantic=*/false)) {
    return ObjC().adornBoolConversionDiagWithTernaryFixit(
        E, Diag(CC, diag::warn_impcast_int_to_objc_signed_char_bool)
               << E->getType());
  }
  std::optional<IntRange> LikelySourceRange = TryGetExprRange(
      Context, E, isConstantEvaluatedContext(), /*Approximate=*/true);
  if (!LikelySourceRange)
    return;

  IntRange SourceTypeRange =
      IntRange::forTargetOfCanonicalType(Context, Source);
  IntRange TargetRange = IntRange::forTargetOfCanonicalType(Context, Target);

  if (LikelySourceRange->Width > TargetRange.Width) {
    // If the source is a constant, use a default-on diagnostic.
    // TODO: this should happen for bitfield stores, too.
    Expr::EvalResult Result;
    if (E->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects,
                         isConstantEvaluatedContext())) {
      llvm::APSInt Value(32);
      Value = Result.Val.getInt();

      if (SourceMgr.isInSystemMacro(CC))
        return;

      std::string PrettySourceValue = toString(Value, 10);
      std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);

      DiagRuntimeBehavior(E->getExprLoc(), E,
                          PDiag(diag::warn_impcast_integer_precision_constant)
                              << PrettySourceValue << PrettyTargetValue
                              << E->getType() << T << E->getSourceRange()
                              << SourceRange(CC));
      return;
    }

    // People want to build with -Wshorten-64-to-32 and not -Wconversion.
    if (SourceMgr.isInSystemMacro(CC))
      return;

    if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
      if (UO->getOpcode() == UO_Minus)
        return DiagnoseImpCast(
            *this, E, T, CC, diag::warn_impcast_integer_precision_on_negation);
    }

    if (TargetRange.Width == 32 && Context.getIntWidth(E->getType()) == 64)
      return DiagnoseImpCast(*this, E, T, CC, diag::warn_impcast_integer_64_32,
                             /* pruneControlFlow */ true);
    return DiagnoseImpCast(*this, E, T, CC,
                           diag::warn_impcast_integer_precision);
  }

  if (TargetRange.Width > SourceTypeRange.Width) {
    if (auto *UO = dyn_cast<UnaryOperator>(E))
      if (UO->getOpcode() == UO_Minus)
        if (Source->isUnsignedIntegerType()) {
          if (Target->isUnsignedIntegerType())
            return DiagnoseImpCast(*this, E, T, CC,
                                   diag::warn_impcast_high_order_zero_bits);
          if (Target->isSignedIntegerType())
            return DiagnoseImpCast(*this, E, T, CC,
                                   diag::warn_impcast_nonnegative_result);
        }
  }

  if (TargetRange.Width == LikelySourceRange->Width &&
      !TargetRange.NonNegative && LikelySourceRange->NonNegative &&
      Source->isSignedIntegerType()) {
    // Warn when doing a signed to signed conversion, warn if the positive
    // source value is exactly the width of the target type, which will
    // cause a negative value to be stored.

    Expr::EvalResult Result;
    if (E->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects) &&
        !SourceMgr.isInSystemMacro(CC)) {
      llvm::APSInt Value = Result.Val.getInt();
      if (isSameWidthConstantConversion(*this, E, T, CC)) {
        std::string PrettySourceValue = toString(Value, 10);
        std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);

        Diag(E->getExprLoc(),
             PDiag(diag::warn_impcast_integer_precision_constant)
                 << PrettySourceValue << PrettyTargetValue << E->getType() << T
                 << E->getSourceRange() << SourceRange(CC));
        return;
      }
    }

    // Fall through for non-constants to give a sign conversion warning.
  }

  if ((!isa<EnumType>(Target) || !isa<EnumType>(Source)) &&
      ((TargetRange.NonNegative && !LikelySourceRange->NonNegative) ||
       (!TargetRange.NonNegative && LikelySourceRange->NonNegative &&
        LikelySourceRange->Width == TargetRange.Width))) {
    if (SourceMgr.isInSystemMacro(CC))
      return;

    if (SourceBT && SourceBT->isInteger() && TargetBT &&
        TargetBT->isInteger() &&
        Source->isSignedIntegerType() == Target->isSignedIntegerType()) {
      return;
    }

    unsigned DiagID = diag::warn_impcast_integer_sign;

    // Traditionally, gcc has warned about this under -Wsign-compare.
    // We also want to warn about it in -Wconversion.
    // So if -Wconversion is off, use a completely identical diagnostic
    // in the sign-compare group.
    // The conditional-checking code will
    if (ICContext) {
      DiagID = diag::warn_impcast_integer_sign_conditional;
      *ICContext = true;
    }

    DiagnoseImpCast(*this, E, T, CC, DiagID);
  }

  // If we're implicitly converting from an integer into an enumeration, that
  // is valid in C but invalid in C++.
  QualType SourceType = E->getEnumCoercedType(Context);
  const BuiltinType *CoercedSourceBT = SourceType->getAs<BuiltinType>();
  if (CoercedSourceBT && CoercedSourceBT->isInteger() && isa<EnumType>(Target))
    return DiagnoseImpCast(*this, E, T, CC, diag::warn_impcast_int_to_enum);

  // Diagnose conversions between different enumeration types.
  // In C, we pretend that the type of an EnumConstantDecl is its enumeration
  // type, to give us better diagnostics.
  Source = Context.getCanonicalType(SourceType).getTypePtr();

  if (const EnumType *SourceEnum = Source->getAs<EnumType>())
    if (const EnumType *TargetEnum = Target->getAs<EnumType>())
      if (SourceEnum->getDecl()->hasNameForLinkage() &&
          TargetEnum->getDecl()->hasNameForLinkage() &&
          SourceEnum != TargetEnum) {
        if (SourceMgr.isInSystemMacro(CC))
          return;

        return DiagnoseImpCast(*this, E, SourceType, T, CC,
                               diag::warn_impcast_different_enum_types);
      }
}

static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E,
                                     SourceLocation CC, QualType T);

static void CheckConditionalOperand(Sema &S, Expr *E, QualType T,
                                    SourceLocation CC, bool &ICContext) {
  E = E->IgnoreParenImpCasts();
  // Diagnose incomplete type for second or third operand in C.
  if (!S.getLangOpts().CPlusPlus && E->getType()->isRecordType())
    S.RequireCompleteExprType(E, diag::err_incomplete_type);

  if (auto *CO = dyn_cast<AbstractConditionalOperator>(E))
    return CheckConditionalOperator(S, CO, CC, T);

  AnalyzeImplicitConversions(S, E, CC);
  if (E->getType() != T)
    return S.CheckImplicitConversion(E, T, CC, &ICContext);
}

static void CheckConditionalOperator(Sema &S, AbstractConditionalOperator *E,
                                     SourceLocation CC, QualType T) {
  AnalyzeImplicitConversions(S, E->getCond(), E->getQuestionLoc());

  Expr *TrueExpr = E->getTrueExpr();
  if (auto *BCO = dyn_cast<BinaryConditionalOperator>(E))
    TrueExpr = BCO->getCommon();

  bool Suspicious = false;
  CheckConditionalOperand(S, TrueExpr, T, CC, Suspicious);
  CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious);

  if (T->isBooleanType())
    DiagnoseIntInBoolContext(S, E);

  // If -Wconversion would have warned about either of the candidates
  // for a signedness conversion to the context type...
  if (!Suspicious) return;

  // ...but it's currently ignored...
  if (!S.Diags.isIgnored(diag::warn_impcast_integer_sign_conditional, CC))
    return;

  // ...then check whether it would have warned about either of the
  // candidates for a signedness conversion to the condition type.
  if (E->getType() == T) return;

  Suspicious = false;
  S.CheckImplicitConversion(TrueExpr->IgnoreParenImpCasts(), E->getType(), CC,
                            &Suspicious);
  if (!Suspicious)
    S.CheckImplicitConversion(E->getFalseExpr()->IgnoreParenImpCasts(),
                              E->getType(), CC, &Suspicious);
}

/// Check conversion of given expression to boolean.
/// Input argument E is a logical expression.
static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) {
  // Run the bool-like conversion checks only for C since there bools are
  // still not used as the return type from "boolean" operators or as the input
  // type for conditional operators.
  if (S.getLangOpts().CPlusPlus)
    return;
  if (E->IgnoreParenImpCasts()->getType()->isAtomicType())
    return;
  S.CheckImplicitConversion(E->IgnoreParenImpCasts(), S.Context.BoolTy, CC);
}

namespace {
struct AnalyzeImplicitConversionsWorkItem {
  Expr *E;
  SourceLocation CC;
  bool IsListInit;
};
}

/// Data recursive variant of AnalyzeImplicitConversions. Subexpressions
/// that should be visited are added to WorkList.
static void AnalyzeImplicitConversions(
    Sema &S, AnalyzeImplicitConversionsWorkItem Item,
    llvm::SmallVectorImpl<AnalyzeImplicitConversionsWorkItem> &WorkList) {
  Expr *OrigE = Item.E;
  SourceLocation CC = Item.CC;

  QualType T = OrigE->getType();
  Expr *E = OrigE->IgnoreParenImpCasts();

  // Propagate whether we are in a C++ list initialization expression.
  // If so, we do not issue warnings for implicit int-float conversion
  // precision loss, because C++11 narrowing already handles it.
  //
  // HLSL's initialization lists are special, so they shouldn't observe the C++
  // behavior here.
  bool IsListInit =
      Item.IsListInit || (isa<InitListExpr>(OrigE) &&
                          S.getLangOpts().CPlusPlus && !S.getLangOpts().HLSL);

  if (E->isTypeDependent() || E->isValueDependent())
    return;

  Expr *SourceExpr = E;
  // Examine, but don't traverse into the source expression of an
  // OpaqueValueExpr, since it may have multiple parents and we don't want to
  // emit duplicate diagnostics. Its fine to examine the form or attempt to
  // evaluate it in the context of checking the specific conversion to T though.
  if (auto *OVE = dyn_cast<OpaqueValueExpr>(E))
    if (auto *Src = OVE->getSourceExpr())
      SourceExpr = Src;

  if (const auto *UO = dyn_cast<UnaryOperator>(SourceExpr))
    if (UO->getOpcode() == UO_Not &&
        UO->getSubExpr()->isKnownToHaveBooleanValue())
      S.Diag(UO->getBeginLoc(), diag::warn_bitwise_negation_bool)
          << OrigE->getSourceRange() << T->isBooleanType()
          << FixItHint::CreateReplacement(UO->getBeginLoc(), "!");

  if (auto *BO = dyn_cast<BinaryOperator>(SourceExpr)) {
    if ((BO->getOpcode() == BO_And || BO->getOpcode() == BO_Or) &&
        BO->getLHS()->isKnownToHaveBooleanValue() &&
        BO->getRHS()->isKnownToHaveBooleanValue() &&
        BO->getLHS()->HasSideEffects(S.Context) &&
        BO->getRHS()->HasSideEffects(S.Context)) {
      SourceManager &SM = S.getSourceManager();
      const LangOptions &LO = S.getLangOpts();
      SourceLocation BLoc = BO->getOperatorLoc();
      SourceLocation ELoc = Lexer::getLocForEndOfToken(BLoc, 0, SM, LO);
      StringRef SR = clang::Lexer::getSourceText(
          clang::CharSourceRange::getTokenRange(BLoc, ELoc), SM, LO);
      // To reduce false positives, only issue the diagnostic if the operator
      // is explicitly spelled as a punctuator. This suppresses the diagnostic
      // when using 'bitand' or 'bitor' either as keywords in C++ or as macros
      // in C, along with other macro spellings the user might invent.
      if (SR.str() == "&" || SR.str() == "|") {

        S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
            << (BO->getOpcode() == BO_And ? "&" : "|")
            << OrigE->getSourceRange()
            << FixItHint::CreateReplacement(
                   BO->getOperatorLoc(),
                   (BO->getOpcode() == BO_And ? "&&" : "||"));
        S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
      }
    } else if (BO->isCommaOp() && !S.getLangOpts().CPlusPlus) {
      /// Analyze the given comma operator. The basic idea behind the analysis
      /// is to analyze the left and right operands slightly differently. The
      /// left operand needs to check whether the operand itself has an implicit
      /// conversion, but not whether the left operand induces an implicit
      /// conversion for the entire comma expression itself. This is similar to
      /// how CheckConditionalOperand behaves; it's as-if the correct operand
      /// were directly used for the implicit conversion check.
      CheckCommaOperand(S, BO->getLHS(), T, BO->getOperatorLoc(),
                        /*ExtraCheckForImplicitConversion=*/false);
      CheckCommaOperand(S, BO->getRHS(), T, BO->getOperatorLoc(),
                        /*ExtraCheckForImplicitConversion=*/true);
      return;
    }
  }

  // For conditional operators, we analyze the arguments as if they
  // were being fed directly into the output.
  if (auto *CO = dyn_cast<AbstractConditionalOperator>(SourceExpr)) {
    CheckConditionalOperator(S, CO, CC, T);
    return;
  }

  // Check implicit argument conversions for function calls.
  if (const auto *Call = dyn_cast<CallExpr>(SourceExpr))
    CheckImplicitArgumentConversions(S, Call, CC);

  // Go ahead and check any implicit conversions we might have skipped.
  // The non-canonical typecheck is just an optimization;
  // CheckImplicitConversion will filter out dead implicit conversions.
  if (SourceExpr->getType() != T)
    S.CheckImplicitConversion(SourceExpr, T, CC, nullptr, IsListInit);

  // Now continue drilling into this expression.

  if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
    // The bound subexpressions in a PseudoObjectExpr are not reachable
    // as transitive children.
    // FIXME: Use a more uniform representation for this.
    for (auto *SE : POE->semantics())
      if (auto *OVE = dyn_cast<OpaqueValueExpr>(SE))
        WorkList.push_back({OVE->getSourceExpr(), CC, IsListInit});
  }

  // Skip past explicit casts.
  if (auto *CE = dyn_cast<ExplicitCastExpr>(E)) {
    E = CE->getSubExpr()->IgnoreParenImpCasts();
    if (!CE->getType()->isVoidType() && E->getType()->isAtomicType())
      S.Diag(E->getBeginLoc(), diag::warn_atomic_implicit_seq_cst);
    WorkList.push_back({E, CC, IsListInit});
    return;
  }

  if (auto *OutArgE = dyn_cast<HLSLOutArgExpr>(E)) {
    WorkList.push_back({OutArgE->getArgLValue(), CC, IsListInit});
    // The base expression is only used to initialize the parameter for
    // arguments to `inout` parameters, so we only traverse down the base
    // expression for `inout` cases.
    if (OutArgE->isInOut())
      WorkList.push_back(
          {OutArgE->getCastedTemporary()->getSourceExpr(), CC, IsListInit});
    WorkList.push_back({OutArgE->getWritebackCast(), CC, IsListInit});
    return;
  }

  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
    // Do a somewhat different check with comparison operators.
    if (BO->isComparisonOp())
      return AnalyzeComparison(S, BO);

    // And with simple assignments.
    if (BO->getOpcode() == BO_Assign)
      return AnalyzeAssignment(S, BO);
    // And with compound assignments.
    if (BO->isAssignmentOp())
      return AnalyzeCompoundAssignment(S, BO);
  }

  // These break the otherwise-useful invariant below.  Fortunately,
  // we don't really need to recurse into them, because any internal
  // expressions should have been analyzed already when they were
  // built into statements.
  if (isa<StmtExpr>(E)) return;

  // Don't descend into unevaluated contexts.
  if (isa<UnaryExprOrTypeTraitExpr>(E)) return;

  // Now just recurse over the expression's children.
  CC = E->getExprLoc();
  BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
  bool IsLogicalAndOperator = BO && BO->getOpcode() == BO_LAnd;
  for (Stmt *SubStmt : E->children()) {
    Expr *ChildExpr = dyn_cast_or_null<Expr>(SubStmt);
    if (!ChildExpr)
      continue;

    if (auto *CSE = dyn_cast<CoroutineSuspendExpr>(E))
      if (ChildExpr == CSE->getOperand())
        // Do not recurse over a CoroutineSuspendExpr's operand.
        // The operand is also a subexpression of getCommonExpr(), and
        // recursing into it directly would produce duplicate diagnostics.
        continue;

    if (IsLogicalAndOperator &&
        isa<StringLiteral>(ChildExpr->IgnoreParenImpCasts()))
      // Ignore checking string literals that are in logical and operators.
      // This is a common pattern for asserts.
      continue;
    WorkList.push_back({ChildExpr, CC, IsListInit});
  }

  if (BO && BO->isLogicalOp()) {
    Expr *SubExpr = BO->getLHS()->IgnoreParenImpCasts();
    if (!IsLogicalAndOperator || !isa<StringLiteral>(SubExpr))
      ::CheckBoolLikeConversion(S, SubExpr, BO->getExprLoc());

    SubExpr = BO->getRHS()->IgnoreParenImpCasts();
    if (!IsLogicalAndOperator || !isa<StringLiteral>(SubExpr))
      ::CheckBoolLikeConversion(S, SubExpr, BO->getExprLoc());
  }

  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) {
    if (U->getOpcode() == UO_LNot) {
      ::CheckBoolLikeConversion(S, U->getSubExpr(), CC);
    } else if (U->getOpcode() != UO_AddrOf) {
      if (U->getSubExpr()->getType()->isAtomicType())
        S.Diag(U->getSubExpr()->getBeginLoc(),
               diag::warn_atomic_implicit_seq_cst);
    }
  }
}

/// AnalyzeImplicitConversions - Find and report any interesting
/// implicit conversions in the given expression.  There are a couple
/// of competing diagnostics here, -Wconversion and -Wsign-compare.
static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC,
                                       bool IsListInit/*= false*/) {
  llvm::SmallVector<AnalyzeImplicitConversionsWorkItem, 16> WorkList;
  WorkList.push_back({OrigE, CC, IsListInit});
  while (!WorkList.empty())
    AnalyzeImplicitConversions(S, WorkList.pop_back_val(), WorkList);
}

// Helper function for Sema::DiagnoseAlwaysNonNullPointer.
// Returns true when emitting a warning about taking the address of a reference.
static bool CheckForReference(Sema &SemaRef, const Expr *E,
                              const PartialDiagnostic &PD) {
  E = E->IgnoreParenImpCasts();

  const FunctionDecl *FD = nullptr;

  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
    if (!DRE->getDecl()->getType()->isReferenceType())
      return false;
  } else if (const MemberExpr *M = dyn_cast<MemberExpr>(E)) {
    if (!M->getMemberDecl()->getType()->isReferenceType())
      return false;
  } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) {
    if (!Call->getCallReturnType(SemaRef.Context)->isReferenceType())
      return false;
    FD = Call->getDirectCallee();
  } else {
    return false;
  }

  SemaRef.Diag(E->getExprLoc(), PD);

  // If possible, point to location of function.
  if (FD) {
    SemaRef.Diag(FD->getLocation(), diag::note_reference_is_return_value) << FD;
  }

  return true;
}

// Returns true if the SourceLocation is expanded from any macro body.
// Returns false if the SourceLocation is invalid, is from not in a macro
// expansion, or is from expanded from a top-level macro argument.
static bool IsInAnyMacroBody(const SourceManager &SM, SourceLocation Loc) {
  if (Loc.isInvalid())
    return false;

  while (Loc.isMacroID()) {
    if (SM.isMacroBodyExpansion(Loc))
      return true;
    Loc = SM.getImmediateMacroCallerLoc(Loc);
  }

  return false;
}

void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
                                        Expr::NullPointerConstantKind NullKind,
                                        bool IsEqual, SourceRange Range) {
  if (!E)
    return;

  // Don't warn inside macros.
  if (E->getExprLoc().isMacroID()) {
    const SourceManager &SM = getSourceManager();
    if (IsInAnyMacroBody(SM, E->getExprLoc()) ||
        IsInAnyMacroBody(SM, Range.getBegin()))
      return;
  }
  E = E->IgnoreImpCasts();

  const bool IsCompare = NullKind != Expr::NPCK_NotNull;

  if (isa<CXXThisExpr>(E)) {
    unsigned DiagID = IsCompare ? diag::warn_this_null_compare
                                : diag::warn_this_bool_conversion;
    Diag(E->getExprLoc(), DiagID) << E->getSourceRange() << Range << IsEqual;
    return;
  }

  bool IsAddressOf = false;

  if (auto *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) {
    if (UO->getOpcode() != UO_AddrOf)
      return;
    IsAddressOf = true;
    E = UO->getSubExpr();
  }

  if (IsAddressOf) {
    unsigned DiagID = IsCompare
                          ? diag::warn_address_of_reference_null_compare
                          : diag::warn_address_of_reference_bool_conversion;
    PartialDiagnostic PD = PDiag(DiagID) << E->getSourceRange() << Range
                                         << IsEqual;
    if (CheckForReference(*this, E, PD)) {
      return;
    }
  }

  auto ComplainAboutNonnullParamOrCall = [&](const Attr *NonnullAttr) {
    bool IsParam = isa<NonNullAttr>(NonnullAttr);
    std::string Str;
    llvm::raw_string_ostream S(Str);
    E->printPretty(S, nullptr, getPrintingPolicy());
    unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare
                                : diag::warn_cast_nonnull_to_bool;
    Diag(E->getExprLoc(), DiagID) << IsParam << S.str()
      << E->getSourceRange() << Range << IsEqual;
    Diag(NonnullAttr->getLocation(), diag::note_declared_nonnull) << IsParam;
  };

  // If we have a CallExpr that is tagged with returns_nonnull, we can complain.
  if (auto *Call = dyn_cast<CallExpr>(E->IgnoreParenImpCasts())) {
    if (auto *Callee = Call->getDirectCallee()) {
      if (const Attr *A = Callee->getAttr<ReturnsNonNullAttr>()) {
        ComplainAboutNonnullParamOrCall(A);
        return;
      }
    }
  }

  // Complain if we are converting a lambda expression to a boolean value
  // outside of instantiation.
  if (!inTemplateInstantiation()) {
    if (const auto *MCallExpr = dyn_cast<CXXMemberCallExpr>(E)) {
      if (const auto *MRecordDecl = MCallExpr->getRecordDecl();
          MRecordDecl && MRecordDecl->isLambda()) {
        Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool)
            << /*LambdaPointerConversionOperatorType=*/3
            << MRecordDecl->getSourceRange() << Range << IsEqual;
        return;
      }
    }
  }

  // Expect to find a single Decl.  Skip anything more complicated.
  ValueDecl *D = nullptr;
  if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
    D = R->getDecl();
  } else if (MemberExpr *M = dyn_cast<MemberExpr>(E)) {
    D = M->getMemberDecl();
  }

  // Weak Decls can be null.
  if (!D || D->isWeak())
    return;

  // Check for parameter decl with nonnull attribute
  if (const auto* PV = dyn_cast<ParmVarDecl>(D)) {
    if (getCurFunction() &&
        !getCurFunction()->ModifiedNonNullParams.count(PV)) {
      if (const Attr *A = PV->getAttr<NonNullAttr>()) {
        ComplainAboutNonnullParamOrCall(A);
        return;
      }

      if (const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
        // Skip function template not specialized yet.
        if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
          return;
        auto ParamIter = llvm::find(FD->parameters(), PV);
        assert(ParamIter != FD->param_end());
        unsigned ParamNo = std::distance(FD->param_begin(), ParamIter);

        for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
          if (!NonNull->args_size()) {
              ComplainAboutNonnullParamOrCall(NonNull);
              return;
          }

          for (const ParamIdx &ArgNo : NonNull->args()) {
            if (ArgNo.getASTIndex() == ParamNo) {
              ComplainAboutNonnullParamOrCall(NonNull);
              return;
            }
          }
        }
      }
    }
  }

  QualType T = D->getType();
  const bool IsArray = T->isArrayType();
  const bool IsFunction = T->isFunctionType();

  // Address of function is used to silence the function warning.
  if (IsAddressOf && IsFunction) {
    return;
  }

  // Found nothing.
  if (!IsAddressOf && !IsFunction && !IsArray)
    return;

  // Pretty print the expression for the diagnostic.
  std::string Str;
  llvm::raw_string_ostream S(Str);
  E->printPretty(S, nullptr, getPrintingPolicy());

  unsigned DiagID = IsCompare ? diag::warn_null_pointer_compare
                              : diag::warn_impcast_pointer_to_bool;
  enum {
    AddressOf,
    FunctionPointer,
    ArrayPointer
  } DiagType;
  if (IsAddressOf)
    DiagType = AddressOf;
  else if (IsFunction)
    DiagType = FunctionPointer;
  else if (IsArray)
    DiagType = ArrayPointer;
  else
    llvm_unreachable("Could not determine diagnostic.");
  Diag(E->getExprLoc(), DiagID) << DiagType << S.str() << E->getSourceRange()
                                << Range << IsEqual;

  if (!IsFunction)
    return;

  // Suggest '&' to silence the function warning.
  Diag(E->getExprLoc(), diag::note_function_warning_silence)
      << FixItHint::CreateInsertion(E->getBeginLoc(), "&");

  // Check to see if '()' fixit should be emitted.
  QualType ReturnType;
  UnresolvedSet<4> NonTemplateOverloads;
  tryExprAsCall(*E, ReturnType, NonTemplateOverloads);
  if (ReturnType.isNull())
    return;

  if (IsCompare) {
    // There are two cases here.  If there is null constant, the only suggest
    // for a pointer return type.  If the null is 0, then suggest if the return
    // type is a pointer or an integer type.
    if (!ReturnType->isPointerType()) {
      if (NullKind == Expr::NPCK_ZeroExpression ||
          NullKind == Expr::NPCK_ZeroLiteral) {
        if (!ReturnType->isIntegerType())
          return;
      } else {
        return;
      }
    }
  } else { // !IsCompare
    // For function to bool, only suggest if the function pointer has bool
    // return type.
    if (!ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
      return;
  }
  Diag(E->getExprLoc(), diag::note_function_to_function_call)
      << FixItHint::CreateInsertion(getLocForEndOfToken(E->getEndLoc()), "()");
}

void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) {
  // Don't diagnose in unevaluated contexts.
  if (isUnevaluatedContext())
    return;

  // Don't diagnose for value- or type-dependent expressions.
  if (E->isTypeDependent() || E->isValueDependent())
    return;

  // Check for array bounds violations in cases where the check isn't triggered
  // elsewhere for other Expr types (like BinaryOperators), e.g. when an
  // ArraySubscriptExpr is on the RHS of a variable initialization.
  CheckArrayAccess(E);

  // This is not the right CC for (e.g.) a variable initialization.
  AnalyzeImplicitConversions(*this, E, CC);
}

void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) {
  ::CheckBoolLikeConversion(*this, E, CC);
}

void Sema::CheckForIntOverflow (const Expr *E) {
  // Use a work list to deal with nested struct initializers.
  SmallVector<const Expr *, 2> Exprs(1, E);

  do {
    const Expr *OriginalE = Exprs.pop_back_val();
    const Expr *E = OriginalE->IgnoreParenCasts();

    if (isa<BinaryOperator, UnaryOperator>(E)) {
      E->EvaluateForOverflow(Context);
      continue;
    }

    if (const auto *InitList = dyn_cast<InitListExpr>(OriginalE))
      Exprs.append(InitList->inits().begin(), InitList->inits().end());
    else if (isa<ObjCBoxedExpr>(OriginalE))
      E->EvaluateForOverflow(Context);
    else if (const auto *Call = dyn_cast<CallExpr>(E))
      Exprs.append(Call->arg_begin(), Call->arg_end());
    else if (const auto *Message = dyn_cast<ObjCMessageExpr>(E))
      Exprs.append(Message->arg_begin(), Message->arg_end());
    else if (const auto *Construct = dyn_cast<CXXConstructExpr>(E))
      Exprs.append(Construct->arg_begin(), Construct->arg_end());
    else if (const auto *Temporary = dyn_cast<CXXBindTemporaryExpr>(E))
      Exprs.push_back(Temporary->getSubExpr());
    else if (const auto *Array = dyn_cast<ArraySubscriptExpr>(E))
      Exprs.push_back(Array->getIdx());
    else if (const auto *Compound = dyn_cast<CompoundLiteralExpr>(E))
      Exprs.push_back(Compound->getInitializer());
    else if (const auto *New = dyn_cast<CXXNewExpr>(E);
             New && New->isArray()) {
      if (auto ArraySize = New->getArraySize())
        Exprs.push_back(*ArraySize);
    } else if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(OriginalE))
      Exprs.push_back(MTE->getSubExpr());
  } while (!Exprs.empty());
}

namespace {

/// Visitor for expressions which looks for unsequenced operations on the
/// same object.
class SequenceChecker : public ConstEvaluatedExprVisitor<SequenceChecker> {
  using Base = ConstEvaluatedExprVisitor<SequenceChecker>;

  /// A tree of sequenced regions within an expression. Two regions are
  /// unsequenced if one is an ancestor or a descendent of the other. When we
  /// finish processing an expression with sequencing, such as a comma
  /// expression, we fold its tree nodes into its parent, since they are
  /// unsequenced with respect to nodes we will visit later.
  class SequenceTree {
    struct Value {
      explicit Value(unsigned Parent) : Parent(Parent), Merged(false) {}
      unsigned Parent : 31;
      LLVM_PREFERRED_TYPE(bool)
      unsigned Merged : 1;
    };
    SmallVector<Value, 8> Values;

  public:
    /// A region within an expression which may be sequenced with respect
    /// to some other region.
    class Seq {
      friend class SequenceTree;

      unsigned Index;

      explicit Seq(unsigned N) : Index(N) {}

    public:
      Seq() : Index(0) {}
    };

    SequenceTree() { Values.push_back(Value(0)); }
    Seq root() const { return Seq(0); }

    /// Create a new sequence of operations, which is an unsequenced
    /// subset of \p Parent. This sequence of operations is sequenced with
    /// respect to other children of \p Parent.
    Seq allocate(Seq Parent) {
      Values.push_back(Value(Parent.Index));
      return Seq(Values.size() - 1);
    }

    /// Merge a sequence of operations into its parent.
    void merge(Seq S) {
      Values[S.Index].Merged = true;
    }

    /// Determine whether two operations are unsequenced. This operation
    /// is asymmetric: \p Cur should be the more recent sequence, and \p Old
    /// should have been merged into its parent as appropriate.
    bool isUnsequenced(Seq Cur, Seq Old) {
      unsigned C = representative(Cur.Index);
      unsigned Target = representative(Old.Index);
      while (C >= Target) {
        if (C == Target)
          return true;
        C = Values[C].Parent;
      }
      return false;
    }

  private:
    /// Pick a representative for a sequence.
    unsigned representative(unsigned K) {
      if (Values[K].Merged)
        // Perform path compression as we go.
        return Values[K].Parent = representative(Values[K].Parent);
      return K;
    }
  };

  /// An object for which we can track unsequenced uses.
  using Object = const NamedDecl *;

  /// Different flavors of object usage which we track. We only track the
  /// least-sequenced usage of each kind.
  enum UsageKind {
    /// A read of an object. Multiple unsequenced reads are OK.
    UK_Use,

    /// A modification of an object which is sequenced before the value
    /// computation of the expression, such as ++n in C++.
    UK_ModAsValue,

    /// A modification of an object which is not sequenced before the value
    /// computation of the expression, such as n++.
    UK_ModAsSideEffect,

    UK_Count = UK_ModAsSideEffect + 1
  };

  /// Bundle together a sequencing region and the expression corresponding
  /// to a specific usage. One Usage is stored for each usage kind in UsageInfo.
  struct Usage {
    const Expr *UsageExpr = nullptr;
    SequenceTree::Seq Seq;

    Usage() = default;
  };

  struct UsageInfo {
    Usage Uses[UK_Count];

    /// Have we issued a diagnostic for this object already?
    bool Diagnosed = false;

    UsageInfo();
  };
  using UsageInfoMap = llvm::SmallDenseMap<Object, UsageInfo, 16>;

  Sema &SemaRef;

  /// Sequenced regions within the expression.
  SequenceTree Tree;

  /// Declaration modifications and references which we have seen.
  UsageInfoMap UsageMap;

  /// The region we are currently within.
  SequenceTree::Seq Region;

  /// Filled in with declarations which were modified as a side-effect
  /// (that is, post-increment operations).
  SmallVectorImpl<std::pair<Object, Usage>> *ModAsSideEffect = nullptr;

  /// Expressions to check later. We defer checking these to reduce
  /// stack usage.
  SmallVectorImpl<const Expr *> &WorkList;

  /// RAII object wrapping the visitation of a sequenced subexpression of an
  /// expression. At the end of this process, the side-effects of the evaluation
  /// become sequenced with respect to the value computation of the result, so
  /// we downgrade any UK_ModAsSideEffect within the evaluation to
  /// UK_ModAsValue.
  struct SequencedSubexpression {
    SequencedSubexpression(SequenceChecker &Self)
      : Self(Self), OldModAsSideEffect(Self.ModAsSideEffect) {
      Self.ModAsSideEffect = &ModAsSideEffect;
    }

    ~SequencedSubexpression() {
      for (const std::pair<Object, Usage> &M : llvm::reverse(ModAsSideEffect)) {
        // Add a new usage with usage kind UK_ModAsValue, and then restore
        // the previous usage with UK_ModAsSideEffect (thus clearing it if
        // the previous one was empty).
        UsageInfo &UI = Self.UsageMap[M.first];
        auto &SideEffectUsage = UI.Uses[UK_ModAsSideEffect];
        Self.addUsage(M.first, UI, SideEffectUsage.UsageExpr, UK_ModAsValue);
        SideEffectUsage = M.second;
      }
      Self.ModAsSideEffect = OldModAsSideEffect;
    }

    SequenceChecker &Self;
    SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect;
    SmallVectorImpl<std::pair<Object, Usage>> *OldModAsSideEffect;
  };

  /// RAII object wrapping the visitation of a subexpression which we might
  /// choose to evaluate as a constant. If any subexpression is evaluated and
  /// found to be non-constant, this allows us to suppress the evaluation of
  /// the outer expression.
  class EvaluationTracker {
  public:
    EvaluationTracker(SequenceChecker &Self)
        : Self(Self), Prev(Self.EvalTracker) {
      Self.EvalTracker = this;
    }

    ~EvaluationTracker() {
      Self.EvalTracker = Prev;
      if (Prev)
        Prev->EvalOK &= EvalOK;
    }

    bool evaluate(const Expr *E, bool &Result) {
      if (!EvalOK || E->isValueDependent())
        return false;
      EvalOK = E->EvaluateAsBooleanCondition(
          Result, Self.SemaRef.Context,
          Self.SemaRef.isConstantEvaluatedContext());
      return EvalOK;
    }

  private:
    SequenceChecker &Self;
    EvaluationTracker *Prev;
    bool EvalOK = true;
  } *EvalTracker = nullptr;

  /// Find the object which is produced by the specified expression,
  /// if any.
  Object getObject(const Expr *E, bool Mod) const {
    E = E->IgnoreParenCasts();
    if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
      if (Mod && (UO->getOpcode() == UO_PreInc || UO->getOpcode() == UO_PreDec))
        return getObject(UO->getSubExpr(), Mod);
    } else if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
      if (BO->getOpcode() == BO_Comma)
        return getObject(BO->getRHS(), Mod);
      if (Mod && BO->isAssignmentOp())
        return getObject(BO->getLHS(), Mod);
    } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
      // FIXME: Check for more interesting cases, like "x.n = ++x.n".
      if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenCasts()))
        return ME->getMemberDecl();
    } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
      // FIXME: If this is a reference, map through to its value.
      return DRE->getDecl();
    return nullptr;
  }

  /// Note that an object \p O was modified or used by an expression
  /// \p UsageExpr with usage kind \p UK. \p UI is the \p UsageInfo for
  /// the object \p O as obtained via the \p UsageMap.
  void addUsage(Object O, UsageInfo &UI, const Expr *UsageExpr, UsageKind UK) {
    // Get the old usage for the given object and usage kind.
    Usage &U = UI.Uses[UK];
    if (!U.UsageExpr || !Tree.isUnsequenced(Region, U.Seq)) {
      // If we have a modification as side effect and are in a sequenced
      // subexpression, save the old Usage so that we can restore it later
      // in SequencedSubexpression::~SequencedSubexpression.
      if (UK == UK_ModAsSideEffect && ModAsSideEffect)
        ModAsSideEffect->push_back(std::make_pair(O, U));
      // Then record the new usage with the current sequencing region.
      U.UsageExpr = UsageExpr;
      U.Seq = Region;
    }
  }

  /// Check whether a modification or use of an object \p O in an expression
  /// \p UsageExpr conflicts with a prior usage of kind \p OtherKind. \p UI is
  /// the \p UsageInfo for the object \p O as obtained via the \p UsageMap.
  /// \p IsModMod is true when we are checking for a mod-mod unsequenced
  /// usage and false we are checking for a mod-use unsequenced usage.
  void checkUsage(Object O, UsageInfo &UI, const Expr *UsageExpr,
                  UsageKind OtherKind, bool IsModMod) {
    if (UI.Diagnosed)
      return;

    const Usage &U = UI.Uses[OtherKind];
    if (!U.UsageExpr || !Tree.isUnsequenced(Region, U.Seq))
      return;

    const Expr *Mod = U.UsageExpr;
    const Expr *ModOrUse = UsageExpr;
    if (OtherKind == UK_Use)
      std::swap(Mod, ModOrUse);

    SemaRef.DiagRuntimeBehavior(
        Mod->getExprLoc(), {Mod, ModOrUse},
        SemaRef.PDiag(IsModMod ? diag::warn_unsequenced_mod_mod
                               : diag::warn_unsequenced_mod_use)
            << O << SourceRange(ModOrUse->getExprLoc()));
    UI.Diagnosed = true;
  }

  // A note on note{Pre, Post}{Use, Mod}:
  //
  // (It helps to follow the algorithm with an expression such as
  //  "((++k)++, k) = k" or "k = (k++, k++)". Both contain unsequenced
  //  operations before C++17 and both are well-defined in C++17).
  //
  // When visiting a node which uses/modify an object we first call notePreUse
  // or notePreMod before visiting its sub-expression(s). At this point the
  // children of the current node have not yet been visited and so the eventual
  // uses/modifications resulting from the children of the current node have not
  // been recorded yet.
  //
  // We then visit the children of the current node. After that notePostUse or
  // notePostMod is called. These will 1) detect an unsequenced modification
  // as side effect (as in "k++ + k") and 2) add a new usage with the
  // appropriate usage kind.
  //
  // We also have to be careful that some operation sequences modification as
  // side effect as well (for example: || or ,). To account for this we wrap
  // the visitation of such a sub-expression (for example: the LHS of || or ,)
  // with SequencedSubexpression. SequencedSubexpression is an RAII object
  // which record usages which are modifications as side effect, and then
  // downgrade them (or more accurately restore the previous usage which was a
  // modification as side effect) when exiting the scope of the sequenced
  // subexpression.

  void notePreUse(Object O, const Expr *UseExpr) {
    UsageInfo &UI = UsageMap[O];
    // Uses conflict with other modifications.
    checkUsage(O, UI, UseExpr, /*OtherKind=*/UK_ModAsValue, /*IsModMod=*/false);
  }

  void notePostUse(Object O, const Expr *UseExpr) {
    UsageInfo &UI = UsageMap[O];
    checkUsage(O, UI, UseExpr, /*OtherKind=*/UK_ModAsSideEffect,
               /*IsModMod=*/false);
    addUsage(O, UI, UseExpr, /*UsageKind=*/UK_Use);
  }

  void notePreMod(Object O, const Expr *ModExpr) {
    UsageInfo &UI = UsageMap[O];
    // Modifications conflict with other modifications and with uses.
    checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_ModAsValue, /*IsModMod=*/true);
    checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_Use, /*IsModMod=*/false);
  }

  void notePostMod(Object O, const Expr *ModExpr, UsageKind UK) {
    UsageInfo &UI = UsageMap[O];
    checkUsage(O, UI, ModExpr, /*OtherKind=*/UK_ModAsSideEffect,
               /*IsModMod=*/true);
    addUsage(O, UI, ModExpr, /*UsageKind=*/UK);
  }

public:
  SequenceChecker(Sema &S, const Expr *E,
                  SmallVectorImpl<const Expr *> &WorkList)
      : Base(S.Context), SemaRef(S), Region(Tree.root()), WorkList(WorkList) {
    Visit(E);
    // Silence a -Wunused-private-field since WorkList is now unused.
    // TODO: Evaluate if it can be used, and if not remove it.
    (void)this->WorkList;
  }

  void VisitStmt(const Stmt *S) {
    // Skip all statements which aren't expressions for now.
  }

  void VisitExpr(const Expr *E) {
    // By default, just recurse to evaluated subexpressions.
    Base::VisitStmt(E);
  }

  void VisitCoroutineSuspendExpr(const CoroutineSuspendExpr *CSE) {
    for (auto *Sub : CSE->children()) {
      const Expr *ChildExpr = dyn_cast_or_null<Expr>(Sub);
      if (!ChildExpr)
        continue;

      if (ChildExpr == CSE->getOperand())
        // Do not recurse over a CoroutineSuspendExpr's operand.
        // The operand is also a subexpression of getCommonExpr(), and
        // recursing into it directly could confuse object management
        // for the sake of sequence tracking.
        continue;

      Visit(Sub);
    }
  }

  void VisitCastExpr(const CastExpr *E) {
    Object O = Object();
    if (E->getCastKind() == CK_LValueToRValue)
      O = getObject(E->getSubExpr(), false);

    if (O)
      notePreUse(O, E);
    VisitExpr(E);
    if (O)
      notePostUse(O, E);
  }

  void VisitSequencedExpressions(const Expr *SequencedBefore,
                                 const Expr *SequencedAfter) {
    SequenceTree::Seq BeforeRegion = Tree.allocate(Region);
    SequenceTree::Seq AfterRegion = Tree.allocate(Region);
    SequenceTree::Seq OldRegion = Region;

    {
      SequencedSubexpression SeqBefore(*this);
      Region = BeforeRegion;
      Visit(SequencedBefore);
    }

    Region = AfterRegion;
    Visit(SequencedAfter);

    Region = OldRegion;

    Tree.merge(BeforeRegion);
    Tree.merge(AfterRegion);
  }

  void VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE) {
    // C++17 [expr.sub]p1:
    //   The expression E1[E2] is identical (by definition) to *((E1)+(E2)). The
    //   expression E1 is sequenced before the expression E2.
    if (SemaRef.getLangOpts().CPlusPlus17)
      VisitSequencedExpressions(ASE->getLHS(), ASE->getRHS());
    else {
      Visit(ASE->getLHS());
      Visit(ASE->getRHS());
    }
  }

  void VisitBinPtrMemD(const BinaryOperator *BO) { VisitBinPtrMem(BO); }
  void VisitBinPtrMemI(const BinaryOperator *BO) { VisitBinPtrMem(BO); }
  void VisitBinPtrMem(const BinaryOperator *BO) {
    // C++17 [expr.mptr.oper]p4:
    //  Abbreviating pm-expression.*cast-expression as E1.*E2, [...]
    //  the expression E1 is sequenced before the expression E2.
    if (SemaRef.getLangOpts().CPlusPlus17)
      VisitSequencedExpressions(BO->getLHS(), BO->getRHS());
    else {
      Visit(BO->getLHS());
      Visit(BO->getRHS());
    }
  }

  void VisitBinShl(const BinaryOperator *BO) { VisitBinShlShr(BO); }
  void VisitBinShr(const BinaryOperator *BO) { VisitBinShlShr(BO); }
  void VisitBinShlShr(const BinaryOperator *BO) {
    // C++17 [expr.shift]p4:
    //  The expression E1 is sequenced before the expression E2.
    if (SemaRef.getLangOpts().CPlusPlus17)
      VisitSequencedExpressions(BO->getLHS(), BO->getRHS());
    else {
      Visit(BO->getLHS());
      Visit(BO->getRHS());
    }
  }

  void VisitBinComma(const BinaryOperator *BO) {
    // C++11 [expr.comma]p1:
    //   Every value computation and side effect associated with the left
    //   expression is sequenced before every value computation and side
    //   effect associated with the right expression.
    VisitSequencedExpressions(BO->getLHS(), BO->getRHS());
  }

  void VisitBinAssign(const BinaryOperator *BO) {
    SequenceTree::Seq RHSRegion;
    SequenceTree::Seq LHSRegion;
    if (SemaRef.getLangOpts().CPlusPlus17) {
      RHSRegion = Tree.allocate(Region);
      LHSRegion = Tree.allocate(Region);
    } else {
      RHSRegion = Region;
      LHSRegion = Region;
    }
    SequenceTree::Seq OldRegion = Region;

    // C++11 [expr.ass]p1:
    //  [...] the assignment is sequenced after the value computation
    //  of the right and left operands, [...]
    //
    // so check it before inspecting the operands and update the
    // map afterwards.
    Object O = getObject(BO->getLHS(), /*Mod=*/true);
    if (O)
      notePreMod(O, BO);

    if (SemaRef.getLangOpts().CPlusPlus17) {
      // C++17 [expr.ass]p1:
      //  [...] The right operand is sequenced before the left operand. [...]
      {
        SequencedSubexpression SeqBefore(*this);
        Region = RHSRegion;
        Visit(BO->getRHS());
      }

      Region = LHSRegion;
      Visit(BO->getLHS());

      if (O && isa<CompoundAssignOperator>(BO))
        notePostUse(O, BO);

    } else {
      // C++11 does not specify any sequencing between the LHS and RHS.
      Region = LHSRegion;
      Visit(BO->getLHS());

      if (O && isa<CompoundAssignOperator>(BO))
        notePostUse(O, BO);

      Region = RHSRegion;
      Visit(BO->getRHS());
    }

    // C++11 [expr.ass]p1:
    //  the assignment is sequenced [...] before the value computation of the
    //  assignment expression.
    // C11 6.5.16/3 has no such rule.
    Region = OldRegion;
    if (O)
      notePostMod(O, BO,
                  SemaRef.getLangOpts().CPlusPlus ? UK_ModAsValue
                                                  : UK_ModAsSideEffect);
    if (SemaRef.getLangOpts().CPlusPlus17) {
      Tree.merge(RHSRegion);
      Tree.merge(LHSRegion);
    }
  }

  void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO) {
    VisitBinAssign(CAO);
  }

  void VisitUnaryPreInc(const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
  void VisitUnaryPreDec(const UnaryOperator *UO) { VisitUnaryPreIncDec(UO); }
  void VisitUnaryPreIncDec(const UnaryOperator *UO) {
    Object O = getObject(UO->getSubExpr(), true);
    if (!O)
      return VisitExpr(UO);

    notePreMod(O, UO);
    Visit(UO->getSubExpr());
    // C++11 [expr.pre.incr]p1:
    //   the expression ++x is equivalent to x+=1
    notePostMod(O, UO,
                SemaRef.getLangOpts().CPlusPlus ? UK_ModAsValue
                                                : UK_ModAsSideEffect);
  }

  void VisitUnaryPostInc(const UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
  void VisitUnaryPostDec(const UnaryOperator *UO) { VisitUnaryPostIncDec(UO); }
  void VisitUnaryPostIncDec(const UnaryOperator *UO) {
    Object O = getObject(UO->getSubExpr(), true);
    if (!O)
      return VisitExpr(UO);

    notePreMod(O, UO);
    Visit(UO->getSubExpr());
    notePostMod(O, UO, UK_ModAsSideEffect);
  }

  void VisitBinLOr(const BinaryOperator *BO) {
    // C++11 [expr.log.or]p2:
    //  If the second expression is evaluated, every value computation and
    //  side effect associated with the first expression is sequenced before
    //  every value computation and side effect associated with the
    //  second expression.
    SequenceTree::Seq LHSRegion = Tree.allocate(Region);
    SequenceTree::Seq RHSRegion = Tree.allocate(Region);
    SequenceTree::Seq OldRegion = Region;

    EvaluationTracker Eval(*this);
    {
      SequencedSubexpression Sequenced(*this);
      Region = LHSRegion;
      Visit(BO->getLHS());
    }

    // C++11 [expr.log.or]p1:
    //  [...] the second operand is not evaluated if the first operand
    //  evaluates to true.
    bool EvalResult = false;
    bool EvalOK = Eval.evaluate(BO->getLHS(), EvalResult);
    bool ShouldVisitRHS = !EvalOK || !EvalResult;
    if (ShouldVisitRHS) {
      Region = RHSRegion;
      Visit(BO->getRHS());
    }

    Region = OldRegion;
    Tree.merge(LHSRegion);
    Tree.merge(RHSRegion);
  }

  void VisitBinLAnd(const BinaryOperator *BO) {
    // C++11 [expr.log.and]p2:
    //  If the second expression is evaluated, every value computation and
    //  side effect associated with the first expression is sequenced before
    //  every value computation and side effect associated with the
    //  second expression.
    SequenceTree::Seq LHSRegion = Tree.allocate(Region);
    SequenceTree::Seq RHSRegion = Tree.allocate(Region);
    SequenceTree::Seq OldRegion = Region;

    EvaluationTracker Eval(*this);
    {
      SequencedSubexpression Sequenced(*this);
      Region = LHSRegion;
      Visit(BO->getLHS());
    }

    // C++11 [expr.log.and]p1:
    //  [...] the second operand is not evaluated if the first operand is false.
    bool EvalResult = false;
    bool EvalOK = Eval.evaluate(BO->getLHS(), EvalResult);
    bool ShouldVisitRHS = !EvalOK || EvalResult;
    if (ShouldVisitRHS) {
      Region = RHSRegion;
      Visit(BO->getRHS());
    }

    Region = OldRegion;
    Tree.merge(LHSRegion);
    Tree.merge(RHSRegion);
  }

  void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO) {
    // C++11 [expr.cond]p1:
    //  [...] Every value computation and side effect associated with the first
    //  expression is sequenced before every value computation and side effect
    //  associated with the second or third expression.
    SequenceTree::Seq ConditionRegion = Tree.allocate(Region);

    // No sequencing is specified between the true and false expression.
    // However since exactly one of both is going to be evaluated we can
    // consider them to be sequenced. This is needed to avoid warning on
    // something like "x ? y+= 1 : y += 2;" in the case where we will visit
    // both the true and false expressions because we can't evaluate x.
    // This will still allow us to detect an expression like (pre C++17)
    // "(x ? y += 1 : y += 2) = y".
    //
    // We don't wrap the visitation of the true and false expression with
    // SequencedSubexpression because we don't want to downgrade modifications
    // as side effect in the true and false expressions after the visition
    // is done. (for example in the expression "(x ? y++ : y++) + y" we should
    // not warn between the two "y++", but we should warn between the "y++"
    // and the "y".
    SequenceTree::Seq TrueRegion = Tree.allocate(Region);
    SequenceTree::Seq FalseRegion = Tree.allocate(Region);
    SequenceTree::Seq OldRegion = Region;

    EvaluationTracker Eval(*this);
    {
      SequencedSubexpression Sequenced(*this);
      Region = ConditionRegion;
      Visit(CO->getCond());
    }

    // C++11 [expr.cond]p1:
    // [...] The first expression is contextually converted to bool (Clause 4).
    // It is evaluated and if it is true, the result of the conditional
    // expression is the value of the second expression, otherwise that of the
    // third expression. Only one of the second and third expressions is
    // evaluated. [...]
    bool EvalResult = false;
    bool EvalOK = Eval.evaluate(CO->getCond(), EvalResult);
    bool ShouldVisitTrueExpr = !EvalOK || EvalResult;
    bool ShouldVisitFalseExpr = !EvalOK || !EvalResult;
    if (ShouldVisitTrueExpr) {
      Region = TrueRegion;
      Visit(CO->getTrueExpr());
    }
    if (ShouldVisitFalseExpr) {
      Region = FalseRegion;
      Visit(CO->getFalseExpr());
    }

    Region = OldRegion;
    Tree.merge(ConditionRegion);
    Tree.merge(TrueRegion);
    Tree.merge(FalseRegion);
  }

  void VisitCallExpr(const CallExpr *CE) {
    // FIXME: CXXNewExpr and CXXDeleteExpr implicitly call functions.

    if (CE->isUnevaluatedBuiltinCall(Context))
      return;

    // C++11 [intro.execution]p15:
    //   When calling a function [...], every value computation and side effect
    //   associated with any argument expression, or with the postfix expression
    //   designating the called function, is sequenced before execution of every
    //   expression or statement in the body of the function [and thus before
    //   the value computation of its result].
    SequencedSubexpression Sequenced(*this);
    SemaRef.runWithSufficientStackSpace(CE->getExprLoc(), [&] {
      // C++17 [expr.call]p5
      //   The postfix-expression is sequenced before each expression in the
      //   expression-list and any default argument. [...]
      SequenceTree::Seq CalleeRegion;
      SequenceTree::Seq OtherRegion;
      if (SemaRef.getLangOpts().CPlusPlus17) {
        CalleeRegion = Tree.allocate(Region);
        OtherRegion = Tree.allocate(Region);
      } else {
        CalleeRegion = Region;
        OtherRegion = Region;
      }
      SequenceTree::Seq OldRegion = Region;

      // Visit the callee expression first.
      Region = CalleeRegion;
      if (SemaRef.getLangOpts().CPlusPlus17) {
        SequencedSubexpression Sequenced(*this);
        Visit(CE->getCallee());
      } else {
        Visit(CE->getCallee());
      }

      // Then visit the argument expressions.
      Region = OtherRegion;
      for (const Expr *Argument : CE->arguments())
        Visit(Argument);

      Region = OldRegion;
      if (SemaRef.getLangOpts().CPlusPlus17) {
        Tree.merge(CalleeRegion);
        Tree.merge(OtherRegion);
      }
    });
  }

  void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *CXXOCE) {
    // C++17 [over.match.oper]p2:
    //   [...] the operator notation is first transformed to the equivalent
    //   function-call notation as summarized in Table 12 (where @ denotes one
    //   of the operators covered in the specified subclause). However, the
    //   operands are sequenced in the order prescribed for the built-in
    //   operator (Clause 8).
    //
    // From the above only overloaded binary operators and overloaded call
    // operators have sequencing rules in C++17 that we need to handle
    // separately.
    if (!SemaRef.getLangOpts().CPlusPlus17 ||
        (CXXOCE->getNumArgs() != 2 && CXXOCE->getOperator() != OO_Call))
      return VisitCallExpr(CXXOCE);

    enum {
      NoSequencing,
      LHSBeforeRHS,
      RHSBeforeLHS,
      LHSBeforeRest
    } SequencingKind;
    switch (CXXOCE->getOperator()) {
    case OO_Equal:
    case OO_PlusEqual:
    case OO_MinusEqual:
    case OO_StarEqual:
    case OO_SlashEqual:
    case OO_PercentEqual:
    case OO_CaretEqual:
    case OO_AmpEqual:
    case OO_PipeEqual:
    case OO_LessLessEqual:
    case OO_GreaterGreaterEqual:
      SequencingKind = RHSBeforeLHS;
      break;

    case OO_LessLess:
    case OO_GreaterGreater:
    case OO_AmpAmp:
    case OO_PipePipe:
    case OO_Comma:
    case OO_ArrowStar:
    case OO_Subscript:
      SequencingKind = LHSBeforeRHS;
      break;

    case OO_Call:
      SequencingKind = LHSBeforeRest;
      break;

    default:
      SequencingKind = NoSequencing;
      break;
    }

    if (SequencingKind == NoSequencing)
      return VisitCallExpr(CXXOCE);

    // This is a call, so all subexpressions are sequenced before the result.
    SequencedSubexpression Sequenced(*this);

    SemaRef.runWithSufficientStackSpace(CXXOCE->getExprLoc(), [&] {
      assert(SemaRef.getLangOpts().CPlusPlus17 &&
             "Should only get there with C++17 and above!");
      assert((CXXOCE->getNumArgs() == 2 || CXXOCE->getOperator() == OO_Call) &&
             "Should only get there with an overloaded binary operator"
             " or an overloaded call operator!");

      if (SequencingKind == LHSBeforeRest) {
        assert(CXXOCE->getOperator() == OO_Call &&
               "We should only have an overloaded call operator here!");

        // This is very similar to VisitCallExpr, except that we only have the
        // C++17 case. The postfix-expression is the first argument of the
        // CXXOperatorCallExpr. The expressions in the expression-list, if any,
        // are in the following arguments.
        //
        // Note that we intentionally do not visit the callee expression since
        // it is just a decayed reference to a function.
        SequenceTree::Seq PostfixExprRegion = Tree.allocate(Region);
        SequenceTree::Seq ArgsRegion = Tree.allocate(Region);
        SequenceTree::Seq OldRegion = Region;

        assert(CXXOCE->getNumArgs() >= 1 &&
               "An overloaded call operator must have at least one argument"
               " for the postfix-expression!");
        const Expr *PostfixExpr = CXXOCE->getArgs()[0];
        llvm::ArrayRef<const Expr *> Args(CXXOCE->getArgs() + 1,
                                          CXXOCE->getNumArgs() - 1);

        // Visit the postfix-expression first.
        {
          Region = PostfixExprRegion;
          SequencedSubexpression Sequenced(*this);
          Visit(PostfixExpr);
        }

        // Then visit the argument expressions.
        Region = ArgsRegion;
        for (const Expr *Arg : Args)
          Visit(Arg);

        Region = OldRegion;
        Tree.merge(PostfixExprRegion);
        Tree.merge(ArgsRegion);
      } else {
        assert(CXXOCE->getNumArgs() == 2 &&
               "Should only have two arguments here!");
        assert((SequencingKind == LHSBeforeRHS ||
                SequencingKind == RHSBeforeLHS) &&
               "Unexpected sequencing kind!");

        // We do not visit the callee expression since it is just a decayed
        // reference to a function.
        const Expr *E1 = CXXOCE->getArg(0);
        const Expr *E2 = CXXOCE->getArg(1);
        if (SequencingKind == RHSBeforeLHS)
          std::swap(E1, E2);

        return VisitSequencedExpressions(E1, E2);
      }
    });
  }

  void VisitCXXConstructExpr(const CXXConstructExpr *CCE) {
    // This is a call, so all subexpressions are sequenced before the result.
    SequencedSubexpression Sequenced(*this);

    if (!CCE->isListInitialization())
      return VisitExpr(CCE);

    // In C++11, list initializations are sequenced.
    SequenceExpressionsInOrder(
        llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs()));
  }

  void VisitInitListExpr(const InitListExpr *ILE) {
    if (!SemaRef.getLangOpts().CPlusPlus11)
      return VisitExpr(ILE);

    // In C++11, list initializations are sequenced.
    SequenceExpressionsInOrder(ILE->inits());
  }

  void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE) {
    // C++20 parenthesized list initializations are sequenced. See C++20
    // [decl.init.general]p16.5 and [decl.init.general]p16.6.2.2.
    SequenceExpressionsInOrder(PLIE->getInitExprs());
  }

private:
  void SequenceExpressionsInOrder(ArrayRef<const Expr *> ExpressionList) {
    SmallVector<SequenceTree::Seq, 32> Elts;
    SequenceTree::Seq Parent = Region;
    for (const Expr *E : ExpressionList) {
      if (!E)
        continue;
      Region = Tree.allocate(Parent);
      Elts.push_back(Region);
      Visit(E);
    }

    // Forget that the initializers are sequenced.
    Region = Parent;
    for (unsigned I = 0; I < Elts.size(); ++I)
      Tree.merge(Elts[I]);
  }
};

SequenceChecker::UsageInfo::UsageInfo() = default;

} // namespace

void Sema::CheckUnsequencedOperations(const Expr *E) {
  SmallVector<const Expr *, 8> WorkList;
  WorkList.push_back(E);
  while (!WorkList.empty()) {
    const Expr *Item = WorkList.pop_back_val();
    SequenceChecker(*this, Item, WorkList);
  }
}

void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
                              bool IsConstexpr) {
  llvm::SaveAndRestore ConstantContext(isConstantEvaluatedOverride,
                                       IsConstexpr || isa<ConstantExpr>(E));
  CheckImplicitConversions(E, CheckLoc);
  if (!E->isInstantiationDependent())
    CheckUnsequencedOperations(E);
  if (!IsConstexpr && !E->isValueDependent())
    CheckForIntOverflow(E);
  DiagnoseMisalignedMembers();
}

void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
                                       FieldDecl *BitField,
                                       Expr *Init) {
  (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc);
}

static void diagnoseArrayStarInParamType(Sema &S, QualType PType,
                                         SourceLocation Loc) {
  if (!PType->isVariablyModifiedType())
    return;
  if (const auto *PointerTy = dyn_cast<PointerType>(PType)) {
    diagnoseArrayStarInParamType(S, PointerTy->getPointeeType(), Loc);
    return;
  }
  if (const auto *ReferenceTy = dyn_cast<ReferenceType>(PType)) {
    diagnoseArrayStarInParamType(S, ReferenceTy->getPointeeType(), Loc);
    return;
  }
  if (const auto *ParenTy = dyn_cast<ParenType>(PType)) {
    diagnoseArrayStarInParamType(S, ParenTy->getInnerType(), Loc);
    return;
  }

  const ArrayType *AT = S.Context.getAsArrayType(PType);
  if (!AT)
    return;

  if (AT->getSizeModifier() != ArraySizeModifier::Star) {
    diagnoseArrayStarInParamType(S, AT->getElementType(), Loc);
    return;
  }

  S.Diag(Loc, diag::err_array_star_in_function_definition);
}

bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
                                    bool CheckParameterNames) {
  bool HasInvalidParm = false;
  for (ParmVarDecl *Param : Parameters) {
    assert(Param && "null in a parameter list");
    // C99 6.7.5.3p4: the parameters in a parameter type list in a
    // function declarator that is part of a function definition of
    // that function shall not have incomplete type.
    //
    // C++23 [dcl.fct.def.general]/p2
    // The type of a parameter [...] for a function definition
    // shall not be a (possibly cv-qualified) class type that is incomplete
    // or abstract within the function body unless the function is deleted.
    if (!Param->isInvalidDecl() &&
        (RequireCompleteType(Param->getLocation(), Param->getType(),
                             diag::err_typecheck_decl_incomplete_type) ||
         RequireNonAbstractType(Param->getBeginLoc(), Param->getOriginalType(),
                                diag::err_abstract_type_in_decl,
                                AbstractParamType))) {
      Param->setInvalidDecl();
      HasInvalidParm = true;
    }

    // C99 6.9.1p5: If the declarator includes a parameter type list, the
    // declaration of each parameter shall include an identifier.
    if (CheckParameterNames && Param->getIdentifier() == nullptr &&
        !Param->isImplicit() && !getLangOpts().CPlusPlus) {
      // Diagnose this as an extension in C17 and earlier.
      if (!getLangOpts().C23)
        Diag(Param->getLocation(), diag::ext_parameter_name_omitted_c23);
    }

    // C99 6.7.5.3p12:
    //   If the function declarator is not part of a definition of that
    //   function, parameters may have incomplete type and may use the [*]
    //   notation in their sequences of declarator specifiers to specify
    //   variable length array types.
    QualType PType = Param->getOriginalType();
    // FIXME: This diagnostic should point the '[*]' if source-location
    // information is added for it.
    diagnoseArrayStarInParamType(*this, PType, Param->getLocation());

    // If the parameter is a c++ class type and it has to be destructed in the
    // callee function, declare the destructor so that it can be called by the
    // callee function. Do not perform any direct access check on the dtor here.
    if (!Param->isInvalidDecl()) {
      if (CXXRecordDecl *ClassDecl = Param->getType()->getAsCXXRecordDecl()) {
        if (!ClassDecl->isInvalidDecl() &&
            !ClassDecl->hasIrrelevantDestructor() &&
            !ClassDecl->isDependentContext() &&
            ClassDecl->isParamDestroyedInCallee()) {
          CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
          MarkFunctionReferenced(Param->getLocation(), Destructor);
          DiagnoseUseOfDecl(Destructor, Param->getLocation());
        }
      }
    }

    // Parameters with the pass_object_size attribute only need to be marked
    // constant at function definitions. Because we lack information about
    // whether we're on a declaration or definition when we're instantiating the
    // attribute, we need to check for constness here.
    if (const auto *Attr = Param->getAttr<PassObjectSizeAttr>())
      if (!Param->getType().isConstQualified())
        Diag(Param->getLocation(), diag::err_attribute_pointers_only)
            << Attr->getSpelling() << 1;

    // Check for parameter names shadowing fields from the class.
    if (LangOpts.CPlusPlus && !Param->isInvalidDecl()) {
      // The owning context for the parameter should be the function, but we
      // want to see if this function's declaration context is a record.
      DeclContext *DC = Param->getDeclContext();
      if (DC && DC->isFunctionOrMethod()) {
        if (auto *RD = dyn_cast<CXXRecordDecl>(DC->getParent()))
          CheckShadowInheritedFields(Param->getLocation(), Param->getDeclName(),
                                     RD, /*DeclIsField*/ false);
      }
    }

    if (!Param->isInvalidDecl() &&
        Param->getOriginalType()->isWebAssemblyTableType()) {
      Param->setInvalidDecl();
      HasInvalidParm = true;
      Diag(Param->getLocation(), diag::err_wasm_table_as_function_parameter);
    }
  }

  return HasInvalidParm;
}

std::optional<std::pair<
    CharUnits, CharUnits>> static getBaseAlignmentAndOffsetFromPtr(const Expr
                                                                       *E,
                                                                   ASTContext
                                                                       &Ctx);

/// Compute the alignment and offset of the base class object given the
/// derived-to-base cast expression and the alignment and offset of the derived
/// class object.
static std::pair<CharUnits, CharUnits>
getDerivedToBaseAlignmentAndOffset(const CastExpr *CE, QualType DerivedType,
                                   CharUnits BaseAlignment, CharUnits Offset,
                                   ASTContext &Ctx) {
  for (auto PathI = CE->path_begin(), PathE = CE->path_end(); PathI != PathE;
       ++PathI) {
    const CXXBaseSpecifier *Base = *PathI;
    const CXXRecordDecl *BaseDecl = Base->getType()->getAsCXXRecordDecl();
    if (Base->isVirtual()) {
      // The complete object may have a lower alignment than the non-virtual
      // alignment of the base, in which case the base may be misaligned. Choose
      // the smaller of the non-virtual alignment and BaseAlignment, which is a
      // conservative lower bound of the complete object alignment.
      CharUnits NonVirtualAlignment =
          Ctx.getASTRecordLayout(BaseDecl).getNonVirtualAlignment();
      BaseAlignment = std::min(BaseAlignment, NonVirtualAlignment);
      Offset = CharUnits::Zero();
    } else {
      const ASTRecordLayout &RL =
          Ctx.getASTRecordLayout(DerivedType->getAsCXXRecordDecl());
      Offset += RL.getBaseClassOffset(BaseDecl);
    }
    DerivedType = Base->getType();
  }

  return std::make_pair(BaseAlignment, Offset);
}

/// Compute the alignment and offset of a binary additive operator.
static std::optional<std::pair<CharUnits, CharUnits>>
getAlignmentAndOffsetFromBinAddOrSub(const Expr *PtrE, const Expr *IntE,
                                     bool IsSub, ASTContext &Ctx) {
  QualType PointeeType = PtrE->getType()->getPointeeType();

  if (!PointeeType->isConstantSizeType())
    return std::nullopt;

  auto P = getBaseAlignmentAndOffsetFromPtr(PtrE, Ctx);

  if (!P)
    return std::nullopt;

  CharUnits EltSize = Ctx.getTypeSizeInChars(PointeeType);
  if (std::optional<llvm::APSInt> IdxRes = IntE->getIntegerConstantExpr(Ctx)) {
    CharUnits Offset = EltSize * IdxRes->getExtValue();
    if (IsSub)
      Offset = -Offset;
    return std::make_pair(P->first, P->second + Offset);
  }

  // If the integer expression isn't a constant expression, compute the lower
  // bound of the alignment using the alignment and offset of the pointer
  // expression and the element size.
  return std::make_pair(
      P->first.alignmentAtOffset(P->second).alignmentAtOffset(EltSize),
      CharUnits::Zero());
}

/// This helper function takes an lvalue expression and returns the alignment of
/// a VarDecl and a constant offset from the VarDecl.
std::optional<std::pair<
    CharUnits,
    CharUnits>> static getBaseAlignmentAndOffsetFromLValue(const Expr *E,
                                                           ASTContext &Ctx) {
  E = E->IgnoreParens();
  switch (E->getStmtClass()) {
  default:
    break;
  case Stmt::CStyleCastExprClass:
  case Stmt::CXXStaticCastExprClass:
  case Stmt::ImplicitCastExprClass: {
    auto *CE = cast<CastExpr>(E);
    const Expr *From = CE->getSubExpr();
    switch (CE->getCastKind()) {
    default:
      break;
    case CK_NoOp:
      return getBaseAlignmentAndOffsetFromLValue(From, Ctx);
    case CK_UncheckedDerivedToBase:
    case CK_DerivedToBase: {
      auto P = getBaseAlignmentAndOffsetFromLValue(From, Ctx);
      if (!P)
        break;
      return getDerivedToBaseAlignmentAndOffset(CE, From->getType(), P->first,
                                                P->second, Ctx);
    }
    }
    break;
  }
  case Stmt::ArraySubscriptExprClass: {
    auto *ASE = cast<ArraySubscriptExpr>(E);
    return getAlignmentAndOffsetFromBinAddOrSub(ASE->getBase(), ASE->getIdx(),
                                                false, Ctx);
  }
  case Stmt::DeclRefExprClass: {
    if (auto *VD = dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())) {
      // FIXME: If VD is captured by copy or is an escaping __block variable,
      // use the alignment of VD's type.
      if (!VD->getType()->isReferenceType()) {
        // Dependent alignment cannot be resolved -> bail out.
        if (VD->hasDependentAlignment())
          break;
        return std::make_pair(Ctx.getDeclAlign(VD), CharUnits::Zero());
      }
      if (VD->hasInit())
        return getBaseAlignmentAndOffsetFromLValue(VD->getInit(), Ctx);
    }
    break;
  }
  case Stmt::MemberExprClass: {
    auto *ME = cast<MemberExpr>(E);
    auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
    if (!FD || FD->getType()->isReferenceType() ||
        FD->getParent()->isInvalidDecl())
      break;
    std::optional<std::pair<CharUnits, CharUnits>> P;
    if (ME->isArrow())
      P = getBaseAlignmentAndOffsetFromPtr(ME->getBase(), Ctx);
    else
      P = getBaseAlignmentAndOffsetFromLValue(ME->getBase(), Ctx);
    if (!P)
      break;
    const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(FD->getParent());
    uint64_t Offset = Layout.getFieldOffset(FD->getFieldIndex());
    return std::make_pair(P->first,
                          P->second + CharUnits::fromQuantity(Offset));
  }
  case Stmt::UnaryOperatorClass: {
    auto *UO = cast<UnaryOperator>(E);
    switch (UO->getOpcode()) {
    default:
      break;
    case UO_Deref:
      return getBaseAlignmentAndOffsetFromPtr(UO->getSubExpr(), Ctx);
    }
    break;
  }
  case Stmt::BinaryOperatorClass: {
    auto *BO = cast<BinaryOperator>(E);
    auto Opcode = BO->getOpcode();
    switch (Opcode) {
    default:
      break;
    case BO_Comma:
      return getBaseAlignmentAndOffsetFromLValue(BO->getRHS(), Ctx);
    }
    break;
  }
  }
  return std::nullopt;
}

/// This helper function takes a pointer expression and returns the alignment of
/// a VarDecl and a constant offset from the VarDecl.
std::optional<std::pair<
    CharUnits, CharUnits>> static getBaseAlignmentAndOffsetFromPtr(const Expr
                                                                       *E,
                                                                   ASTContext
                                                                       &Ctx) {
  E = E->IgnoreParens();
  switch (E->getStmtClass()) {
  default:
    break;
  case Stmt::CStyleCastExprClass:
  case Stmt::CXXStaticCastExprClass:
  case Stmt::ImplicitCastExprClass: {
    auto *CE = cast<CastExpr>(E);
    const Expr *From = CE->getSubExpr();
    switch (CE->getCastKind()) {
    default:
      break;
    case CK_NoOp:
      return getBaseAlignmentAndOffsetFromPtr(From, Ctx);
    case CK_ArrayToPointerDecay:
      return getBaseAlignmentAndOffsetFromLValue(From, Ctx);
    case CK_UncheckedDerivedToBase:
    case CK_DerivedToBase: {
      auto P = getBaseAlignmentAndOffsetFromPtr(From, Ctx);
      if (!P)
        break;
      return getDerivedToBaseAlignmentAndOffset(
          CE, From->getType()->getPointeeType(), P->first, P->second, Ctx);
    }
    }
    break;
  }
  case Stmt::CXXThisExprClass: {
    auto *RD = E->getType()->getPointeeType()->getAsCXXRecordDecl();
    CharUnits Alignment = Ctx.getASTRecordLayout(RD).getNonVirtualAlignment();
    return std::make_pair(Alignment, CharUnits::Zero());
  }
  case Stmt::UnaryOperatorClass: {
    auto *UO = cast<UnaryOperator>(E);
    if (UO->getOpcode() == UO_AddrOf)
      return getBaseAlignmentAndOffsetFromLValue(UO->getSubExpr(), Ctx);
    break;
  }
  case Stmt::BinaryOperatorClass: {
    auto *BO = cast<BinaryOperator>(E);
    auto Opcode = BO->getOpcode();
    switch (Opcode) {
    default:
      break;
    case BO_Add:
    case BO_Sub: {
      const Expr *LHS = BO->getLHS(), *RHS = BO->getRHS();
      if (Opcode == BO_Add && !RHS->getType()->isIntegralOrEnumerationType())
        std::swap(LHS, RHS);
      return getAlignmentAndOffsetFromBinAddOrSub(LHS, RHS, Opcode == BO_Sub,
                                                  Ctx);
    }
    case BO_Comma:
      return getBaseAlignmentAndOffsetFromPtr(BO->getRHS(), Ctx);
    }
    break;
  }
  }
  return std::nullopt;
}

static CharUnits getPresumedAlignmentOfPointer(const Expr *E, Sema &S) {
  // See if we can compute the alignment of a VarDecl and an offset from it.
  std::optional<std::pair<CharUnits, CharUnits>> P =
      getBaseAlignmentAndOffsetFromPtr(E, S.Context);

  if (P)
    return P->first.alignmentAtOffset(P->second);

  // If that failed, return the type's alignment.
  return S.Context.getTypeAlignInChars(E->getType()->getPointeeType());
}

void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) {
  // This is actually a lot of work to potentially be doing on every
  // cast; don't do it if we're ignoring -Wcast_align (as is the default).
  if (getDiagnostics().isIgnored(diag::warn_cast_align, TRange.getBegin()))
    return;

  // Ignore dependent types.
  if (T->isDependentType() || Op->getType()->isDependentType())
    return;

  // Require that the destination be a pointer type.
  const PointerType *DestPtr = T->getAs<PointerType>();
  if (!DestPtr) return;

  // If the destination has alignment 1, we're done.
  QualType DestPointee = DestPtr->getPointeeType();
  if (DestPointee->isIncompleteType()) return;
  CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee);
  if (DestAlign.isOne()) return;

  // Require that the source be a pointer type.
  const PointerType *SrcPtr = Op->getType()->getAs<PointerType>();
  if (!SrcPtr) return;
  QualType SrcPointee = SrcPtr->getPointeeType();

  // Explicitly allow casts from cv void*.  We already implicitly
  // allowed casts to cv void*, since they have alignment 1.
  // Also allow casts involving incomplete types, which implicitly
  // includes 'void'.
  if (SrcPointee->isIncompleteType()) return;

  CharUnits SrcAlign = getPresumedAlignmentOfPointer(Op, *this);

  if (SrcAlign >= DestAlign) return;

  Diag(TRange.getBegin(), diag::warn_cast_align)
    << Op->getType() << T
    << static_cast<unsigned>(SrcAlign.getQuantity())
    << static_cast<unsigned>(DestAlign.getQuantity())
    << TRange << Op->getSourceRange();
}

void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
                            const ArraySubscriptExpr *ASE,
                            bool AllowOnePastEnd, bool IndexNegated) {
  // Already diagnosed by the constant evaluator.
  if (isConstantEvaluatedContext())
    return;

  IndexExpr = IndexExpr->IgnoreParenImpCasts();
  if (IndexExpr->isValueDependent())
    return;

  const Type *EffectiveType =
      BaseExpr->getType()->getPointeeOrArrayElementType();
  BaseExpr = BaseExpr->IgnoreParenCasts();
  const ConstantArrayType *ArrayTy =
      Context.getAsConstantArrayType(BaseExpr->getType());

  LangOptions::StrictFlexArraysLevelKind
    StrictFlexArraysLevel = getLangOpts().getStrictFlexArraysLevel();

  const Type *BaseType =
      ArrayTy == nullptr ? nullptr : ArrayTy->getElementType().getTypePtr();
  bool IsUnboundedArray =
      BaseType == nullptr || BaseExpr->isFlexibleArrayMemberLike(
                                 Context, StrictFlexArraysLevel,
                                 /*IgnoreTemplateOrMacroSubstitution=*/true);
  if (EffectiveType->isDependentType() ||
      (!IsUnboundedArray && BaseType->isDependentType()))
    return;

  Expr::EvalResult Result;
  if (!IndexExpr->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects))
    return;

  llvm::APSInt index = Result.Val.getInt();
  if (IndexNegated) {
    index.setIsUnsigned(false);
    index = -index;
  }

  if (IsUnboundedArray) {
    if (EffectiveType->isFunctionType())
      return;
    if (index.isUnsigned() || !index.isNegative()) {
      const auto &ASTC = getASTContext();
      unsigned AddrBits = ASTC.getTargetInfo().getPointerWidth(
          EffectiveType->getCanonicalTypeInternal().getAddressSpace());
      if (index.getBitWidth() < AddrBits)
        index = index.zext(AddrBits);
      std::optional<CharUnits> ElemCharUnits =
          ASTC.getTypeSizeInCharsIfKnown(EffectiveType);
      // PR50741 - If EffectiveType has unknown size (e.g., if it's a void
      // pointer) bounds-checking isn't meaningful.
      if (!ElemCharUnits || ElemCharUnits->isZero())
        return;
      llvm::APInt ElemBytes(index.getBitWidth(), ElemCharUnits->getQuantity());
      // If index has more active bits than address space, we already know
      // we have a bounds violation to warn about.  Otherwise, compute
      // address of (index + 1)th element, and warn about bounds violation
      // only if that address exceeds address space.
      if (index.getActiveBits() <= AddrBits) {
        bool Overflow;
        llvm::APInt Product(index);
        Product += 1;
        Product = Product.umul_ov(ElemBytes, Overflow);
        if (!Overflow && Product.getActiveBits() <= AddrBits)
          return;
      }

      // Need to compute max possible elements in address space, since that
      // is included in diag message.
      llvm::APInt MaxElems = llvm::APInt::getMaxValue(AddrBits);
      MaxElems = MaxElems.zext(std::max(AddrBits + 1, ElemBytes.getBitWidth()));
      MaxElems += 1;
      ElemBytes = ElemBytes.zextOrTrunc(MaxElems.getBitWidth());
      MaxElems = MaxElems.udiv(ElemBytes);

      unsigned DiagID =
          ASE ? diag::warn_array_index_exceeds_max_addressable_bounds
              : diag::warn_ptr_arith_exceeds_max_addressable_bounds;

      // Diag message shows element size in bits and in "bytes" (platform-
      // dependent CharUnits)
      DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
                          PDiag(DiagID)
                              << toString(index, 10, true) << AddrBits
                              << (unsigned)ASTC.toBits(*ElemCharUnits)
                              << toString(ElemBytes, 10, false)
                              << toString(MaxElems, 10, false)
                              << (unsigned)MaxElems.getLimitedValue(~0U)
                              << IndexExpr->getSourceRange());

      const NamedDecl *ND = nullptr;
      // Try harder to find a NamedDecl to point at in the note.
      while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
        BaseExpr = ASE->getBase()->IgnoreParenCasts();
      if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
        ND = DRE->getDecl();
      if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
        ND = ME->getMemberDecl();

      if (ND)
        DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr,
                            PDiag(diag::note_array_declared_here) << ND);
    }
    return;
  }

  if (index.isUnsigned() || !index.isNegative()) {
    // It is possible that the type of the base expression after
    // IgnoreParenCasts is incomplete, even though the type of the base
    // expression before IgnoreParenCasts is complete (see PR39746 for an
    // example). In this case we have no information about whether the array
    // access exceeds the array bounds. However we can still diagnose an array
    // access which precedes the array bounds.
    if (BaseType->isIncompleteType())
      return;

    llvm::APInt size = ArrayTy->getSize();

    if (BaseType != EffectiveType) {
      // Make sure we're comparing apples to apples when comparing index to
      // size.
      uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType);
      uint64_t array_typesize = Context.getTypeSize(BaseType);

      // Handle ptrarith_typesize being zero, such as when casting to void*.
      // Use the size in bits (what "getTypeSize()" returns) rather than bytes.
      if (!ptrarith_typesize)
        ptrarith_typesize = Context.getCharWidth();

      if (ptrarith_typesize != array_typesize) {
        // There's a cast to a different size type involved.
        uint64_t ratio = array_typesize / ptrarith_typesize;

        // TODO: Be smarter about handling cases where array_typesize is not a
        // multiple of ptrarith_typesize.
        if (ptrarith_typesize * ratio == array_typesize)
          size *= llvm::APInt(size.getBitWidth(), ratio);
      }
    }

    if (size.getBitWidth() > index.getBitWidth())
      index = index.zext(size.getBitWidth());
    else if (size.getBitWidth() < index.getBitWidth())
      size = size.zext(index.getBitWidth());

    // For array subscripting the index must be less than size, but for pointer
    // arithmetic also allow the index (offset) to be equal to size since
    // computing the next address after the end of the array is legal and
    // commonly done e.g. in C++ iterators and range-based for loops.
    if (AllowOnePastEnd ? index.ule(size) : index.ult(size))
      return;

    // Suppress the warning if the subscript expression (as identified by the
    // ']' location) and the index expression are both from macro expansions
    // within a system header.
    if (ASE) {
      SourceLocation RBracketLoc = SourceMgr.getSpellingLoc(
          ASE->getRBracketLoc());
      if (SourceMgr.isInSystemHeader(RBracketLoc)) {
        SourceLocation IndexLoc =
            SourceMgr.getSpellingLoc(IndexExpr->getBeginLoc());
        if (SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc))
          return;
      }
    }

    unsigned DiagID = ASE ? diag::warn_array_index_exceeds_bounds
                          : diag::warn_ptr_arith_exceeds_bounds;
    unsigned CastMsg = (!ASE || BaseType == EffectiveType) ? 0 : 1;
    QualType CastMsgTy = ASE ? ASE->getLHS()->getType() : QualType();

    DiagRuntimeBehavior(
        BaseExpr->getBeginLoc(), BaseExpr,
        PDiag(DiagID) << toString(index, 10, true) << ArrayTy->desugar()
                      << CastMsg << CastMsgTy << IndexExpr->getSourceRange());
  } else {
    unsigned DiagID = diag::warn_array_index_precedes_bounds;
    if (!ASE) {
      DiagID = diag::warn_ptr_arith_precedes_bounds;
      if (index.isNegative()) index = -index;
    }

    DiagRuntimeBehavior(BaseExpr->getBeginLoc(), BaseExpr,
                        PDiag(DiagID) << toString(index, 10, true)
                                      << IndexExpr->getSourceRange());
  }

  const NamedDecl *ND = nullptr;
  // Try harder to find a NamedDecl to point at in the note.
  while (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BaseExpr))
    BaseExpr = ASE->getBase()->IgnoreParenCasts();
  if (const auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
    ND = DRE->getDecl();
  if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr))
    ND = ME->getMemberDecl();

  if (ND)
    DiagRuntimeBehavior(ND->getBeginLoc(), BaseExpr,
                        PDiag(diag::note_array_declared_here) << ND);
}

void Sema::CheckArrayAccess(const Expr *expr) {
  int AllowOnePastEnd = 0;
  while (expr) {
    expr = expr->IgnoreParenImpCasts();
    switch (expr->getStmtClass()) {
      case Stmt::ArraySubscriptExprClass: {
        const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(expr);
        CheckArrayAccess(ASE->getBase(), ASE->getIdx(), ASE,
                         AllowOnePastEnd > 0);
        expr = ASE->getBase();
        break;
      }
      case Stmt::MemberExprClass: {
        expr = cast<MemberExpr>(expr)->getBase();
        break;
      }
      case Stmt::ArraySectionExprClass: {
        const ArraySectionExpr *ASE = cast<ArraySectionExpr>(expr);
        // FIXME: We should probably be checking all of the elements to the
        // 'length' here as well.
        if (ASE->getLowerBound())
          CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(),
                           /*ASE=*/nullptr, AllowOnePastEnd > 0);
        return;
      }
      case Stmt::UnaryOperatorClass: {
        // Only unwrap the * and & unary operators
        const UnaryOperator *UO = cast<UnaryOperator>(expr);
        expr = UO->getSubExpr();
        switch (UO->getOpcode()) {
          case UO_AddrOf:
            AllowOnePastEnd++;
            break;
          case UO_Deref:
            AllowOnePastEnd--;
            break;
          default:
            return;
        }
        break;
      }
      case Stmt::ConditionalOperatorClass: {
        const ConditionalOperator *cond = cast<ConditionalOperator>(expr);
        if (const Expr *lhs = cond->getLHS())
          CheckArrayAccess(lhs);
        if (const Expr *rhs = cond->getRHS())
          CheckArrayAccess(rhs);
        return;
      }
      case Stmt::CXXOperatorCallExprClass: {
        const auto *OCE = cast<CXXOperatorCallExpr>(expr);
        for (const auto *Arg : OCE->arguments())
          CheckArrayAccess(Arg);
        return;
      }
      default:
        return;
    }
  }
}

static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
                                     Expr *RHS, bool isProperty) {
  // Check if RHS is an Objective-C object literal, which also can get
  // immediately zapped in a weak reference.  Note that we explicitly
  // allow ObjCStringLiterals, since those are designed to never really die.
  RHS = RHS->IgnoreParenImpCasts();

  // This enum needs to match with the 'select' in
  // warn_objc_arc_literal_assign (off-by-1).
  SemaObjC::ObjCLiteralKind Kind = S.ObjC().CheckLiteralKind(RHS);
  if (Kind == SemaObjC::LK_String || Kind == SemaObjC::LK_None)
    return false;

  S.Diag(Loc, diag::warn_arc_literal_assign)
    << (unsigned) Kind
    << (isProperty ? 0 : 1)
    << RHS->getSourceRange();

  return true;
}

static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc,
                                    Qualifiers::ObjCLifetime LT,
                                    Expr *RHS, bool isProperty) {
  // Strip off any implicit cast added to get to the one ARC-specific.
  while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
    if (cast->getCastKind() == CK_ARCConsumeObject) {
      S.Diag(Loc, diag::warn_arc_retained_assign)
        << (LT == Qualifiers::OCL_ExplicitNone)
        << (isProperty ? 0 : 1)
        << RHS->getSourceRange();
      return true;
    }
    RHS = cast->getSubExpr();
  }

  if (LT == Qualifiers::OCL_Weak &&
      checkUnsafeAssignLiteral(S, Loc, RHS, isProperty))
    return true;

  return false;
}

bool Sema::checkUnsafeAssigns(SourceLocation Loc,
                              QualType LHS, Expr *RHS) {
  Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();

  if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
    return false;

  if (checkUnsafeAssignObject(*this, Loc, LT, RHS, false))
    return true;

  return false;
}

void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
                              Expr *LHS, Expr *RHS) {
  QualType LHSType;
  // PropertyRef on LHS type need be directly obtained from
  // its declaration as it has a PseudoType.
  ObjCPropertyRefExpr *PRE
    = dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens());
  if (PRE && !PRE->isImplicitProperty()) {
    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
    if (PD)
      LHSType = PD->getType();
  }

  if (LHSType.isNull())
    LHSType = LHS->getType();

  Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();

  if (LT == Qualifiers::OCL_Weak) {
    if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
      getCurFunction()->markSafeWeakUse(LHS);
  }

  if (checkUnsafeAssigns(Loc, LHSType, RHS))
    return;

  // FIXME. Check for other life times.
  if (LT != Qualifiers::OCL_None)
    return;

  if (PRE) {
    if (PRE->isImplicitProperty())
      return;
    const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
    if (!PD)
      return;

    unsigned Attributes = PD->getPropertyAttributes();
    if (Attributes & ObjCPropertyAttribute::kind_assign) {
      // when 'assign' attribute was not explicitly specified
      // by user, ignore it and rely on property type itself
      // for lifetime info.
      unsigned AsWrittenAttr = PD->getPropertyAttributesAsWritten();
      if (!(AsWrittenAttr & ObjCPropertyAttribute::kind_assign) &&
          LHSType->isObjCRetainableType())
        return;

      while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) {
        if (cast->getCastKind() == CK_ARCConsumeObject) {
          Diag(Loc, diag::warn_arc_retained_property_assign)
          << RHS->getSourceRange();
          return;
        }
        RHS = cast->getSubExpr();
      }
    } else if (Attributes & ObjCPropertyAttribute::kind_weak) {
      if (checkUnsafeAssignObject(*this, Loc, Qualifiers::OCL_Weak, RHS, true))
        return;
    }
  }
}

//===--- CHECK: Empty statement body (-Wempty-body) ---------------------===//

static bool ShouldDiagnoseEmptyStmtBody(const SourceManager &SourceMgr,
                                        SourceLocation StmtLoc,
                                        const NullStmt *Body) {
  // Do not warn if the body is a macro that expands to nothing, e.g:
  //
  // #define CALL(x)
  // if (condition)
  //   CALL(0);
  if (Body->hasLeadingEmptyMacro())
    return false;

  // Get line numbers of statement and body.
  bool StmtLineInvalid;
  unsigned StmtLine = SourceMgr.getPresumedLineNumber(StmtLoc,
                                                      &StmtLineInvalid);
  if (StmtLineInvalid)
    return false;

  bool BodyLineInvalid;
  unsigned BodyLine = SourceMgr.getSpellingLineNumber(Body->getSemiLoc(),
                                                      &BodyLineInvalid);
  if (BodyLineInvalid)
    return false;

  // Warn if null statement and body are on the same line.
  if (StmtLine != BodyLine)
    return false;

  return true;
}

void Sema::DiagnoseEmptyStmtBody(SourceLocation StmtLoc,
                                 const Stmt *Body,
                                 unsigned DiagID) {
  // Since this is a syntactic check, don't emit diagnostic for template
  // instantiations, this just adds noise.
  if (CurrentInstantiationScope)
    return;

  // The body should be a null statement.
  const NullStmt *NBody = dyn_cast<NullStmt>(Body);
  if (!NBody)
    return;

  // Do the usual checks.
  if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody))
    return;

  Diag(NBody->getSemiLoc(), DiagID);
  Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line);
}

void Sema::DiagnoseEmptyLoopBody(const Stmt *S,
                                 const Stmt *PossibleBody) {
  assert(!CurrentInstantiationScope); // Ensured by caller

  SourceLocation StmtLoc;
  const Stmt *Body;
  unsigned DiagID;
  if (const ForStmt *FS = dyn_cast<ForStmt>(S)) {
    StmtLoc = FS->getRParenLoc();
    Body = FS->getBody();
    DiagID = diag::warn_empty_for_body;
  } else if (const WhileStmt *WS = dyn_cast<WhileStmt>(S)) {
    StmtLoc = WS->getRParenLoc();
    Body = WS->getBody();
    DiagID = diag::warn_empty_while_body;
  } else
    return; // Neither `for' nor `while'.

  // The body should be a null statement.
  const NullStmt *NBody = dyn_cast<NullStmt>(Body);
  if (!NBody)
    return;

  // Skip expensive checks if diagnostic is disabled.
  if (Diags.isIgnored(DiagID, NBody->getSemiLoc()))
    return;

  // Do the usual checks.
  if (!ShouldDiagnoseEmptyStmtBody(SourceMgr, StmtLoc, NBody))
    return;

  // `for(...);' and `while(...);' are popular idioms, so in order to keep
  // noise level low, emit diagnostics only if for/while is followed by a
  // CompoundStmt, e.g.:
  //    for (int i = 0; i < n; i++);
  //    {
  //      a(i);
  //    }
  // or if for/while is followed by a statement with more indentation
  // than for/while itself:
  //    for (int i = 0; i < n; i++);
  //      a(i);
  bool ProbableTypo = isa<CompoundStmt>(PossibleBody);
  if (!ProbableTypo) {
    bool BodyColInvalid;
    unsigned BodyCol = SourceMgr.getPresumedColumnNumber(
        PossibleBody->getBeginLoc(), &BodyColInvalid);
    if (BodyColInvalid)
      return;

    bool StmtColInvalid;
    unsigned StmtCol =
        SourceMgr.getPresumedColumnNumber(S->getBeginLoc(), &StmtColInvalid);
    if (StmtColInvalid)
      return;

    if (BodyCol > StmtCol)
      ProbableTypo = true;
  }

  if (ProbableTypo) {
    Diag(NBody->getSemiLoc(), DiagID);
    Diag(NBody->getSemiLoc(), diag::note_empty_body_on_separate_line);
  }
}

//===--- CHECK: Warn on self move with std::move. -------------------------===//

void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
                             SourceLocation OpLoc) {
  if (Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, OpLoc))
    return;

  if (inTemplateInstantiation())
    return;

  // Strip parens and casts away.
  LHSExpr = LHSExpr->IgnoreParenImpCasts();
  RHSExpr = RHSExpr->IgnoreParenImpCasts();

  // Check for a call to std::move or for a static_cast<T&&>(..) to an xvalue
  // which we can treat as an inlined std::move
  if (const auto *CE = dyn_cast<CallExpr>(RHSExpr);
      CE && CE->getNumArgs() == 1 && CE->isCallToStdMove())
    RHSExpr = CE->getArg(0);
  else if (const auto *CXXSCE = dyn_cast<CXXStaticCastExpr>(RHSExpr);
           CXXSCE && CXXSCE->isXValue())
    RHSExpr = CXXSCE->getSubExpr();
  else
    return;

  const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
  const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);

  // Two DeclRefExpr's, check that the decls are the same.
  if (LHSDeclRef && RHSDeclRef) {
    if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
      return;
    if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
        RHSDeclRef->getDecl()->getCanonicalDecl())
      return;

    auto D = Diag(OpLoc, diag::warn_self_move)
             << LHSExpr->getType() << LHSExpr->getSourceRange()
             << RHSExpr->getSourceRange();
    if (const FieldDecl *F =
            getSelfAssignmentClassMemberCandidate(RHSDeclRef->getDecl()))
      D << 1 << F
        << FixItHint::CreateInsertion(LHSDeclRef->getBeginLoc(), "this->");
    else
      D << 0;
    return;
  }

  // Member variables require a different approach to check for self moves.
  // MemberExpr's are the same if every nested MemberExpr refers to the same
  // Decl and that the base Expr's are DeclRefExpr's with the same Decl or
  // the base Expr's are CXXThisExpr's.
  const Expr *LHSBase = LHSExpr;
  const Expr *RHSBase = RHSExpr;
  const MemberExpr *LHSME = dyn_cast<MemberExpr>(LHSExpr);
  const MemberExpr *RHSME = dyn_cast<MemberExpr>(RHSExpr);
  if (!LHSME || !RHSME)
    return;

  while (LHSME && RHSME) {
    if (LHSME->getMemberDecl()->getCanonicalDecl() !=
        RHSME->getMemberDecl()->getCanonicalDecl())
      return;

    LHSBase = LHSME->getBase();
    RHSBase = RHSME->getBase();
    LHSME = dyn_cast<MemberExpr>(LHSBase);
    RHSME = dyn_cast<MemberExpr>(RHSBase);
  }

  LHSDeclRef = dyn_cast<DeclRefExpr>(LHSBase);
  RHSDeclRef = dyn_cast<DeclRefExpr>(RHSBase);
  if (LHSDeclRef && RHSDeclRef) {
    if (!LHSDeclRef->getDecl() || !RHSDeclRef->getDecl())
      return;
    if (LHSDeclRef->getDecl()->getCanonicalDecl() !=
        RHSDeclRef->getDecl()->getCanonicalDecl())
      return;

    Diag(OpLoc, diag::warn_self_move)
        << LHSExpr->getType() << 0 << LHSExpr->getSourceRange()
        << RHSExpr->getSourceRange();
    return;
  }

  if (isa<CXXThisExpr>(LHSBase) && isa<CXXThisExpr>(RHSBase))
    Diag(OpLoc, diag::warn_self_move)
        << LHSExpr->getType() << 0 << LHSExpr->getSourceRange()
        << RHSExpr->getSourceRange();
}

//===--- Layout compatibility ----------------------------------------------//

static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2);

/// Check if two enumeration types are layout-compatible.
static bool isLayoutCompatible(const ASTContext &C, const EnumDecl *ED1,
                               const EnumDecl *ED2) {
  // C++11 [dcl.enum] p8:
  // Two enumeration types are layout-compatible if they have the same
  // underlying type.
  return ED1->isComplete() && ED2->isComplete() &&
         C.hasSameType(ED1->getIntegerType(), ED2->getIntegerType());
}

/// Check if two fields are layout-compatible.
/// Can be used on union members, which are exempt from alignment requirement
/// of common initial sequence.
static bool isLayoutCompatible(const ASTContext &C, const FieldDecl *Field1,
                               const FieldDecl *Field2,
                               bool AreUnionMembers = false) {
  [[maybe_unused]] const Type *Field1Parent =
      Field1->getParent()->getTypeForDecl();
  [[maybe_unused]] const Type *Field2Parent =
      Field2->getParent()->getTypeForDecl();
  assert(((Field1Parent->isStructureOrClassType() &&
           Field2Parent->isStructureOrClassType()) ||
          (Field1Parent->isUnionType() && Field2Parent->isUnionType())) &&
         "Can't evaluate layout compatibility between a struct field and a "
         "union field.");
  assert(((!AreUnionMembers && Field1Parent->isStructureOrClassType()) ||
          (AreUnionMembers && Field1Parent->isUnionType())) &&
         "AreUnionMembers should be 'true' for union fields (only).");

  if (!isLayoutCompatible(C, Field1->getType(), Field2->getType()))
    return false;

  if (Field1->isBitField() != Field2->isBitField())
    return false;

  if (Field1->isBitField()) {
    // Make sure that the bit-fields are the same length.
    unsigned Bits1 = Field1->getBitWidthValue();
    unsigned Bits2 = Field2->getBitWidthValue();

    if (Bits1 != Bits2)
      return false;
  }

  if (Field1->hasAttr<clang::NoUniqueAddressAttr>() ||
      Field2->hasAttr<clang::NoUniqueAddressAttr>())
    return false;

  if (!AreUnionMembers &&
      Field1->getMaxAlignment() != Field2->getMaxAlignment())
    return false;

  return true;
}

/// Check if two standard-layout structs are layout-compatible.
/// (C++11 [class.mem] p17)
static bool isLayoutCompatibleStruct(const ASTContext &C, const RecordDecl *RD1,
                                     const RecordDecl *RD2) {
  // Get to the class where the fields are declared
  if (const CXXRecordDecl *D1CXX = dyn_cast<CXXRecordDecl>(RD1))
    RD1 = D1CXX->getStandardLayoutBaseWithFields();

  if (const CXXRecordDecl *D2CXX = dyn_cast<CXXRecordDecl>(RD2))
    RD2 = D2CXX->getStandardLayoutBaseWithFields();

  // Check the fields.
  return llvm::equal(RD1->fields(), RD2->fields(),
                     [&C](const FieldDecl *F1, const FieldDecl *F2) -> bool {
                       return isLayoutCompatible(C, F1, F2);
                     });
}

/// Check if two standard-layout unions are layout-compatible.
/// (C++11 [class.mem] p18)
static bool isLayoutCompatibleUnion(const ASTContext &C, const RecordDecl *RD1,
                                    const RecordDecl *RD2) {
  llvm::SmallPtrSet<const FieldDecl *, 8> UnmatchedFields(llvm::from_range,
                                                          RD2->fields());

  for (auto *Field1 : RD1->fields()) {
    auto I = UnmatchedFields.begin();
    auto E = UnmatchedFields.end();

    for ( ; I != E; ++I) {
      if (isLayoutCompatible(C, Field1, *I, /*IsUnionMember=*/true)) {
        bool Result = UnmatchedFields.erase(*I);
        (void) Result;
        assert(Result);
        break;
      }
    }
    if (I == E)
      return false;
  }

  return UnmatchedFields.empty();
}

static bool isLayoutCompatible(const ASTContext &C, const RecordDecl *RD1,
                               const RecordDecl *RD2) {
  if (RD1->isUnion() != RD2->isUnion())
    return false;

  if (RD1->isUnion())
    return isLayoutCompatibleUnion(C, RD1, RD2);
  else
    return isLayoutCompatibleStruct(C, RD1, RD2);
}

/// Check if two types are layout-compatible in C++11 sense.
static bool isLayoutCompatible(const ASTContext &C, QualType T1, QualType T2) {
  if (T1.isNull() || T2.isNull())
    return false;

  // C++20 [basic.types] p11:
  // Two types cv1 T1 and cv2 T2 are layout-compatible types
  // if T1 and T2 are the same type, layout-compatible enumerations (9.7.1),
  // or layout-compatible standard-layout class types (11.4).
  T1 = T1.getCanonicalType().getUnqualifiedType();
  T2 = T2.getCanonicalType().getUnqualifiedType();

  if (C.hasSameType(T1, T2))
    return true;

  const Type::TypeClass TC1 = T1->getTypeClass();
  const Type::TypeClass TC2 = T2->getTypeClass();

  if (TC1 != TC2)
    return false;

  if (TC1 == Type::Enum) {
    return isLayoutCompatible(C,
                              cast<EnumType>(T1)->getDecl(),
                              cast<EnumType>(T2)->getDecl());
  } else if (TC1 == Type::Record) {
    if (!T1->isStandardLayoutType() || !T2->isStandardLayoutType())
      return false;

    return isLayoutCompatible(C,
                              cast<RecordType>(T1)->getDecl(),
                              cast<RecordType>(T2)->getDecl());
  }

  return false;
}

bool Sema::IsLayoutCompatible(QualType T1, QualType T2) const {
  return isLayoutCompatible(getASTContext(), T1, T2);
}

//===-------------- Pointer interconvertibility ----------------------------//

bool Sema::IsPointerInterconvertibleBaseOf(const TypeSourceInfo *Base,
                                           const TypeSourceInfo *Derived) {
  QualType BaseT = Base->getType()->getCanonicalTypeUnqualified();
  QualType DerivedT = Derived->getType()->getCanonicalTypeUnqualified();

  if (BaseT->isStructureOrClassType() && DerivedT->isStructureOrClassType() &&
      getASTContext().hasSameType(BaseT, DerivedT))
    return true;

  if (!IsDerivedFrom(Derived->getTypeLoc().getBeginLoc(), DerivedT, BaseT))
    return false;

  // Per [basic.compound]/4.3, containing object has to be standard-layout.
  if (DerivedT->getAsCXXRecordDecl()->isStandardLayout())
    return true;

  return false;
}

//===--- CHECK: pointer_with_type_tag attribute: datatypes should match ----//

/// Given a type tag expression find the type tag itself.
///
/// \param TypeExpr Type tag expression, as it appears in user's code.
///
/// \param VD Declaration of an identifier that appears in a type tag.
///
/// \param MagicValue Type tag magic value.
///
/// \param isConstantEvaluated whether the evalaution should be performed in

/// constant context.
static bool FindTypeTagExpr(const Expr *TypeExpr, const ASTContext &Ctx,
                            const ValueDecl **VD, uint64_t *MagicValue,
                            bool isConstantEvaluated) {
  while(true) {
    if (!TypeExpr)
      return false;

    TypeExpr = TypeExpr->IgnoreParenImpCasts()->IgnoreParenCasts();

    switch (TypeExpr->getStmtClass()) {
    case Stmt::UnaryOperatorClass: {
      const UnaryOperator *UO = cast<UnaryOperator>(TypeExpr);
      if (UO->getOpcode() == UO_AddrOf || UO->getOpcode() == UO_Deref) {
        TypeExpr = UO->getSubExpr();
        continue;
      }
      return false;
    }

    case Stmt::DeclRefExprClass: {
      const DeclRefExpr *DRE = cast<DeclRefExpr>(TypeExpr);
      *VD = DRE->getDecl();
      return true;
    }

    case Stmt::IntegerLiteralClass: {
      const IntegerLiteral *IL = cast<IntegerLiteral>(TypeExpr);
      llvm::APInt MagicValueAPInt = IL->getValue();
      if (MagicValueAPInt.getActiveBits() <= 64) {
        *MagicValue = MagicValueAPInt.getZExtValue();
        return true;
      } else
        return false;
    }

    case Stmt::BinaryConditionalOperatorClass:
    case Stmt::ConditionalOperatorClass: {
      const AbstractConditionalOperator *ACO =
          cast<AbstractConditionalOperator>(TypeExpr);
      bool Result;
      if (ACO->getCond()->EvaluateAsBooleanCondition(Result, Ctx,
                                                     isConstantEvaluated)) {
        if (Result)
          TypeExpr = ACO->getTrueExpr();
        else
          TypeExpr = ACO->getFalseExpr();
        continue;
      }
      return false;
    }

    case Stmt::BinaryOperatorClass: {
      const BinaryOperator *BO = cast<BinaryOperator>(TypeExpr);
      if (BO->getOpcode() == BO_Comma) {
        TypeExpr = BO->getRHS();
        continue;
      }
      return false;
    }

    default:
      return false;
    }
  }
}

/// Retrieve the C type corresponding to type tag TypeExpr.
///
/// \param TypeExpr Expression that specifies a type tag.
///
/// \param MagicValues Registered magic values.
///
/// \param FoundWrongKind Set to true if a type tag was found, but of a wrong
///        kind.
///
/// \param TypeInfo Information about the corresponding C type.
///
/// \param isConstantEvaluated whether the evalaution should be performed in
/// constant context.
///
/// \returns true if the corresponding C type was found.
static bool GetMatchingCType(
    const IdentifierInfo *ArgumentKind, const Expr *TypeExpr,
    const ASTContext &Ctx,
    const llvm::DenseMap<Sema::TypeTagMagicValue, Sema::TypeTagData>
        *MagicValues,
    bool &FoundWrongKind, Sema::TypeTagData &TypeInfo,
    bool isConstantEvaluated) {
  FoundWrongKind = false;

  // Variable declaration that has type_tag_for_datatype attribute.
  const ValueDecl *VD = nullptr;

  uint64_t MagicValue;

  if (!FindTypeTagExpr(TypeExpr, Ctx, &VD, &MagicValue, isConstantEvaluated))
    return false;

  if (VD) {
    if (TypeTagForDatatypeAttr *I = VD->getAttr<TypeTagForDatatypeAttr>()) {
      if (I->getArgumentKind() != ArgumentKind) {
        FoundWrongKind = true;
        return false;
      }
      TypeInfo.Type = I->getMatchingCType();
      TypeInfo.LayoutCompatible = I->getLayoutCompatible();
      TypeInfo.MustBeNull = I->getMustBeNull();
      return true;
    }
    return false;
  }

  if (!MagicValues)
    return false;

  llvm::DenseMap<Sema::TypeTagMagicValue,
                 Sema::TypeTagData>::const_iterator I =
      MagicValues->find(std::make_pair(ArgumentKind, MagicValue));
  if (I == MagicValues->end())
    return false;

  TypeInfo = I->second;
  return true;
}

void Sema::RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
                                      uint64_t MagicValue, QualType Type,
                                      bool LayoutCompatible,
                                      bool MustBeNull) {
  if (!TypeTagForDatatypeMagicValues)
    TypeTagForDatatypeMagicValues.reset(
        new llvm::DenseMap<TypeTagMagicValue, TypeTagData>);

  TypeTagMagicValue Magic(ArgumentKind, MagicValue);
  (*TypeTagForDatatypeMagicValues)[Magic] =
      TypeTagData(Type, LayoutCompatible, MustBeNull);
}

static bool IsSameCharType(QualType T1, QualType T2) {
  const BuiltinType *BT1 = T1->getAs<BuiltinType>();
  if (!BT1)
    return false;

  const BuiltinType *BT2 = T2->getAs<BuiltinType>();
  if (!BT2)
    return false;

  BuiltinType::Kind T1Kind = BT1->getKind();
  BuiltinType::Kind T2Kind = BT2->getKind();

  return (T1Kind == BuiltinType::SChar  && T2Kind == BuiltinType::Char_S) ||
         (T1Kind == BuiltinType::UChar  && T2Kind == BuiltinType::Char_U) ||
         (T1Kind == BuiltinType::Char_U && T2Kind == BuiltinType::UChar) ||
         (T1Kind == BuiltinType::Char_S && T2Kind == BuiltinType::SChar);
}

void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
                                    const ArrayRef<const Expr *> ExprArgs,
                                    SourceLocation CallSiteLoc) {
  const IdentifierInfo *ArgumentKind = Attr->getArgumentKind();
  bool IsPointerAttr = Attr->getIsPointer();

  // Retrieve the argument representing the 'type_tag'.
  unsigned TypeTagIdxAST = Attr->getTypeTagIdx().getASTIndex();
  if (TypeTagIdxAST >= ExprArgs.size()) {
    Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
        << 0 << Attr->getTypeTagIdx().getSourceIndex();
    return;
  }
  const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST];
  bool FoundWrongKind;
  TypeTagData TypeInfo;
  if (!GetMatchingCType(ArgumentKind, TypeTagExpr, Context,
                        TypeTagForDatatypeMagicValues.get(), FoundWrongKind,
                        TypeInfo, isConstantEvaluatedContext())) {
    if (FoundWrongKind)
      Diag(TypeTagExpr->getExprLoc(),
           diag::warn_type_tag_for_datatype_wrong_kind)
        << TypeTagExpr->getSourceRange();
    return;
  }

  // Retrieve the argument representing the 'arg_idx'.
  unsigned ArgumentIdxAST = Attr->getArgumentIdx().getASTIndex();
  if (ArgumentIdxAST >= ExprArgs.size()) {
    Diag(CallSiteLoc, diag::err_tag_index_out_of_range)
        << 1 << Attr->getArgumentIdx().getSourceIndex();
    return;
  }
  const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST];
  if (IsPointerAttr) {
    // Skip implicit cast of pointer to `void *' (as a function argument).
    if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgumentExpr))
      if (ICE->getType()->isVoidPointerType() &&
          ICE->getCastKind() == CK_BitCast)
        ArgumentExpr = ICE->getSubExpr();
  }
  QualType ArgumentType = ArgumentExpr->getType();

  // Passing a `void*' pointer shouldn't trigger a warning.
  if (IsPointerAttr && ArgumentType->isVoidPointerType())
    return;

  if (TypeInfo.MustBeNull) {
    // Type tag with matching void type requires a null pointer.
    if (!ArgumentExpr->isNullPointerConstant(Context,
                                             Expr::NPC_ValueDependentIsNotNull)) {
      Diag(ArgumentExpr->getExprLoc(),
           diag::warn_type_safety_null_pointer_required)
          << ArgumentKind->getName()
          << ArgumentExpr->getSourceRange()
          << TypeTagExpr->getSourceRange();
    }
    return;
  }

  QualType RequiredType = TypeInfo.Type;
  if (IsPointerAttr)
    RequiredType = Context.getPointerType(RequiredType);

  bool mismatch = false;
  if (!TypeInfo.LayoutCompatible) {
    mismatch = !Context.hasSameType(ArgumentType, RequiredType);

    // C++11 [basic.fundamental] p1:
    // Plain char, signed char, and unsigned char are three distinct types.
    //
    // But we treat plain `char' as equivalent to `signed char' or `unsigned
    // char' depending on the current char signedness mode.
    if (mismatch)
      if ((IsPointerAttr && IsSameCharType(ArgumentType->getPointeeType(),
                                           RequiredType->getPointeeType())) ||
          (!IsPointerAttr && IsSameCharType(ArgumentType, RequiredType)))
        mismatch = false;
  } else
    if (IsPointerAttr)
      mismatch = !isLayoutCompatible(Context,
                                     ArgumentType->getPointeeType(),
                                     RequiredType->getPointeeType());
    else
      mismatch = !isLayoutCompatible(Context, ArgumentType, RequiredType);

  if (mismatch)
    Diag(ArgumentExpr->getExprLoc(), diag::warn_type_safety_type_mismatch)
        << ArgumentType << ArgumentKind
        << TypeInfo.LayoutCompatible << RequiredType
        << ArgumentExpr->getSourceRange()
        << TypeTagExpr->getSourceRange();
}

void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
                                         CharUnits Alignment) {
  MisalignedMembers.emplace_back(E, RD, MD, Alignment);
}

void Sema::DiagnoseMisalignedMembers() {
  for (MisalignedMember &m : MisalignedMembers) {
    const NamedDecl *ND = m.RD;
    if (ND->getName().empty()) {
      if (const TypedefNameDecl *TD = m.RD->getTypedefNameForAnonDecl())
        ND = TD;
    }
    Diag(m.E->getBeginLoc(), diag::warn_taking_address_of_packed_member)
        << m.MD << ND << m.E->getSourceRange();
  }
  MisalignedMembers.clear();
}

void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
  E = E->IgnoreParens();
  if (!T->isPointerType() && !T->isIntegerType() && !T->isDependentType())
    return;
  if (isa<UnaryOperator>(E) &&
      cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) {
    auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
    if (isa<MemberExpr>(Op)) {
      auto *MA = llvm::find(MisalignedMembers, MisalignedMember(Op));
      if (MA != MisalignedMembers.end() &&
          (T->isDependentType() || T->isIntegerType() ||
           (T->isPointerType() && (T->getPointeeType()->isIncompleteType() ||
                                   Context.getTypeAlignInChars(
                                       T->getPointeeType()) <= MA->Alignment))))
        MisalignedMembers.erase(MA);
    }
  }
}

void Sema::RefersToMemberWithReducedAlignment(
    Expr *E,
    llvm::function_ref<void(Expr *, RecordDecl *, FieldDecl *, CharUnits)>
        Action) {
  const auto *ME = dyn_cast<MemberExpr>(E);
  if (!ME)
    return;

  // No need to check expressions with an __unaligned-qualified type.
  if (E->getType().getQualifiers().hasUnaligned())
    return;

  // For a chain of MemberExpr like "a.b.c.d" this list
  // will keep FieldDecl's like [d, c, b].
  SmallVector<FieldDecl *, 4> ReverseMemberChain;
  const MemberExpr *TopME = nullptr;
  bool AnyIsPacked = false;
  do {
    QualType BaseType = ME->getBase()->getType();
    if (BaseType->isDependentType())
      return;
    if (ME->isArrow())
      BaseType = BaseType->getPointeeType();
    RecordDecl *RD = BaseType->castAs<RecordType>()->getDecl();
    if (RD->isInvalidDecl())
      return;

    ValueDecl *MD = ME->getMemberDecl();
    auto *FD = dyn_cast<FieldDecl>(MD);
    // We do not care about non-data members.
    if (!FD || FD->isInvalidDecl())
      return;

    AnyIsPacked =
        AnyIsPacked || (RD->hasAttr<PackedAttr>() || MD->hasAttr<PackedAttr>());
    ReverseMemberChain.push_back(FD);

    TopME = ME;
    ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParens());
  } while (ME);
  assert(TopME && "We did not compute a topmost MemberExpr!");

  // Not the scope of this diagnostic.
  if (!AnyIsPacked)
    return;

  const Expr *TopBase = TopME->getBase()->IgnoreParenImpCasts();
  const auto *DRE = dyn_cast<DeclRefExpr>(TopBase);
  // TODO: The innermost base of the member expression may be too complicated.
  // For now, just disregard these cases. This is left for future
  // improvement.
  if (!DRE && !isa<CXXThisExpr>(TopBase))
      return;

  // Alignment expected by the whole expression.
  CharUnits ExpectedAlignment = Context.getTypeAlignInChars(E->getType());

  // No need to do anything else with this case.
  if (ExpectedAlignment.isOne())
    return;

  // Synthesize offset of the whole access.
  CharUnits Offset;
  for (const FieldDecl *FD : llvm::reverse(ReverseMemberChain))
    Offset += Context.toCharUnitsFromBits(Context.getFieldOffset(FD));

  // Compute the CompleteObjectAlignment as the alignment of the whole chain.
  CharUnits CompleteObjectAlignment = Context.getTypeAlignInChars(
      ReverseMemberChain.back()->getParent()->getTypeForDecl());

  // The base expression of the innermost MemberExpr may give
  // stronger guarantees than the class containing the member.
  if (DRE && !TopME->isArrow()) {
    const ValueDecl *VD = DRE->getDecl();
    if (!VD->getType()->isReferenceType())
      CompleteObjectAlignment =
          std::max(CompleteObjectAlignment, Context.getDeclAlign(VD));
  }

  // Check if the synthesized offset fulfills the alignment.
  if (Offset % ExpectedAlignment != 0 ||
      // It may fulfill the offset it but the effective alignment may still be
      // lower than the expected expression alignment.
      CompleteObjectAlignment < ExpectedAlignment) {
    // If this happens, we want to determine a sensible culprit of this.
    // Intuitively, watching the chain of member expressions from right to
    // left, we start with the required alignment (as required by the field
    // type) but some packed attribute in that chain has reduced the alignment.
    // It may happen that another packed structure increases it again. But if
    // we are here such increase has not been enough. So pointing the first
    // FieldDecl that either is packed or else its RecordDecl is,
    // seems reasonable.
    FieldDecl *FD = nullptr;
    CharUnits Alignment;
    for (FieldDecl *FDI : ReverseMemberChain) {
      if (FDI->hasAttr<PackedAttr>() ||
          FDI->getParent()->hasAttr<PackedAttr>()) {
        FD = FDI;
        Alignment = std::min(
            Context.getTypeAlignInChars(FD->getType()),
            Context.getTypeAlignInChars(FD->getParent()->getTypeForDecl()));
        break;
      }
    }
    assert(FD && "We did not find a packed FieldDecl!");
    Action(E, FD->getParent(), FD, Alignment);
  }
}

void Sema::CheckAddressOfPackedMember(Expr *rhs) {
  using namespace std::placeholders;

  RefersToMemberWithReducedAlignment(
      rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1,
                     _2, _3, _4));
}

// Performs a similar job to Sema::UsualUnaryConversions, but without any
// implicit promotion of integral/enumeration types.
static ExprResult BuiltinVectorMathConversions(Sema &S, Expr *E) {
  // First, convert to an r-value.
  ExprResult Res = S.DefaultFunctionArrayLvalueConversion(E);
  if (Res.isInvalid())
    return ExprError();

  // Promote floating-point types.
  return S.UsualUnaryFPConversions(Res.get());
}

bool Sema::PrepareBuiltinElementwiseMathOneArgCall(
    CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr) {
  if (checkArgCount(TheCall, 1))
    return true;

  ExprResult A = BuiltinVectorMathConversions(*this, TheCall->getArg(0));
  if (A.isInvalid())
    return true;

  TheCall->setArg(0, A.get());
  QualType TyA = A.get()->getType();

  if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA,
                                  ArgTyRestr, 1))
    return true;

  TheCall->setType(TyA);
  return false;
}

bool Sema::BuiltinElementwiseMath(CallExpr *TheCall,
                                  EltwiseBuiltinArgTyRestriction ArgTyRestr) {
  if (auto Res = BuiltinVectorMath(TheCall, ArgTyRestr); Res.has_value()) {
    TheCall->setType(*Res);
    return false;
  }
  return true;
}

bool Sema::BuiltinVectorToScalarMath(CallExpr *TheCall) {
  std::optional<QualType> Res = BuiltinVectorMath(TheCall);
  if (!Res)
    return true;

  if (auto *VecTy0 = (*Res)->getAs<VectorType>())
    TheCall->setType(VecTy0->getElementType());
  else
    TheCall->setType(*Res);

  return false;
}

static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS,
                                             SourceLocation Loc) {
  QualType L = LHS->getEnumCoercedType(S.Context),
           R = RHS->getEnumCoercedType(S.Context);
  if (L->isUnscopedEnumerationType() && R->isUnscopedEnumerationType() &&
      !S.Context.hasSameUnqualifiedType(L, R)) {
    return S.Diag(Loc, diag::err_conv_mixed_enum_types)
           << LHS->getSourceRange() << RHS->getSourceRange()
           << /*Arithmetic Between*/ 0 << L << R;
  }
  return false;
}

std::optional<QualType>
Sema::BuiltinVectorMath(CallExpr *TheCall,
                        EltwiseBuiltinArgTyRestriction ArgTyRestr) {
  if (checkArgCount(TheCall, 2))
    return std::nullopt;

  if (checkBuiltinVectorMathMixedEnums(
          *this, TheCall->getArg(0), TheCall->getArg(1), TheCall->getExprLoc()))
    return std::nullopt;

  Expr *Args[2];
  for (int I = 0; I < 2; ++I) {
    ExprResult Converted =
        BuiltinVectorMathConversions(*this, TheCall->getArg(I));
    if (Converted.isInvalid())
      return std::nullopt;
    Args[I] = Converted.get();
  }

  SourceLocation LocA = Args[0]->getBeginLoc();
  QualType TyA = Args[0]->getType();
  QualType TyB = Args[1]->getType();

  if (checkMathBuiltinElementType(*this, LocA, TyA, ArgTyRestr, 1))
    return std::nullopt;

  if (!Context.hasSameUnqualifiedType(TyA, TyB)) {
    Diag(LocA, diag::err_typecheck_call_different_arg_types) << TyA << TyB;
    return std::nullopt;
  }

  TheCall->setArg(0, Args[0]);
  TheCall->setArg(1, Args[1]);
  return TyA;
}

bool Sema::BuiltinElementwiseTernaryMath(
    CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr) {
  if (checkArgCount(TheCall, 3))
    return true;

  SourceLocation Loc = TheCall->getExprLoc();
  if (checkBuiltinVectorMathMixedEnums(*this, TheCall->getArg(0),
                                       TheCall->getArg(1), Loc) ||
      checkBuiltinVectorMathMixedEnums(*this, TheCall->getArg(1),
                                       TheCall->getArg(2), Loc))
    return true;

  Expr *Args[3];
  for (int I = 0; I < 3; ++I) {
    ExprResult Converted =
        BuiltinVectorMathConversions(*this, TheCall->getArg(I));
    if (Converted.isInvalid())
      return true;
    Args[I] = Converted.get();
  }

  int ArgOrdinal = 1;
  for (Expr *Arg : Args) {
    if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
                                    ArgTyRestr, ArgOrdinal++))
      return true;
  }

  for (int I = 1; I < 3; ++I) {
    if (Args[0]->getType().getCanonicalType() !=
        Args[I]->getType().getCanonicalType()) {
      return Diag(Args[0]->getBeginLoc(),
                  diag::err_typecheck_call_different_arg_types)
             << Args[0]->getType() << Args[I]->getType();
    }

    TheCall->setArg(I, Args[I]);
  }

  TheCall->setType(Args[0]->getType());
  return false;
}

bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall) {
  if (checkArgCount(TheCall, 1))
    return true;

  ExprResult A = UsualUnaryConversions(TheCall->getArg(0));
  if (A.isInvalid())
    return true;

  TheCall->setArg(0, A.get());
  return false;
}

bool Sema::BuiltinNonDeterministicValue(CallExpr *TheCall) {
  if (checkArgCount(TheCall, 1))
    return true;

  ExprResult Arg = TheCall->getArg(0);
  QualType TyArg = Arg.get()->getType();

  if (!TyArg->isBuiltinType() && !TyArg->isVectorType())
    return Diag(TheCall->getArg(0)->getBeginLoc(),
                diag::err_builtin_invalid_arg_type)
           << 1 << /* vector */ 2 << /* integer */ 1 << /* fp */ 1 << TyArg;

  TheCall->setType(TyArg);
  return false;
}

ExprResult Sema::BuiltinMatrixTranspose(CallExpr *TheCall,
                                        ExprResult CallResult) {
  if (checkArgCount(TheCall, 1))
    return ExprError();

  ExprResult MatrixArg = DefaultLvalueConversion(TheCall->getArg(0));
  if (MatrixArg.isInvalid())
    return MatrixArg;
  Expr *Matrix = MatrixArg.get();

  auto *MType = Matrix->getType()->getAs<ConstantMatrixType>();
  if (!MType) {
    Diag(Matrix->getBeginLoc(), diag::err_builtin_invalid_arg_type)
        << 1 << /* matrix */ 3 << /* no int */ 0 << /* no fp */ 0
        << Matrix->getType();
    return ExprError();
  }

  // Create returned matrix type by swapping rows and columns of the argument
  // matrix type.
  QualType ResultType = Context.getConstantMatrixType(
      MType->getElementType(), MType->getNumColumns(), MType->getNumRows());

  // Change the return type to the type of the returned matrix.
  TheCall->setType(ResultType);

  // Update call argument to use the possibly converted matrix argument.
  TheCall->setArg(0, Matrix);
  return CallResult;
}

// Get and verify the matrix dimensions.
static std::optional<unsigned>
getAndVerifyMatrixDimension(Expr *Expr, StringRef Name, Sema &S) {
  SourceLocation ErrorPos;
  std::optional<llvm::APSInt> Value =
      Expr->getIntegerConstantExpr(S.Context, &ErrorPos);
  if (!Value) {
    S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_scalar_unsigned_arg)
        << Name;
    return {};
  }
  uint64_t Dim = Value->getZExtValue();
  if (!ConstantMatrixType::isDimensionValid(Dim)) {
    S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_invalid_dimension)
        << Name << ConstantMatrixType::getMaxElementsPerDimension();
    return {};
  }
  return Dim;
}

ExprResult Sema::BuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
                                              ExprResult CallResult) {
  if (!getLangOpts().MatrixTypes) {
    Diag(TheCall->getBeginLoc(), diag::err_builtin_matrix_disabled);
    return ExprError();
  }

  if (checkArgCount(TheCall, 4))
    return ExprError();

  unsigned PtrArgIdx = 0;
  Expr *PtrExpr = TheCall->getArg(PtrArgIdx);
  Expr *RowsExpr = TheCall->getArg(1);
  Expr *ColumnsExpr = TheCall->getArg(2);
  Expr *StrideExpr = TheCall->getArg(3);

  bool ArgError = false;

  // Check pointer argument.
  {
    ExprResult PtrConv = DefaultFunctionArrayLvalueConversion(PtrExpr);
    if (PtrConv.isInvalid())
      return PtrConv;
    PtrExpr = PtrConv.get();
    TheCall->setArg(0, PtrExpr);
    if (PtrExpr->isTypeDependent()) {
      TheCall->setType(Context.DependentTy);
      return TheCall;
    }
  }

  auto *PtrTy = PtrExpr->getType()->getAs<PointerType>();
  QualType ElementTy;
  if (!PtrTy) {
    Diag(PtrExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
        << PtrArgIdx + 1 << 0 << /* pointer to element ty */ 5 << /* no fp */ 0
        << PtrExpr->getType();
    ArgError = true;
  } else {
    ElementTy = PtrTy->getPointeeType().getUnqualifiedType();

    if (!ConstantMatrixType::isValidElementType(ElementTy)) {
      Diag(PtrExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
          << PtrArgIdx + 1 << 0 << /* pointer to element ty */ 5
          << /* no fp */ 0 << PtrExpr->getType();
      ArgError = true;
    }
  }

  // Apply default Lvalue conversions and convert the expression to size_t.
  auto ApplyArgumentConversions = [this](Expr *E) {
    ExprResult Conv = DefaultLvalueConversion(E);
    if (Conv.isInvalid())
      return Conv;

    return tryConvertExprToType(Conv.get(), Context.getSizeType());
  };

  // Apply conversion to row and column expressions.
  ExprResult RowsConv = ApplyArgumentConversions(RowsExpr);
  if (!RowsConv.isInvalid()) {
    RowsExpr = RowsConv.get();
    TheCall->setArg(1, RowsExpr);
  } else
    RowsExpr = nullptr;

  ExprResult ColumnsConv = ApplyArgumentConversions(ColumnsExpr);
  if (!ColumnsConv.isInvalid()) {
    ColumnsExpr = ColumnsConv.get();
    TheCall->setArg(2, ColumnsExpr);
  } else
    ColumnsExpr = nullptr;

  // If any part of the result matrix type is still pending, just use
  // Context.DependentTy, until all parts are resolved.
  if ((RowsExpr && RowsExpr->isTypeDependent()) ||
      (ColumnsExpr && ColumnsExpr->isTypeDependent())) {
    TheCall->setType(Context.DependentTy);
    return CallResult;
  }

  // Check row and column dimensions.
  std::optional<unsigned> MaybeRows;
  if (RowsExpr)
    MaybeRows = getAndVerifyMatrixDimension(RowsExpr, "row", *this);

  std::optional<unsigned> MaybeColumns;
  if (ColumnsExpr)
    MaybeColumns = getAndVerifyMatrixDimension(ColumnsExpr, "column", *this);

  // Check stride argument.
  ExprResult StrideConv = ApplyArgumentConversions(StrideExpr);
  if (StrideConv.isInvalid())
    return ExprError();
  StrideExpr = StrideConv.get();
  TheCall->setArg(3, StrideExpr);

  if (MaybeRows) {
    if (std::optional<llvm::APSInt> Value =
            StrideExpr->getIntegerConstantExpr(Context)) {
      uint64_t Stride = Value->getZExtValue();
      if (Stride < *MaybeRows) {
        Diag(StrideExpr->getBeginLoc(),
             diag::err_builtin_matrix_stride_too_small);
        ArgError = true;
      }
    }
  }

  if (ArgError || !MaybeRows || !MaybeColumns)
    return ExprError();

  TheCall->setType(
      Context.getConstantMatrixType(ElementTy, *MaybeRows, *MaybeColumns));
  return CallResult;
}

ExprResult Sema::BuiltinMatrixColumnMajorStore(CallExpr *TheCall,
                                               ExprResult CallResult) {
  if (checkArgCount(TheCall, 3))
    return ExprError();

  unsigned PtrArgIdx = 1;
  Expr *MatrixExpr = TheCall->getArg(0);
  Expr *PtrExpr = TheCall->getArg(PtrArgIdx);
  Expr *StrideExpr = TheCall->getArg(2);

  bool ArgError = false;

  {
    ExprResult MatrixConv = DefaultLvalueConversion(MatrixExpr);
    if (MatrixConv.isInvalid())
      return MatrixConv;
    MatrixExpr = MatrixConv.get();
    TheCall->setArg(0, MatrixExpr);
  }
  if (MatrixExpr->isTypeDependent()) {
    TheCall->setType(Context.DependentTy);
    return TheCall;
  }

  auto *MatrixTy = MatrixExpr->getType()->getAs<ConstantMatrixType>();
  if (!MatrixTy) {
    Diag(MatrixExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
        << 1 << /* matrix ty */ 3 << 0 << 0 << MatrixExpr->getType();
    ArgError = true;
  }

  {
    ExprResult PtrConv = DefaultFunctionArrayLvalueConversion(PtrExpr);
    if (PtrConv.isInvalid())
      return PtrConv;
    PtrExpr = PtrConv.get();
    TheCall->setArg(1, PtrExpr);
    if (PtrExpr->isTypeDependent()) {
      TheCall->setType(Context.DependentTy);
      return TheCall;
    }
  }

  // Check pointer argument.
  auto *PtrTy = PtrExpr->getType()->getAs<PointerType>();
  if (!PtrTy) {
    Diag(PtrExpr->getBeginLoc(), diag::err_builtin_invalid_arg_type)
        << PtrArgIdx + 1 << 0 << /* pointer to element ty */ 5 << 0
        << PtrExpr->getType();
    ArgError = true;
  } else {
    QualType ElementTy = PtrTy->getPointeeType();
    if (ElementTy.isConstQualified()) {
      Diag(PtrExpr->getBeginLoc(), diag::err_builtin_matrix_store_to_const);
      ArgError = true;
    }
    ElementTy = ElementTy.getUnqualifiedType().getCanonicalType();
    if (MatrixTy &&
        !Context.hasSameType(ElementTy, MatrixTy->getElementType())) {
      Diag(PtrExpr->getBeginLoc(),
           diag::err_builtin_matrix_pointer_arg_mismatch)
          << ElementTy << MatrixTy->getElementType();
      ArgError = true;
    }
  }

  // Apply default Lvalue conversions and convert the stride expression to
  // size_t.
  {
    ExprResult StrideConv = DefaultLvalueConversion(StrideExpr);
    if (StrideConv.isInvalid())
      return StrideConv;

    StrideConv = tryConvertExprToType(StrideConv.get(), Context.getSizeType());
    if (StrideConv.isInvalid())
      return StrideConv;
    StrideExpr = StrideConv.get();
    TheCall->setArg(2, StrideExpr);
  }

  // Check stride argument.
  if (MatrixTy) {
    if (std::optional<llvm::APSInt> Value =
            StrideExpr->getIntegerConstantExpr(Context)) {
      uint64_t Stride = Value->getZExtValue();
      if (Stride < MatrixTy->getNumRows()) {
        Diag(StrideExpr->getBeginLoc(),
             diag::err_builtin_matrix_stride_too_small);
        ArgError = true;
      }
    }
  }

  if (ArgError)
    return ExprError();

  return CallResult;
}

void Sema::CheckTCBEnforcement(const SourceLocation CallExprLoc,
                               const NamedDecl *Callee) {
  // This warning does not make sense in code that has no runtime behavior.
  if (isUnevaluatedContext())
    return;

  const NamedDecl *Caller = getCurFunctionOrMethodDecl();

  if (!Caller || !Caller->hasAttr<EnforceTCBAttr>())
    return;

  // Search through the enforce_tcb and enforce_tcb_leaf attributes to find
  // all TCBs the callee is a part of.
  llvm::StringSet<> CalleeTCBs;
  for (const auto *A : Callee->specific_attrs<EnforceTCBAttr>())
    CalleeTCBs.insert(A->getTCBName());
  for (const auto *A : Callee->specific_attrs<EnforceTCBLeafAttr>())
    CalleeTCBs.insert(A->getTCBName());

  // Go through the TCBs the caller is a part of and emit warnings if Caller
  // is in a TCB that the Callee is not.
  for (const auto *A : Caller->specific_attrs<EnforceTCBAttr>()) {
    StringRef CallerTCB = A->getTCBName();
    if (CalleeTCBs.count(CallerTCB) == 0) {
      this->Diag(CallExprLoc, diag::warn_tcb_enforcement_violation)
          << Callee << CallerTCB;
    }
  }
}
