//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===//
//
// 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 the actions class which performs semantic analysis and
// builds an AST out of a parse stream.
//
//===----------------------------------------------------------------------===//

#include "UsedDeclVisitor.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/RISCVIntrinsicManager.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaAMDGPU.h"
#include "clang/Sema/SemaARM.h"
#include "clang/Sema/SemaAVR.h"
#include "clang/Sema/SemaBPF.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/SemaDirectX.h"
#include "clang/Sema/SemaHLSL.h"
#include "clang/Sema/SemaHexagon.h"
#include "clang/Sema/SemaLoongArch.h"
#include "clang/Sema/SemaM68k.h"
#include "clang/Sema/SemaMIPS.h"
#include "clang/Sema/SemaMSP430.h"
#include "clang/Sema/SemaNVPTX.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/SemaOpenACC.h"
#include "clang/Sema/SemaOpenCL.h"
#include "clang/Sema/SemaOpenMP.h"
#include "clang/Sema/SemaPPC.h"
#include "clang/Sema/SemaPseudoObject.h"
#include "clang/Sema/SemaRISCV.h"
#include "clang/Sema/SemaSPIRV.h"
#include "clang/Sema/SemaSYCL.h"
#include "clang/Sema/SemaSwift.h"
#include "clang/Sema/SemaSystemZ.h"
#include "clang/Sema/SemaWasm.h"
#include "clang/Sema/SemaX86.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "clang/Sema/TypoCorrection.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/TimeProfiler.h"
#include <optional>

using namespace clang;
using namespace sema;

SourceLocation Sema::getLocForEndOfToken(SourceLocation Loc, unsigned Offset) {
  return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
}

SourceRange
Sema::getRangeForNextToken(SourceLocation Loc, bool IncludeMacros,
                           bool IncludeComments,
                           std::optional<tok::TokenKind> ExpectedToken) {
  if (!Loc.isValid())
    return SourceRange();
  std::optional<Token> NextToken =
      Lexer::findNextToken(Loc, SourceMgr, LangOpts, IncludeComments);
  if (!NextToken)
    return SourceRange();
  if (ExpectedToken && NextToken->getKind() != *ExpectedToken)
    return SourceRange();
  SourceLocation TokenStart = NextToken->getLocation();
  SourceLocation TokenEnd = NextToken->getLastLoc();
  if (!TokenStart.isValid() || !TokenEnd.isValid())
    return SourceRange();
  if (!IncludeMacros && (TokenStart.isMacroID() || TokenEnd.isMacroID()))
    return SourceRange();

  return SourceRange(TokenStart, TokenEnd);
}

ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }

DarwinSDKInfo *
Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
                                              StringRef Platform) {
  auto *SDKInfo = getDarwinSDKInfoForAvailabilityChecking();
  if (!SDKInfo && !WarnedDarwinSDKInfoMissing) {
    Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking)
        << Platform;
    WarnedDarwinSDKInfoMissing = true;
  }
  return SDKInfo;
}

DarwinSDKInfo *Sema::getDarwinSDKInfoForAvailabilityChecking() {
  if (CachedDarwinSDKInfo)
    return CachedDarwinSDKInfo->get();
  auto SDKInfo = parseDarwinSDKInfo(
      PP.getFileManager().getVirtualFileSystem(),
      PP.getHeaderSearchInfo().getHeaderSearchOpts().Sysroot);
  if (SDKInfo && *SDKInfo) {
    CachedDarwinSDKInfo = std::make_unique<DarwinSDKInfo>(std::move(**SDKInfo));
    return CachedDarwinSDKInfo->get();
  }
  if (!SDKInfo)
    llvm::consumeError(SDKInfo.takeError());
  CachedDarwinSDKInfo = std::unique_ptr<DarwinSDKInfo>();
  return nullptr;
}

IdentifierInfo *Sema::InventAbbreviatedTemplateParameterTypeName(
    const IdentifierInfo *ParamName, unsigned int Index) {
  std::string InventedName;
  llvm::raw_string_ostream OS(InventedName);

  if (!ParamName)
    OS << "auto:" << Index + 1;
  else
    OS << ParamName->getName() << ":auto";

  return &Context.Idents.get(OS.str());
}

PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
                                       const Preprocessor &PP) {
  PrintingPolicy Policy = Context.getPrintingPolicy();
  // In diagnostics, we print _Bool as bool if the latter is defined as the
  // former.
  Policy.Bool = Context.getLangOpts().Bool;
  if (!Policy.Bool) {
    if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
      Policy.Bool = BoolMacro->isObjectLike() &&
                    BoolMacro->getNumTokens() == 1 &&
                    BoolMacro->getReplacementToken(0).is(tok::kw__Bool);
    }
  }

  // Shorten the data output if needed
  Policy.EntireContentsOfLargeArray = false;

  return Policy;
}

void Sema::ActOnTranslationUnitScope(Scope *S) {
  TUScope = S;
  PushDeclContext(S, Context.getTranslationUnitDecl());
}

namespace clang {
namespace sema {

class SemaPPCallbacks : public PPCallbacks {
  Sema *S = nullptr;
  llvm::SmallVector<SourceLocation, 8> IncludeStack;
  llvm::SmallVector<llvm::TimeTraceProfilerEntry *, 8> ProfilerStack;

public:
  void set(Sema &S) { this->S = &S; }

  void reset() { S = nullptr; }

  void FileChanged(SourceLocation Loc, FileChangeReason Reason,
                   SrcMgr::CharacteristicKind FileType,
                   FileID PrevFID) override {
    if (!S)
      return;
    switch (Reason) {
    case EnterFile: {
      SourceManager &SM = S->getSourceManager();
      SourceLocation IncludeLoc = SM.getIncludeLoc(SM.getFileID(Loc));
      if (IncludeLoc.isValid()) {
        if (llvm::timeTraceProfilerEnabled()) {
          OptionalFileEntryRef FE = SM.getFileEntryRefForID(SM.getFileID(Loc));
          ProfilerStack.push_back(llvm::timeTraceAsyncProfilerBegin(
              "Source", FE ? FE->getName() : StringRef("<unknown>")));
        }

        IncludeStack.push_back(IncludeLoc);
        S->DiagnoseNonDefaultPragmaAlignPack(
            Sema::PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude,
            IncludeLoc);
      }
      break;
    }
    case ExitFile:
      if (!IncludeStack.empty()) {
        if (llvm::timeTraceProfilerEnabled())
          llvm::timeTraceProfilerEnd(ProfilerStack.pop_back_val());

        S->DiagnoseNonDefaultPragmaAlignPack(
            Sema::PragmaAlignPackDiagnoseKind::ChangedStateAtExit,
            IncludeStack.pop_back_val());
      }
      break;
    default:
      break;
    }
  }
  void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
                        diag::Severity Mapping, StringRef Str) override {
    // If one of the analysis-based diagnostics was enabled while processing
    // a function, we want to note it in the analysis-based warnings so they
    // can be run at the end of the function body even if the analysis warnings
    // are disabled at that point.
    SmallVector<diag::kind, 256> GroupDiags;
    diag::Flavor Flavor =
        Str[1] == 'W' ? diag::Flavor::WarningOrError : diag::Flavor::Remark;
    StringRef Group = Str.substr(2);

    if (S->PP.getDiagnostics().getDiagnosticIDs()->getDiagnosticsInGroup(
            Flavor, Group, GroupDiags))
      return;

    for (diag::kind K : GroupDiags) {
      // Note: the cases in this switch should be kept in sync with the
      // diagnostics in AnalysisBasedWarnings::getPolicyInEffectAt().
      AnalysisBasedWarnings::Policy &Override =
          S->AnalysisWarnings.getPolicyOverrides();
      switch (K) {
      default: break;
      case diag::warn_unreachable:
      case diag::warn_unreachable_break:
      case diag::warn_unreachable_return:
      case diag::warn_unreachable_loop_increment:
        Override.enableCheckUnreachable = true;
        break;
      case diag::warn_double_lock:
        Override.enableThreadSafetyAnalysis = true;
        break;
      case diag::warn_use_in_invalid_state:
        Override.enableConsumedAnalysis = true;
        break;
      }
    }
  }
};

} // end namespace sema
} // end namespace clang

const unsigned Sema::MaxAlignmentExponent;
const uint64_t Sema::MaximumAlignment;

Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
           TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
    : SemaBase(*this), CollectStats(false), TUKind(TUKind),
      CurFPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp),
      Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()),
      SourceMgr(PP.getSourceManager()), APINotes(SourceMgr, LangOpts),
      AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr),
      LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr),
      OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr),
      StackHandler(Diags), CurScope(nullptr), Ident_super(nullptr),
      AMDGPUPtr(std::make_unique<SemaAMDGPU>(*this)),
      ARMPtr(std::make_unique<SemaARM>(*this)),
      AVRPtr(std::make_unique<SemaAVR>(*this)),
      BPFPtr(std::make_unique<SemaBPF>(*this)),
      CodeCompletionPtr(
          std::make_unique<SemaCodeCompletion>(*this, CodeCompleter)),
      CUDAPtr(std::make_unique<SemaCUDA>(*this)),
      DirectXPtr(std::make_unique<SemaDirectX>(*this)),
      HLSLPtr(std::make_unique<SemaHLSL>(*this)),
      HexagonPtr(std::make_unique<SemaHexagon>(*this)),
      LoongArchPtr(std::make_unique<SemaLoongArch>(*this)),
      M68kPtr(std::make_unique<SemaM68k>(*this)),
      MIPSPtr(std::make_unique<SemaMIPS>(*this)),
      MSP430Ptr(std::make_unique<SemaMSP430>(*this)),
      NVPTXPtr(std::make_unique<SemaNVPTX>(*this)),
      ObjCPtr(std::make_unique<SemaObjC>(*this)),
      OpenACCPtr(std::make_unique<SemaOpenACC>(*this)),
      OpenCLPtr(std::make_unique<SemaOpenCL>(*this)),
      OpenMPPtr(std::make_unique<SemaOpenMP>(*this)),
      PPCPtr(std::make_unique<SemaPPC>(*this)),
      PseudoObjectPtr(std::make_unique<SemaPseudoObject>(*this)),
      RISCVPtr(std::make_unique<SemaRISCV>(*this)),
      SPIRVPtr(std::make_unique<SemaSPIRV>(*this)),
      SYCLPtr(std::make_unique<SemaSYCL>(*this)),
      SwiftPtr(std::make_unique<SemaSwift>(*this)),
      SystemZPtr(std::make_unique<SemaSystemZ>(*this)),
      WasmPtr(std::make_unique<SemaWasm>(*this)),
      X86Ptr(std::make_unique<SemaX86>(*this)),
      MSPointerToMemberRepresentationMethod(
          LangOpts.getMSPointerToMemberRepresentationMethod()),
      MSStructPragmaOn(false), VtorDispStack(LangOpts.getVtorDispMode()),
      AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)),
      DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
      CodeSegStack(nullptr), StrictGuardStackCheckStack(false),
      FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr),
      VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
      StdCoroutineTraitsCache(nullptr), IdResolver(pp),
      OriginalLexicalContext(nullptr), StdInitializerList(nullptr),
      StdTypeIdentity(nullptr),
      FullyCheckedComparisonCategories(
          static_cast<unsigned>(ComparisonCategoryType::Last) + 1),
      StdSourceLocationImplDecl(nullptr), CXXTypeInfoDecl(nullptr),
      GlobalNewDeleteDeclared(false), DisableTypoCorrection(false),
      TyposCorrected(0), IsBuildingRecoveryCallExpr(false), NumSFINAEErrors(0),
      AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr),
      InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
      ArgPackSubstIndex(std::nullopt), SatisfactionCache(Context) {
  assert(pp.TUKind == TUKind);
  TUScope = nullptr;

  LoadedExternalKnownNamespaces = false;
  for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
    ObjC().NSNumberLiteralMethods[I] = nullptr;

  if (getLangOpts().ObjC)
    ObjC().NSAPIObj.reset(new NSAPI(Context));

  if (getLangOpts().CPlusPlus)
    FieldCollector.reset(new CXXFieldCollector());

  // Tell diagnostics how to render things from the AST library.
  Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context);

  // This evaluation context exists to ensure that there's always at least one
  // valid evaluation context available. It is never removed from the
  // evaluation stack.
  ExprEvalContexts.emplace_back(
      ExpressionEvaluationContext::PotentiallyEvaluated, 0, CleanupInfo{},
      nullptr, ExpressionEvaluationContextRecord::EK_Other);

  // Initialization of data sharing attributes stack for OpenMP
  OpenMP().InitDataSharingAttributesStack();

  std::unique_ptr<sema::SemaPPCallbacks> Callbacks =
      std::make_unique<sema::SemaPPCallbacks>();
  SemaPPCallbackHandler = Callbacks.get();
  PP.addPPCallbacks(std::move(Callbacks));
  SemaPPCallbackHandler->set(*this);

  CurFPFeatures.setFPEvalMethod(PP.getCurrentFPEvalMethod());
}

// Anchor Sema's type info to this TU.
void Sema::anchor() {}

void Sema::addImplicitTypedef(StringRef Name, QualType T) {
  DeclarationName DN = &Context.Idents.get(Name);
  if (IdResolver.begin(DN) == IdResolver.end())
    PushOnScopeChains(Context.buildImplicitTypedef(T, Name), TUScope);
}

void Sema::Initialize() {
  // Create BuiltinVaListDecl *before* ExternalSemaSource::InitializeSema(this)
  // because during initialization ASTReader can emit globals that require
  // name mangling. And the name mangling uses BuiltinVaListDecl.
  if (Context.getTargetInfo().hasBuiltinMSVaList())
    (void)Context.getBuiltinMSVaListDecl();
  (void)Context.getBuiltinVaListDecl();

  if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
    SC->InitializeSema(*this);

  // Tell the external Sema source about this Sema object.
  if (ExternalSemaSource *ExternalSema
      = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
    ExternalSema->InitializeSema(*this);

  // This needs to happen after ExternalSemaSource::InitializeSema(this) or we
  // will not be able to merge any duplicate __va_list_tag decls correctly.
  VAListTagName = PP.getIdentifierInfo("__va_list_tag");

  if (!TUScope)
    return;

  // Initialize predefined 128-bit integer types, if needed.
  if (Context.getTargetInfo().hasInt128Type() ||
      (Context.getAuxTargetInfo() &&
       Context.getAuxTargetInfo()->hasInt128Type())) {
    // If either of the 128-bit integer types are unavailable to name lookup,
    // define them now.
    DeclarationName Int128 = &Context.Idents.get("__int128_t");
    if (IdResolver.begin(Int128) == IdResolver.end())
      PushOnScopeChains(Context.getInt128Decl(), TUScope);

    DeclarationName UInt128 = &Context.Idents.get("__uint128_t");
    if (IdResolver.begin(UInt128) == IdResolver.end())
      PushOnScopeChains(Context.getUInt128Decl(), TUScope);
  }


  // Initialize predefined Objective-C types:
  if (getLangOpts().ObjC) {
    // If 'SEL' does not yet refer to any declarations, make it refer to the
    // predefined 'SEL'.
    DeclarationName SEL = &Context.Idents.get("SEL");
    if (IdResolver.begin(SEL) == IdResolver.end())
      PushOnScopeChains(Context.getObjCSelDecl(), TUScope);

    // If 'id' does not yet refer to any declarations, make it refer to the
    // predefined 'id'.
    DeclarationName Id = &Context.Idents.get("id");
    if (IdResolver.begin(Id) == IdResolver.end())
      PushOnScopeChains(Context.getObjCIdDecl(), TUScope);

    // Create the built-in typedef for 'Class'.
    DeclarationName Class = &Context.Idents.get("Class");
    if (IdResolver.begin(Class) == IdResolver.end())
      PushOnScopeChains(Context.getObjCClassDecl(), TUScope);

    // Create the built-in forward declaratino for 'Protocol'.
    DeclarationName Protocol = &Context.Idents.get("Protocol");
    if (IdResolver.begin(Protocol) == IdResolver.end())
      PushOnScopeChains(Context.getObjCProtocolDecl(), TUScope);
  }

  // Create the internal type for the *StringMakeConstantString builtins.
  DeclarationName ConstantString = &Context.Idents.get("__NSConstantString");
  if (IdResolver.begin(ConstantString) == IdResolver.end())
    PushOnScopeChains(Context.getCFConstantStringDecl(), TUScope);

  // Initialize Microsoft "predefined C++ types".
  if (getLangOpts().MSVCCompat) {
    if (getLangOpts().CPlusPlus &&
        IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
      PushOnScopeChains(Context.getMSTypeInfoTagDecl(), TUScope);

    addImplicitTypedef("size_t", Context.getSizeType());
  }

  // Initialize predefined OpenCL types and supported extensions and (optional)
  // core features.
  if (getLangOpts().OpenCL) {
    getOpenCLOptions().addSupport(
        Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts());
    addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
    addImplicitTypedef("event_t", Context.OCLEventTy);
    auto OCLCompatibleVersion = getLangOpts().getOpenCLCompatibleVersion();
    if (OCLCompatibleVersion >= 200) {
      if (getLangOpts().OpenCLCPlusPlus || getLangOpts().Blocks) {
        addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
        addImplicitTypedef("queue_t", Context.OCLQueueTy);
      }
      if (getLangOpts().OpenCLPipes)
        addImplicitTypedef("reserve_id_t", Context.OCLReserveIDTy);
      addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
      addImplicitTypedef("atomic_uint",
                         Context.getAtomicType(Context.UnsignedIntTy));
      addImplicitTypedef("atomic_float",
                         Context.getAtomicType(Context.FloatTy));
      // OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
      // 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
      addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));


      // OpenCL v2.0 s6.13.11.6:
      // - The atomic_long and atomic_ulong types are supported if the
      //   cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
      //   extensions are supported.
      // - The atomic_double type is only supported if double precision
      //   is supported and the cl_khr_int64_base_atomics and
      //   cl_khr_int64_extended_atomics extensions are supported.
      // - If the device address space is 64-bits, the data types
      //   atomic_intptr_t, atomic_uintptr_t, atomic_size_t and
      //   atomic_ptrdiff_t are supported if the cl_khr_int64_base_atomics and
      //   cl_khr_int64_extended_atomics extensions are supported.

      auto AddPointerSizeDependentTypes = [&]() {
        auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
        auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
        auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
        auto AtomicPtrDiffT =
            Context.getAtomicType(Context.getPointerDiffType());
        addImplicitTypedef("atomic_size_t", AtomicSizeT);
        addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
        addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
        addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
      };

      if (Context.getTypeSize(Context.getSizeType()) == 32) {
        AddPointerSizeDependentTypes();
      }

      if (getOpenCLOptions().isSupported("cl_khr_fp16", getLangOpts())) {
        auto AtomicHalfT = Context.getAtomicType(Context.HalfTy);
        addImplicitTypedef("atomic_half", AtomicHalfT);
      }

      std::vector<QualType> Atomic64BitTypes;
      if (getOpenCLOptions().isSupported("cl_khr_int64_base_atomics",
                                         getLangOpts()) &&
          getOpenCLOptions().isSupported("cl_khr_int64_extended_atomics",
                                         getLangOpts())) {
        if (getOpenCLOptions().isSupported("cl_khr_fp64", getLangOpts())) {
          auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
          addImplicitTypedef("atomic_double", AtomicDoubleT);
          Atomic64BitTypes.push_back(AtomicDoubleT);
        }
        auto AtomicLongT = Context.getAtomicType(Context.LongTy);
        auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
        addImplicitTypedef("atomic_long", AtomicLongT);
        addImplicitTypedef("atomic_ulong", AtomicULongT);


        if (Context.getTypeSize(Context.getSizeType()) == 64) {
          AddPointerSizeDependentTypes();
        }
      }
    }

#define EXT_OPAQUE_TYPE(ExtType, Id, Ext)                                      \
  if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) {                   \
    addImplicitTypedef(#ExtType, Context.Id##Ty);                              \
  }
#include "clang/Basic/OpenCLExtensionTypes.def"
  }

  if (Context.getTargetInfo().hasAArch64ACLETypes() ||
      (Context.getAuxTargetInfo() &&
       Context.getAuxTargetInfo()->hasAArch64ACLETypes())) {
#define SVE_TYPE(Name, Id, SingletonId)                                        \
  addImplicitTypedef(#Name, Context.SingletonId);
#define NEON_VECTOR_TYPE(Name, BaseType, ElBits, NumEls, VectorKind)           \
  addImplicitTypedef(                                                          \
      #Name, Context.getVectorType(Context.BaseType, NumEls, VectorKind));
#include "clang/Basic/AArch64ACLETypes.def"
  }

  if (Context.getTargetInfo().getTriple().isPPC64()) {
#define PPC_VECTOR_MMA_TYPE(Name, Id, Size) \
      addImplicitTypedef(#Name, Context.Id##Ty);
#include "clang/Basic/PPCTypes.def"
#define PPC_VECTOR_VSX_TYPE(Name, Id, Size) \
    addImplicitTypedef(#Name, Context.Id##Ty);
#include "clang/Basic/PPCTypes.def"
  }

  if (Context.getTargetInfo().hasRISCVVTypes()) {
#define RVV_TYPE(Name, Id, SingletonId)                                        \
  addImplicitTypedef(Name, Context.SingletonId);
#include "clang/Basic/RISCVVTypes.def"
  }

  if (Context.getTargetInfo().getTriple().isWasm() &&
      Context.getTargetInfo().hasFeature("reference-types")) {
#define WASM_TYPE(Name, Id, SingletonId)                                       \
  addImplicitTypedef(Name, Context.SingletonId);
#include "clang/Basic/WebAssemblyReferenceTypes.def"
  }

  if (Context.getTargetInfo().getTriple().isAMDGPU() ||
      (Context.getAuxTargetInfo() &&
       Context.getAuxTargetInfo()->getTriple().isAMDGPU())) {
#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align)                       \
  addImplicitTypedef(Name, Context.SingletonId);
#include "clang/Basic/AMDGPUTypes.def"
  }

  if (Context.getTargetInfo().hasBuiltinMSVaList()) {
    DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
    if (IdResolver.begin(MSVaList) == IdResolver.end())
      PushOnScopeChains(Context.getBuiltinMSVaListDecl(), TUScope);
  }

  DeclarationName BuiltinVaList = &Context.Idents.get("__builtin_va_list");
  if (IdResolver.begin(BuiltinVaList) == IdResolver.end())
    PushOnScopeChains(Context.getBuiltinVaListDecl(), TUScope);
}

Sema::~Sema() {
  assert(InstantiatingSpecializations.empty() &&
         "failed to clean up an InstantiatingTemplate?");

  if (VisContext) FreeVisContext();

  // Kill all the active scopes.
  for (sema::FunctionScopeInfo *FSI : FunctionScopes)
    delete FSI;

  // Tell the SemaConsumer to forget about us; we're going out of scope.
  if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
    SC->ForgetSema();

  // Detach from the external Sema source.
  if (ExternalSemaSource *ExternalSema
        = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource()))
    ExternalSema->ForgetSema();

  // Delete cached satisfactions.
  std::vector<ConstraintSatisfaction *> Satisfactions;
  Satisfactions.reserve(SatisfactionCache.size());
  for (auto &Node : SatisfactionCache)
    Satisfactions.push_back(&Node);
  for (auto *Node : Satisfactions)
    delete Node;

  threadSafety::threadSafetyCleanup(ThreadSafetyDeclCache);

  // Destroys data sharing attributes stack for OpenMP
  OpenMP().DestroyDataSharingAttributesStack();

  // Detach from the PP callback handler which outlives Sema since it's owned
  // by the preprocessor.
  SemaPPCallbackHandler->reset();
}

void Sema::runWithSufficientStackSpace(SourceLocation Loc,
                                       llvm::function_ref<void()> Fn) {
  StackHandler.runWithSufficientStackSpace(Loc, Fn);
}

bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
                                      UnavailableAttr::ImplicitReason reason) {
  // If we're not in a function, it's an error.
  FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext);
  if (!fn) return false;

  // If we're in template instantiation, it's an error.
  if (inTemplateInstantiation())
    return false;

  // If that function's not in a system header, it's an error.
  if (!Context.getSourceManager().isInSystemHeader(loc))
    return false;

  // If the function is already unavailable, it's not an error.
  if (fn->hasAttr<UnavailableAttr>()) return true;

  fn->addAttr(UnavailableAttr::CreateImplicit(Context, "", reason, loc));
  return true;
}

ASTMutationListener *Sema::getASTMutationListener() const {
  return getASTConsumer().GetASTMutationListener();
}

void Sema::addExternalSource(IntrusiveRefCntPtr<ExternalSemaSource> E) {
  assert(E && "Cannot use with NULL ptr");

  if (!ExternalSource) {
    ExternalSource = std::move(E);
    return;
  }

  if (auto *Ex = dyn_cast<MultiplexExternalSemaSource>(ExternalSource.get()))
    Ex->AddSource(std::move(E));
  else
    ExternalSource = llvm::makeIntrusiveRefCnt<MultiplexExternalSemaSource>(
        ExternalSource, std::move(E));
}

void Sema::PrintStats() const {
  llvm::errs() << "\n*** Semantic Analysis Stats:\n";
  llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n";

  BumpAlloc.PrintStats();
  AnalysisWarnings.PrintStats();
}

void Sema::diagnoseNullableToNonnullConversion(QualType DstType,
                                               QualType SrcType,
                                               SourceLocation Loc) {
  std::optional<NullabilityKind> ExprNullability = SrcType->getNullability();
  if (!ExprNullability || (*ExprNullability != NullabilityKind::Nullable &&
                           *ExprNullability != NullabilityKind::NullableResult))
    return;

  std::optional<NullabilityKind> TypeNullability = DstType->getNullability();
  if (!TypeNullability || *TypeNullability != NullabilityKind::NonNull)
    return;

  Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType;
}

// Generate diagnostics when adding or removing effects in a type conversion.
void Sema::diagnoseFunctionEffectConversion(QualType DstType, QualType SrcType,
                                            SourceLocation Loc) {
  const auto SrcFX = FunctionEffectsRef::get(SrcType);
  const auto DstFX = FunctionEffectsRef::get(DstType);
  if (SrcFX != DstFX) {
    for (const auto &Diff : FunctionEffectDiffVector(SrcFX, DstFX)) {
      if (Diff.shouldDiagnoseConversion(SrcType, SrcFX, DstType, DstFX))
        Diag(Loc, diag::warn_invalid_add_func_effects) << Diff.effectName();
    }
  }
}

void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E) {
  // nullptr only exists from C++11 on, so don't warn on its absence earlier.
  if (!getLangOpts().CPlusPlus11)
    return;

  if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer)
    return;

  const Expr *EStripped = E->IgnoreParenImpCasts();
  if (EStripped->getType()->isNullPtrType())
    return;
  if (isa<GNUNullExpr>(EStripped))
    return;

  if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant,
                      E->getBeginLoc()))
    return;

  // Don't diagnose the conversion from a 0 literal to a null pointer argument
  // in a synthesized call to operator<=>.
  if (!CodeSynthesisContexts.empty() &&
      CodeSynthesisContexts.back().Kind ==
          CodeSynthesisContext::RewritingOperatorAsSpaceship)
    return;

  // Ignore null pointers in defaulted comparison operators.
  FunctionDecl *FD = getCurFunctionDecl();
  if (FD && FD->isDefaulted()) {
    return;
  }

  // If it is a macro from system header, and if the macro name is not "NULL",
  // do not warn.
  // Note that uses of "NULL" will be ignored above on systems that define it
  // as __null.
  SourceLocation MaybeMacroLoc = E->getBeginLoc();
  if (Diags.getSuppressSystemWarnings() &&
      SourceMgr.isInSystemMacro(MaybeMacroLoc) &&
      !findMacroSpelling(MaybeMacroLoc, "NULL"))
    return;

  Diag(E->getBeginLoc(), diag::warn_zero_as_null_pointer_constant)
      << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
}

/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// The result is of the given category.
ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
                                   CastKind Kind, ExprValueKind VK,
                                   const CXXCastPath *BasePath,
                                   CheckedConversionKind CCK) {
#ifndef NDEBUG
  if (VK == VK_PRValue && !E->isPRValue()) {
    switch (Kind) {
    default:
      llvm_unreachable(
          ("can't implicitly cast glvalue to prvalue with this cast "
           "kind: " +
           std::string(CastExpr::getCastKindName(Kind)))
              .c_str());
    case CK_Dependent:
    case CK_LValueToRValue:
    case CK_ArrayToPointerDecay:
    case CK_FunctionToPointerDecay:
    case CK_ToVoid:
    case CK_NonAtomicToAtomic:
    case CK_HLSLArrayRValue:
    case CK_HLSLAggregateSplatCast:
      break;
    }
  }
  assert((VK == VK_PRValue || Kind == CK_Dependent || !E->isPRValue()) &&
         "can't cast prvalue to glvalue");
#endif

  diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc());
  diagnoseZeroToNullptrConversion(Kind, E);
  if (Context.hasAnyFunctionEffects() && !isCast(CCK) &&
      Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer)
    diagnoseFunctionEffectConversion(Ty, E->getType(), E->getBeginLoc());

  QualType ExprTy = Context.getCanonicalType(E->getType());
  QualType TypeTy = Context.getCanonicalType(Ty);

  // This cast is used in place of a regular LValue to RValue cast for
  // HLSL Array Parameter Types. It needs to be emitted even if
  // ExprTy == TypeTy, except if E is an HLSLOutArgExpr
  // Emitting a cast in that case will prevent HLSLOutArgExpr from
  // being handled properly in EmitCallArg
  if (Kind == CK_HLSLArrayRValue && !isa<HLSLOutArgExpr>(E))
    return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK,
                                    CurFPFeatureOverrides());

  if (ExprTy == TypeTy)
    return E;

  if (Kind == CK_ArrayToPointerDecay) {
    // C++1z [conv.array]: The temporary materialization conversion is applied.
    // We also use this to fuel C++ DR1213, which applies to C++11 onwards.
    if (getLangOpts().CPlusPlus && E->isPRValue()) {
      // The temporary is an lvalue in C++98 and an xvalue otherwise.
      ExprResult Materialized = CreateMaterializeTemporaryExpr(
          E->getType(), E, !getLangOpts().CPlusPlus11);
      if (Materialized.isInvalid())
        return ExprError();
      E = Materialized.get();
    }
    // C17 6.7.1p6 footnote 124: The implementation can treat any register
    // declaration simply as an auto declaration. However, whether or not
    // addressable storage is actually used, the address of any part of an
    // object declared with storage-class specifier register cannot be
    // computed, either explicitly(by use of the unary & operator as discussed
    // in 6.5.3.2) or implicitly(by converting an array name to a pointer as
    // discussed in 6.3.2.1).Thus, the only operator that can be applied to an
    // array declared with storage-class specifier register is sizeof.
    if (VK == VK_PRValue && !getLangOpts().CPlusPlus && !E->isPRValue()) {
      if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
        if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
          if (VD->getStorageClass() == SC_Register) {
            Diag(E->getExprLoc(), diag::err_typecheck_address_of)
                << /*register variable*/ 3 << E->getSourceRange();
            return ExprError();
          }
        }
      }
    }
  }

  if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
    if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
      ImpCast->setType(Ty);
      ImpCast->setValueKind(VK);
      return E;
    }
  }

  return ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK,
                                  CurFPFeatureOverrides());
}

CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
  switch (ScalarTy->getScalarTypeKind()) {
  case Type::STK_Bool: return CK_NoOp;
  case Type::STK_CPointer: return CK_PointerToBoolean;
  case Type::STK_BlockPointer: return CK_PointerToBoolean;
  case Type::STK_ObjCObjectPointer: return CK_PointerToBoolean;
  case Type::STK_MemberPointer: return CK_MemberPointerToBoolean;
  case Type::STK_Integral: return CK_IntegralToBoolean;
  case Type::STK_Floating: return CK_FloatingToBoolean;
  case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
  case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
  case Type::STK_FixedPoint: return CK_FixedPointToBoolean;
  }
  llvm_unreachable("unknown scalar type kind");
}

/// Used to prune the decls of Sema's UnusedFileScopedDecls vector.
static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
  if (D->getMostRecentDecl()->isUsed())
    return true;

  if (D->isExternallyVisible())
    return true;

  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
    // If this is a function template and none of its specializations is used,
    // we should warn.
    if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate())
      for (const auto *Spec : Template->specializations())
        if (ShouldRemoveFromUnused(SemaRef, Spec))
          return true;

    // UnusedFileScopedDecls stores the first declaration.
    // The declaration may have become definition so check again.
    const FunctionDecl *DeclToCheck;
    if (FD->hasBody(DeclToCheck))
      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);

    // Later redecls may add new information resulting in not having to warn,
    // so check again.
    DeclToCheck = FD->getMostRecentDecl();
    if (DeclToCheck != FD)
      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
  }

  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
    // If a variable usable in constant expressions is referenced,
    // don't warn if it isn't used: if the value of a variable is required
    // for the computation of a constant expression, it doesn't make sense to
    // warn even if the variable isn't odr-used.  (isReferenced doesn't
    // precisely reflect that, but it's a decent approximation.)
    if (VD->isReferenced() &&
        VD->mightBeUsableInConstantExpressions(SemaRef->Context))
      return true;

    if (VarTemplateDecl *Template = VD->getDescribedVarTemplate())
      // If this is a variable template and none of its specializations is used,
      // we should warn.
      for (const auto *Spec : Template->specializations())
        if (ShouldRemoveFromUnused(SemaRef, Spec))
          return true;

    // UnusedFileScopedDecls stores the first declaration.
    // The declaration may have become definition so check again.
    const VarDecl *DeclToCheck = VD->getDefinition();
    if (DeclToCheck)
      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);

    // Later redecls may add new information resulting in not having to warn,
    // so check again.
    DeclToCheck = VD->getMostRecentDecl();
    if (DeclToCheck != VD)
      return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck);
  }

  return false;
}

static bool isFunctionOrVarDeclExternC(const NamedDecl *ND) {
  if (const auto *FD = dyn_cast<FunctionDecl>(ND))
    return FD->isExternC();
  return cast<VarDecl>(ND)->isExternC();
}

/// Determine whether ND is an external-linkage function or variable whose
/// type has no linkage.
bool Sema::isExternalWithNoLinkageType(const ValueDecl *VD) const {
  // Note: it's not quite enough to check whether VD has UniqueExternalLinkage,
  // because we also want to catch the case where its type has VisibleNoLinkage,
  // which does not affect the linkage of VD.
  return getLangOpts().CPlusPlus && VD->hasExternalFormalLinkage() &&
         !isExternalFormalLinkage(VD->getType()->getLinkage()) &&
         !isFunctionOrVarDeclExternC(VD);
}

/// Obtains a sorted list of functions and variables that are undefined but
/// ODR-used.
void Sema::getUndefinedButUsed(
    SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
  for (const auto &UndefinedUse : UndefinedButUsed) {
    NamedDecl *ND = UndefinedUse.first;

    // Ignore attributes that have become invalid.
    if (ND->isInvalidDecl()) continue;

    // __attribute__((weakref)) is basically a definition.
    if (ND->hasAttr<WeakRefAttr>()) continue;

    if (isa<CXXDeductionGuideDecl>(ND))
      continue;

    if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
      // An exported function will always be emitted when defined, so even if
      // the function is inline, it doesn't have to be emitted in this TU. An
      // imported function implies that it has been exported somewhere else.
      continue;
    }

    if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
      if (FD->isDefined())
        continue;
      if (FD->isExternallyVisible() &&
          !isExternalWithNoLinkageType(FD) &&
          !FD->getMostRecentDecl()->isInlined() &&
          !FD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
        continue;
      if (FD->getBuiltinID())
        continue;
    } else {
      const auto *VD = cast<VarDecl>(ND);
      if (VD->hasDefinition() != VarDecl::DeclarationOnly)
        continue;
      if (VD->isExternallyVisible() &&
          !isExternalWithNoLinkageType(VD) &&
          !VD->getMostRecentDecl()->isInline() &&
          !VD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
        continue;

      // Skip VarDecls that lack formal definitions but which we know are in
      // fact defined somewhere.
      if (VD->isKnownToBeDefined())
        continue;
    }

    Undefined.push_back(std::make_pair(ND, UndefinedUse.second));
  }
}

/// checkUndefinedButUsed - Check for undefined objects with internal linkage
/// or that are inline.
static void checkUndefinedButUsed(Sema &S) {
  if (S.UndefinedButUsed.empty()) return;

  // Collect all the still-undefined entities with internal linkage.
  SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
  S.getUndefinedButUsed(Undefined);
  S.UndefinedButUsed.clear();
  if (Undefined.empty()) return;

  for (const auto &Undef : Undefined) {
    ValueDecl *VD = cast<ValueDecl>(Undef.first);
    SourceLocation UseLoc = Undef.second;

    if (S.isExternalWithNoLinkageType(VD)) {
      // C++ [basic.link]p8:
      //   A type without linkage shall not be used as the type of a variable
      //   or function with external linkage unless
      //    -- the entity has C language linkage
      //    -- the entity is not odr-used or is defined in the same TU
      //
      // As an extension, accept this in cases where the type is externally
      // visible, since the function or variable actually can be defined in
      // another translation unit in that case.
      S.Diag(VD->getLocation(), isExternallyVisible(VD->getType()->getLinkage())
                                    ? diag::ext_undefined_internal_type
                                    : diag::err_undefined_internal_type)
        << isa<VarDecl>(VD) << VD;
    } else if (!VD->isExternallyVisible()) {
      // FIXME: We can promote this to an error. The function or variable can't
      // be defined anywhere else, so the program must necessarily violate the
      // one definition rule.
      bool IsImplicitBase = false;
      if (const auto *BaseD = dyn_cast<FunctionDecl>(VD)) {
        auto *DVAttr = BaseD->getAttr<OMPDeclareVariantAttr>();
        if (DVAttr && !DVAttr->getTraitInfo().isExtensionActive(
                          llvm::omp::TraitProperty::
                              implementation_extension_disable_implicit_base)) {
          const auto *Func = cast<FunctionDecl>(
              cast<DeclRefExpr>(DVAttr->getVariantFuncRef())->getDecl());
          IsImplicitBase = BaseD->isImplicit() &&
                           Func->getIdentifier()->isMangledOpenMPVariantName();
        }
      }
      if (!S.getLangOpts().OpenMP || !IsImplicitBase)
        S.Diag(VD->getLocation(), diag::warn_undefined_internal)
            << isa<VarDecl>(VD) << VD;
    } else if (auto *FD = dyn_cast<FunctionDecl>(VD)) {
      (void)FD;
      assert(FD->getMostRecentDecl()->isInlined() &&
             "used object requires definition but isn't inline or internal?");
      // FIXME: This is ill-formed; we should reject.
      S.Diag(VD->getLocation(), diag::warn_undefined_inline) << VD;
    } else {
      assert(cast<VarDecl>(VD)->getMostRecentDecl()->isInline() &&
             "used var requires definition but isn't inline or internal?");
      S.Diag(VD->getLocation(), diag::err_undefined_inline_var) << VD;
    }
    if (UseLoc.isValid())
      S.Diag(UseLoc, diag::note_used_here);
  }
}

void Sema::LoadExternalWeakUndeclaredIdentifiers() {
  if (!ExternalSource)
    return;

  SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs;
  ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs);
  for (auto &WeakID : WeakIDs)
    (void)WeakUndeclaredIdentifiers[WeakID.first].insert(WeakID.second);
}


typedef llvm::DenseMap<const CXXRecordDecl*, bool> RecordCompleteMap;

/// Returns true, if all methods and nested classes of the given
/// CXXRecordDecl are defined in this translation unit.
///
/// Should only be called from ActOnEndOfTranslationUnit so that all
/// definitions are actually read.
static bool MethodsAndNestedClassesComplete(const CXXRecordDecl *RD,
                                            RecordCompleteMap &MNCComplete) {
  RecordCompleteMap::iterator Cache = MNCComplete.find(RD);
  if (Cache != MNCComplete.end())
    return Cache->second;
  if (!RD->isCompleteDefinition())
    return false;
  bool Complete = true;
  for (DeclContext::decl_iterator I = RD->decls_begin(),
                                  E = RD->decls_end();
       I != E && Complete; ++I) {
    if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I))
      Complete = M->isDefined() || M->isDefaulted() ||
                 (M->isPureVirtual() && !isa<CXXDestructorDecl>(M));
    else if (const FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(*I))
      // If the template function is marked as late template parsed at this
      // point, it has not been instantiated and therefore we have not
      // performed semantic analysis on it yet, so we cannot know if the type
      // can be considered complete.
      Complete = !F->getTemplatedDecl()->isLateTemplateParsed() &&
                  F->getTemplatedDecl()->isDefined();
    else if (const CXXRecordDecl *R = dyn_cast<CXXRecordDecl>(*I)) {
      if (R->isInjectedClassName())
        continue;
      if (R->hasDefinition())
        Complete = MethodsAndNestedClassesComplete(R->getDefinition(),
                                                   MNCComplete);
      else
        Complete = false;
    }
  }
  MNCComplete[RD] = Complete;
  return Complete;
}

/// Returns true, if the given CXXRecordDecl is fully defined in this
/// translation unit, i.e. all methods are defined or pure virtual and all
/// friends, friend functions and nested classes are fully defined in this
/// translation unit.
///
/// Should only be called from ActOnEndOfTranslationUnit so that all
/// definitions are actually read.
static bool IsRecordFullyDefined(const CXXRecordDecl *RD,
                                 RecordCompleteMap &RecordsComplete,
                                 RecordCompleteMap &MNCComplete) {
  RecordCompleteMap::iterator Cache = RecordsComplete.find(RD);
  if (Cache != RecordsComplete.end())
    return Cache->second;
  bool Complete = MethodsAndNestedClassesComplete(RD, MNCComplete);
  for (CXXRecordDecl::friend_iterator I = RD->friend_begin(),
                                      E = RD->friend_end();
       I != E && Complete; ++I) {
    // Check if friend classes and methods are complete.
    if (TypeSourceInfo *TSI = (*I)->getFriendType()) {
      // Friend classes are available as the TypeSourceInfo of the FriendDecl.
      if (CXXRecordDecl *FriendD = TSI->getType()->getAsCXXRecordDecl())
        Complete = MethodsAndNestedClassesComplete(FriendD, MNCComplete);
      else
        Complete = false;
    } else {
      // Friend functions are available through the NamedDecl of FriendDecl.
      if (const FunctionDecl *FD =
          dyn_cast<FunctionDecl>((*I)->getFriendDecl()))
        Complete = FD->isDefined();
      else
        // This is a template friend, give up.
        Complete = false;
    }
  }
  RecordsComplete[RD] = Complete;
  return Complete;
}

void Sema::emitAndClearUnusedLocalTypedefWarnings() {
  if (ExternalSource)
    ExternalSource->ReadUnusedLocalTypedefNameCandidates(
        UnusedLocalTypedefNameCandidates);
  for (const TypedefNameDecl *TD : UnusedLocalTypedefNameCandidates) {
    if (TD->isReferenced())
      continue;
    Diag(TD->getLocation(), diag::warn_unused_local_typedef)
        << isa<TypeAliasDecl>(TD) << TD->getDeclName();
  }
  UnusedLocalTypedefNameCandidates.clear();
}

void Sema::ActOnStartOfTranslationUnit() {
  if (getLangOpts().CPlusPlusModules &&
      getLangOpts().getCompilingModule() == LangOptions::CMK_HeaderUnit)
    HandleStartOfHeaderUnit();
}

void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) {
  if (Kind == TUFragmentKind::Global) {
    // Perform Pending Instantiations at the end of global module fragment so
    // that the module ownership of TU-level decls won't get messed.
    llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
    PerformPendingInstantiations();
    return;
  }

  // Transfer late parsed template instantiations over to the pending template
  // instantiation list. During normal compilation, the late template parser
  // will be installed and instantiating these templates will succeed.
  //
  // If we are building a TU prefix for serialization, it is also safe to
  // transfer these over, even though they are not parsed. The end of the TU
  // should be outside of any eager template instantiation scope, so when this
  // AST is deserialized, these templates will not be parsed until the end of
  // the combined TU.
  PendingInstantiations.insert(PendingInstantiations.end(),
                               LateParsedInstantiations.begin(),
                               LateParsedInstantiations.end());
  LateParsedInstantiations.clear();

  // If DefinedUsedVTables ends up marking any virtual member functions it
  // might lead to more pending template instantiations, which we then need
  // to instantiate.
  DefineUsedVTables();

  // C++: Perform implicit template instantiations.
  //
  // FIXME: When we perform these implicit instantiations, we do not
  // carefully keep track of the point of instantiation (C++ [temp.point]).
  // This means that name lookup that occurs within the template
  // instantiation will always happen at the end of the translation unit,
  // so it will find some names that are not required to be found. This is
  // valid, but we could do better by diagnosing if an instantiation uses a
  // name that was not visible at its first point of instantiation.
  if (ExternalSource) {
    // Load pending instantiations from the external source.
    SmallVector<PendingImplicitInstantiation, 4> Pending;
    ExternalSource->ReadPendingInstantiations(Pending);
    for (auto PII : Pending)
      if (auto Func = dyn_cast<FunctionDecl>(PII.first))
        Func->setInstantiationIsPending(true);
    PendingInstantiations.insert(PendingInstantiations.begin(),
                                 Pending.begin(), Pending.end());
  }

  {
    llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
    PerformPendingInstantiations();
  }

  emitDeferredDiags();

  assert(LateParsedInstantiations.empty() &&
         "end of TU template instantiation should not create more "
         "late-parsed templates");
}

void Sema::ActOnEndOfTranslationUnit() {
  assert(DelayedDiagnostics.getCurrentPool() == nullptr
         && "reached end of translation unit with a pool attached?");

  // If code completion is enabled, don't perform any end-of-translation-unit
  // work.
  if (PP.isCodeCompletionEnabled())
    return;

  // Complete translation units and modules define vtables and perform implicit
  // instantiations. PCH files do not.
  if (TUKind != TU_Prefix) {
    ObjC().DiagnoseUseOfUnimplementedSelectors();

    ActOnEndOfTranslationUnitFragment(
        !ModuleScopes.empty() && ModuleScopes.back().Module->Kind ==
                                     Module::PrivateModuleFragment
            ? TUFragmentKind::Private
            : TUFragmentKind::Normal);

    if (LateTemplateParserCleanup)
      LateTemplateParserCleanup(OpaqueParser);

    CheckDelayedMemberExceptionSpecs();
  } else {
    // If we are building a TU prefix for serialization, it is safe to transfer
    // these over, even though they are not parsed. The end of the TU should be
    // outside of any eager template instantiation scope, so when this AST is
    // deserialized, these templates will not be parsed until the end of the
    // combined TU.
    PendingInstantiations.insert(PendingInstantiations.end(),
                                 LateParsedInstantiations.begin(),
                                 LateParsedInstantiations.end());
    LateParsedInstantiations.clear();

    if (LangOpts.PCHInstantiateTemplates) {
      llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
      PerformPendingInstantiations();
    }
  }

  DiagnoseUnterminatedPragmaAlignPack();
  DiagnoseUnterminatedPragmaAttribute();
  OpenMP().DiagnoseUnterminatedOpenMPDeclareTarget();
  DiagnosePrecisionLossInComplexDivision();

  // All delayed member exception specs should be checked or we end up accepting
  // incompatible declarations.
  assert(DelayedOverridingExceptionSpecChecks.empty());
  assert(DelayedEquivalentExceptionSpecChecks.empty());

  // All dllexport classes should have been processed already.
  assert(DelayedDllExportClasses.empty());
  assert(DelayedDllExportMemberFunctions.empty());

  // Remove file scoped decls that turned out to be used.
  UnusedFileScopedDecls.erase(
      std::remove_if(UnusedFileScopedDecls.begin(nullptr, true),
                     UnusedFileScopedDecls.end(),
                     [this](const DeclaratorDecl *DD) {
                       return ShouldRemoveFromUnused(this, DD);
                     }),
      UnusedFileScopedDecls.end());

  if (TUKind == TU_Prefix) {
    // Translation unit prefixes don't need any of the checking below.
    if (!PP.isIncrementalProcessingEnabled())
      TUScope = nullptr;
    return;
  }

  // Check for #pragma weak identifiers that were never declared
  LoadExternalWeakUndeclaredIdentifiers();
  for (const auto &WeakIDs : WeakUndeclaredIdentifiers) {
    if (WeakIDs.second.empty())
      continue;

    Decl *PrevDecl = LookupSingleName(TUScope, WeakIDs.first, SourceLocation(),
                                      LookupOrdinaryName);
    if (PrevDecl != nullptr &&
        !(isa<FunctionDecl>(PrevDecl) || isa<VarDecl>(PrevDecl)))
      for (const auto &WI : WeakIDs.second)
        Diag(WI.getLocation(), diag::warn_attribute_wrong_decl_type)
            << "'weak'" << /*isRegularKeyword=*/0 << ExpectedVariableOrFunction;
    else
      for (const auto &WI : WeakIDs.second)
        Diag(WI.getLocation(), diag::warn_weak_identifier_undeclared)
            << WeakIDs.first;
  }

  if (LangOpts.CPlusPlus11 &&
      !Diags.isIgnored(diag::warn_delegating_ctor_cycle, SourceLocation()))
    CheckDelegatingCtorCycles();

  if (!Diags.hasErrorOccurred()) {
    if (ExternalSource)
      ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
    checkUndefinedButUsed(*this);
  }

  // A global-module-fragment is only permitted within a module unit.
  if (!ModuleScopes.empty() && ModuleScopes.back().Module->Kind ==
                                   Module::ExplicitGlobalModuleFragment) {
    Diag(ModuleScopes.back().BeginLoc,
         diag::err_module_declaration_missing_after_global_module_introducer);
  } else if (getLangOpts().getCompilingModule() ==
                 LangOptions::CMK_ModuleInterface &&
             // We can't use ModuleScopes here since ModuleScopes is always
             // empty if we're compiling the BMI.
             !getASTContext().getCurrentNamedModule()) {
    // If we are building a module interface unit, we should have seen the
    // module declaration.
    //
    // FIXME: Make a better guess as to where to put the module declaration.
    Diag(getSourceManager().getLocForStartOfFile(
             getSourceManager().getMainFileID()),
         diag::err_module_declaration_missing);
  }

  // Now we can decide whether the modules we're building need an initializer.
  if (Module *CurrentModule = getCurrentModule();
      CurrentModule && CurrentModule->isInterfaceOrPartition()) {
    auto DoesModNeedInit = [this](Module *M) {
      if (!getASTContext().getModuleInitializers(M).empty())
        return true;
      for (auto [Exported, _] : M->Exports)
        if (Exported->isNamedModuleInterfaceHasInit())
          return true;
      for (Module *I : M->Imports)
        if (I->isNamedModuleInterfaceHasInit())
          return true;

      return false;
    };

    CurrentModule->NamedModuleHasInit =
        DoesModNeedInit(CurrentModule) ||
        llvm::any_of(CurrentModule->submodules(), DoesModNeedInit);
  }

  if (TUKind == TU_ClangModule) {
    // If we are building a module, resolve all of the exported declarations
    // now.
    if (Module *CurrentModule = PP.getCurrentModule()) {
      ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();

      SmallVector<Module *, 2> Stack;
      Stack.push_back(CurrentModule);
      while (!Stack.empty()) {
        Module *Mod = Stack.pop_back_val();

        // Resolve the exported declarations and conflicts.
        // FIXME: Actually complain, once we figure out how to teach the
        // diagnostic client to deal with complaints in the module map at this
        // point.
        ModMap.resolveExports(Mod, /*Complain=*/false);
        ModMap.resolveUses(Mod, /*Complain=*/false);
        ModMap.resolveConflicts(Mod, /*Complain=*/false);

        // Queue the submodules, so their exports will also be resolved.
        auto SubmodulesRange = Mod->submodules();
        Stack.append(SubmodulesRange.begin(), SubmodulesRange.end());
      }
    }

    // Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for
    // modules when they are built, not every time they are used.
    emitAndClearUnusedLocalTypedefWarnings();
  }

  // C++ standard modules. Diagnose cases where a function is declared inline
  // in the module purview but has no definition before the end of the TU or
  // the start of a Private Module Fragment (if one is present).
  if (!PendingInlineFuncDecls.empty()) {
    for (auto *D : PendingInlineFuncDecls) {
      if (auto *FD = dyn_cast<FunctionDecl>(D)) {
        bool DefInPMF = false;
        if (auto *FDD = FD->getDefinition()) {
          DefInPMF = FDD->getOwningModule()->isPrivateModule();
          if (!DefInPMF)
            continue;
        }
        Diag(FD->getLocation(), diag::err_export_inline_not_defined)
            << DefInPMF;
        // If we have a PMF it should be at the end of the ModuleScopes.
        if (DefInPMF &&
            ModuleScopes.back().Module->Kind == Module::PrivateModuleFragment) {
          Diag(ModuleScopes.back().BeginLoc,
               diag::note_private_module_fragment);
        }
      }
    }
    PendingInlineFuncDecls.clear();
  }

  // C99 6.9.2p2:
  //   A declaration of an identifier for an object that has file
  //   scope without an initializer, and without a storage-class
  //   specifier or with the storage-class specifier static,
  //   constitutes a tentative definition. If a translation unit
  //   contains one or more tentative definitions for an identifier,
  //   and the translation unit contains no external definition for
  //   that identifier, then the behavior is exactly as if the
  //   translation unit contains a file scope declaration of that
  //   identifier, with the composite type as of the end of the
  //   translation unit, with an initializer equal to 0.
  llvm::SmallPtrSet<VarDecl *, 32> Seen;
  for (TentativeDefinitionsType::iterator
           T = TentativeDefinitions.begin(ExternalSource.get()),
           TEnd = TentativeDefinitions.end();
       T != TEnd; ++T) {
    VarDecl *VD = (*T)->getActingDefinition();

    // If the tentative definition was completed, getActingDefinition() returns
    // null. If we've already seen this variable before, insert()'s second
    // return value is false.
    if (!VD || VD->isInvalidDecl() || !Seen.insert(VD).second)
      continue;

    if (const IncompleteArrayType *ArrayT
        = Context.getAsIncompleteArrayType(VD->getType())) {
      // Set the length of the array to 1 (C99 6.9.2p5).
      Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
      llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
      QualType T = Context.getConstantArrayType(
          ArrayT->getElementType(), One, nullptr, ArraySizeModifier::Normal, 0);
      VD->setType(T);
    } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
                                   diag::err_tentative_def_incomplete_type))
      VD->setInvalidDecl();

    // No initialization is performed for a tentative definition.
    CheckCompleteVariableDeclaration(VD);

    // In C, if the definition is const-qualified and has no initializer, it
    // is left uninitialized unless it has static or thread storage duration.
    QualType Type = VD->getType();
    if (!VD->isInvalidDecl() && !getLangOpts().CPlusPlus &&
        Type.isConstQualified() && !VD->getAnyInitializer()) {
      unsigned DiagID = diag::warn_default_init_const_unsafe;
      if (VD->getStorageDuration() == SD_Static ||
          VD->getStorageDuration() == SD_Thread)
        DiagID = diag::warn_default_init_const;

      bool EmitCppCompat = !Diags.isIgnored(
          diag::warn_cxx_compat_hack_fake_diagnostic_do_not_emit,
          VD->getLocation());

      Diag(VD->getLocation(), DiagID) << Type << EmitCppCompat;
    }

    // Notify the consumer that we've completed a tentative definition.
    if (!VD->isInvalidDecl())
      Consumer.CompleteTentativeDefinition(VD);
  }

  for (auto *D : ExternalDeclarations) {
    if (!D || D->isInvalidDecl() || D->getPreviousDecl() || !D->isUsed())
      continue;

    Consumer.CompleteExternalDeclaration(D);
  }

  if (LangOpts.HLSL)
    HLSL().ActOnEndOfTranslationUnit(getASTContext().getTranslationUnitDecl());

  // If there were errors, disable 'unused' warnings since they will mostly be
  // noise. Don't warn for a use from a module: either we should warn on all
  // file-scope declarations in modules or not at all, but whether the
  // declaration is used is immaterial.
  if (!Diags.hasErrorOccurred() && TUKind != TU_ClangModule) {
    // Output warning for unused file scoped decls.
    for (UnusedFileScopedDeclsType::iterator
             I = UnusedFileScopedDecls.begin(ExternalSource.get()),
             E = UnusedFileScopedDecls.end();
         I != E; ++I) {
      if (ShouldRemoveFromUnused(this, *I))
        continue;

      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
        const FunctionDecl *DiagD;
        if (!FD->hasBody(DiagD))
          DiagD = FD;
        if (DiagD->isDeleted())
          continue; // Deleted functions are supposed to be unused.
        SourceRange DiagRange = DiagD->getLocation();
        if (const ASTTemplateArgumentListInfo *ASTTAL =
                DiagD->getTemplateSpecializationArgsAsWritten())
          DiagRange.setEnd(ASTTAL->RAngleLoc);
        if (DiagD->isReferenced()) {
          if (isa<CXXMethodDecl>(DiagD))
            Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
                << DiagD << DiagRange;
          else {
            if (FD->getStorageClass() == SC_Static &&
                !FD->isInlineSpecified() &&
                !SourceMgr.isInMainFile(
                   SourceMgr.getExpansionLoc(FD->getLocation())))
              Diag(DiagD->getLocation(),
                   diag::warn_unneeded_static_internal_decl)
                  << DiagD << DiagRange;
            else
              Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
                  << /*function=*/0 << DiagD << DiagRange;
          }
        } else if (!FD->isTargetMultiVersion() ||
                   FD->isTargetMultiVersionDefault()) {
          if (FD->getDescribedFunctionTemplate())
            Diag(DiagD->getLocation(), diag::warn_unused_template)
                << /*function=*/0 << DiagD << DiagRange;
          else
            Diag(DiagD->getLocation(), isa<CXXMethodDecl>(DiagD)
                                           ? diag::warn_unused_member_function
                                           : diag::warn_unused_function)
                << DiagD << DiagRange;
        }
      } else {
        const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
        if (!DiagD)
          DiagD = cast<VarDecl>(*I);
        SourceRange DiagRange = DiagD->getLocation();
        if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(DiagD)) {
          if (const ASTTemplateArgumentListInfo *ASTTAL =
                  VTSD->getTemplateArgsAsWritten())
            DiagRange.setEnd(ASTTAL->RAngleLoc);
        }
        if (DiagD->isReferenced()) {
          Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
              << /*variable=*/1 << DiagD << DiagRange;
        } else if (DiagD->getDescribedVarTemplate()) {
          Diag(DiagD->getLocation(), diag::warn_unused_template)
              << /*variable=*/1 << DiagD << DiagRange;
        } else if (DiagD->getType().isConstQualified()) {
          const SourceManager &SM = SourceMgr;
          if (SM.getMainFileID() != SM.getFileID(DiagD->getLocation()) ||
              !PP.getLangOpts().IsHeaderFile)
            Diag(DiagD->getLocation(), diag::warn_unused_const_variable)
                << DiagD << DiagRange;
        } else {
          Diag(DiagD->getLocation(), diag::warn_unused_variable)
              << DiagD << DiagRange;
        }
      }
    }

    emitAndClearUnusedLocalTypedefWarnings();
  }

  if (!Diags.isIgnored(diag::warn_unused_private_field, SourceLocation())) {
    // FIXME: Load additional unused private field candidates from the external
    // source.
    RecordCompleteMap RecordsComplete;
    RecordCompleteMap MNCComplete;
    for (const NamedDecl *D : UnusedPrivateFields) {
      const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext());
      if (RD && !RD->isUnion() &&
          IsRecordFullyDefined(RD, RecordsComplete, MNCComplete)) {
        Diag(D->getLocation(), diag::warn_unused_private_field)
              << D->getDeclName();
      }
    }
  }

  if (!Diags.isIgnored(diag::warn_mismatched_delete_new, SourceLocation())) {
    if (ExternalSource)
      ExternalSource->ReadMismatchingDeleteExpressions(DeleteExprs);
    for (const auto &DeletedFieldInfo : DeleteExprs) {
      for (const auto &DeleteExprLoc : DeletedFieldInfo.second) {
        AnalyzeDeleteExprMismatch(DeletedFieldInfo.first, DeleteExprLoc.first,
                                  DeleteExprLoc.second);
      }
    }
  }

  AnalysisWarnings.IssueWarnings(Context.getTranslationUnitDecl());

  if (Context.hasAnyFunctionEffects())
    performFunctionEffectAnalysis(Context.getTranslationUnitDecl());

  // Check we've noticed that we're no longer parsing the initializer for every
  // variable. If we miss cases, then at best we have a performance issue and
  // at worst a rejects-valid bug.
  assert(ParsingInitForAutoVars.empty() &&
         "Didn't unmark var as having its initializer parsed");

  if (!PP.isIncrementalProcessingEnabled())
    TUScope = nullptr;

  checkExposure(Context.getTranslationUnitDecl());
}


//===----------------------------------------------------------------------===//
// Helper functions.
//===----------------------------------------------------------------------===//

DeclContext *Sema::getFunctionLevelDeclContext(bool AllowLambda) const {
  DeclContext *DC = CurContext;

  while (true) {
    if (isa<BlockDecl>(DC) || isa<EnumDecl>(DC) || isa<CapturedDecl>(DC) ||
        isa<RequiresExprBodyDecl>(DC)) {
      DC = DC->getParent();
    } else if (!AllowLambda && isa<CXXMethodDecl>(DC) &&
               cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&
               cast<CXXRecordDecl>(DC->getParent())->isLambda()) {
      DC = DC->getParent()->getParent();
    } else break;
  }

  return DC;
}

/// getCurFunctionDecl - If inside of a function body, this returns a pointer
/// to the function decl for the function being parsed.  If we're currently
/// in a 'block', this returns the containing context.
FunctionDecl *Sema::getCurFunctionDecl(bool AllowLambda) const {
  DeclContext *DC = getFunctionLevelDeclContext(AllowLambda);
  return dyn_cast<FunctionDecl>(DC);
}

ObjCMethodDecl *Sema::getCurMethodDecl() {
  DeclContext *DC = getFunctionLevelDeclContext();
  while (isa<RecordDecl>(DC))
    DC = DC->getParent();
  return dyn_cast<ObjCMethodDecl>(DC);
}

NamedDecl *Sema::getCurFunctionOrMethodDecl() const {
  DeclContext *DC = getFunctionLevelDeclContext();
  if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC))
    return cast<NamedDecl>(DC);
  return nullptr;
}

LangAS Sema::getDefaultCXXMethodAddrSpace() const {
  if (getLangOpts().OpenCL)
    return getASTContext().getDefaultOpenCLPointeeAddrSpace();
  return LangAS::Default;
}

void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) {
  // FIXME: It doesn't make sense to me that DiagID is an incoming argument here
  // and yet we also use the current diag ID on the DiagnosticsEngine. This has
  // been made more painfully obvious by the refactor that introduced this
  // function, but it is possible that the incoming argument can be
  // eliminated. If it truly cannot be (for example, there is some reentrancy
  // issue I am not seeing yet), then there should at least be a clarifying
  // comment somewhere.
  Diagnostic DiagInfo(&Diags, DB);
  if (std::optional<TemplateDeductionInfo *> Info = isSFINAEContext()) {
    switch (DiagnosticIDs::getDiagnosticSFINAEResponse(DiagInfo.getID())) {
    case DiagnosticIDs::SFINAE_Report:
      // We'll report the diagnostic below.
      break;

    case DiagnosticIDs::SFINAE_SubstitutionFailure:
      // Count this failure so that we know that template argument deduction
      // has failed.
      ++NumSFINAEErrors;

      // Make a copy of this suppressed diagnostic and store it with the
      // template-deduction information.
      if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
        (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
                       PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
      }

      Diags.setLastDiagnosticIgnored(true);
      return;

    case DiagnosticIDs::SFINAE_AccessControl: {
      // Per C++ Core Issue 1170, access control is part of SFINAE.
      // Additionally, the AccessCheckingSFINAE flag can be used to temporarily
      // make access control a part of SFINAE for the purposes of checking
      // type traits.
      if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus11)
        break;

      SourceLocation Loc = DiagInfo.getLocation();

      // Suppress this diagnostic.
      ++NumSFINAEErrors;

      // Make a copy of this suppressed diagnostic and store it with the
      // template-deduction information.
      if (*Info && !(*Info)->hasSFINAEDiagnostic()) {
        (*Info)->addSFINAEDiagnostic(DiagInfo.getLocation(),
                       PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
      }

      Diags.setLastDiagnosticIgnored(true);

      // Now produce a C++98 compatibility warning.
      Diag(Loc, diag::warn_cxx98_compat_sfinae_access_control);

      // The last diagnostic which Sema produced was ignored. Suppress any
      // notes attached to it.
      Diags.setLastDiagnosticIgnored(true);
      return;
    }

    case DiagnosticIDs::SFINAE_Suppress:
      if (DiagnosticsEngine::Level Level = getDiagnostics().getDiagnosticLevel(
              DiagInfo.getID(), DiagInfo.getLocation());
          Level == DiagnosticsEngine::Ignored)
        return;
      // Make a copy of this suppressed diagnostic and store it with the
      // template-deduction information;
      if (*Info) {
        (*Info)->addSuppressedDiagnostic(
            DiagInfo.getLocation(),
            PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
        if (!Diags.getDiagnosticIDs()->isNote(DiagID))
          PrintContextStack([Info](SourceLocation Loc, PartialDiagnostic PD) {
            (*Info)->addSuppressedDiagnostic(Loc, std::move(PD));
          });
      }

      // Suppress this diagnostic.
      Diags.setLastDiagnosticIgnored(true);
      return;
    }
  }

  // Copy the diagnostic printing policy over the ASTContext printing policy.
  // TODO: Stop doing that.  See: https://reviews.llvm.org/D45093#1090292
  Context.setPrintingPolicy(getPrintingPolicy());

  // Emit the diagnostic.
  if (!Diags.EmitDiagnostic(DB))
    return;

  // If this is not a note, and we're in a template instantiation
  // that is different from the last template instantiation where
  // we emitted an error, print a template instantiation
  // backtrace.
  if (!Diags.getDiagnosticIDs()->isNote(DiagID))
    PrintContextStack();
}

bool Sema::hasUncompilableErrorOccurred() const {
  if (getDiagnostics().hasUncompilableErrorOccurred())
    return true;
  auto *FD = dyn_cast<FunctionDecl>(CurContext);
  if (!FD)
    return false;
  auto Loc = DeviceDeferredDiags.find(FD);
  if (Loc == DeviceDeferredDiags.end())
    return false;
  for (auto PDAt : Loc->second) {
    if (Diags.getDiagnosticIDs()->isDefaultMappingAsError(
            PDAt.second.getDiagID()))
      return true;
  }
  return false;
}

// Print notes showing how we can reach FD starting from an a priori
// known-callable function.
static void emitCallStackNotes(Sema &S, const FunctionDecl *FD) {
  auto FnIt = S.CUDA().DeviceKnownEmittedFns.find(FD);
  while (FnIt != S.CUDA().DeviceKnownEmittedFns.end()) {
    // Respect error limit.
    if (S.Diags.hasFatalErrorOccurred())
      return;
    DiagnosticBuilder Builder(
        S.Diags.Report(FnIt->second.Loc, diag::note_called_by));
    Builder << FnIt->second.FD;
    FnIt = S.CUDA().DeviceKnownEmittedFns.find(FnIt->second.FD);
  }
}

namespace {

/// Helper class that emits deferred diagnostic messages if an entity directly
/// or indirectly using the function that causes the deferred diagnostic
/// messages is known to be emitted.
///
/// During parsing of AST, certain diagnostic messages are recorded as deferred
/// diagnostics since it is unknown whether the functions containing such
/// diagnostics will be emitted. A list of potentially emitted functions and
/// variables that may potentially trigger emission of functions are also
/// recorded. DeferredDiagnosticsEmitter recursively visits used functions
/// by each function to emit deferred diagnostics.
///
/// During the visit, certain OpenMP directives or initializer of variables
/// with certain OpenMP attributes will cause subsequent visiting of any
/// functions enter a state which is called OpenMP device context in this
/// implementation. The state is exited when the directive or initializer is
/// exited. This state can change the emission states of subsequent uses
/// of functions.
///
/// Conceptually the functions or variables to be visited form a use graph
/// where the parent node uses the child node. At any point of the visit,
/// the tree nodes traversed from the tree root to the current node form a use
/// stack. The emission state of the current node depends on two factors:
///    1. the emission state of the root node
///    2. whether the current node is in OpenMP device context
/// If the function is decided to be emitted, its contained deferred diagnostics
/// are emitted, together with the information about the use stack.
///
class DeferredDiagnosticsEmitter
    : public UsedDeclVisitor<DeferredDiagnosticsEmitter> {
public:
  typedef UsedDeclVisitor<DeferredDiagnosticsEmitter> Inherited;

  // Whether the function is already in the current use-path.
  llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> InUsePath;

  // The current use-path.
  llvm::SmallVector<CanonicalDeclPtr<FunctionDecl>, 4> UsePath;

  // Whether the visiting of the function has been done. Done[0] is for the
  // case not in OpenMP device context. Done[1] is for the case in OpenMP
  // device context. We need two sets because diagnostics emission may be
  // different depending on whether it is in OpenMP device context.
  llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> DoneMap[2];

  // Emission state of the root node of the current use graph.
  bool ShouldEmitRootNode;

  // Current OpenMP device context level. It is initialized to 0 and each
  // entering of device context increases it by 1 and each exit decreases
  // it by 1. Non-zero value indicates it is currently in device context.
  unsigned InOMPDeviceContext;

  DeferredDiagnosticsEmitter(Sema &S)
      : Inherited(S), ShouldEmitRootNode(false), InOMPDeviceContext(0) {}

  bool shouldVisitDiscardedStmt() const { return false; }

  void VisitOMPTargetDirective(OMPTargetDirective *Node) {
    ++InOMPDeviceContext;
    Inherited::VisitOMPTargetDirective(Node);
    --InOMPDeviceContext;
  }

  void visitUsedDecl(SourceLocation Loc, Decl *D) {
    if (isa<VarDecl>(D))
      return;
    if (auto *FD = dyn_cast<FunctionDecl>(D))
      checkFunc(Loc, FD);
    else
      Inherited::visitUsedDecl(Loc, D);
  }

  // Visitor member and parent dtors called by this dtor.
  void VisitCalledDestructors(CXXDestructorDecl *DD) {
    const CXXRecordDecl *RD = DD->getParent();

    // Visit the dtors of all members
    for (const FieldDecl *FD : RD->fields()) {
      QualType FT = FD->getType();
      if (const auto *ClassDecl = FT->getAsCXXRecordDecl();
          ClassDecl &&
          (ClassDecl->isBeingDefined() || ClassDecl->isCompleteDefinition()))
        if (CXXDestructorDecl *MemberDtor = ClassDecl->getDestructor())
          asImpl().visitUsedDecl(MemberDtor->getLocation(), MemberDtor);
    }

    // Also visit base class dtors
    for (const auto &Base : RD->bases()) {
      QualType BaseType = Base.getType();
      if (const auto *BaseDecl = BaseType->getAsCXXRecordDecl();
          BaseDecl &&
          (BaseDecl->isBeingDefined() || BaseDecl->isCompleteDefinition()))
        if (CXXDestructorDecl *BaseDtor = BaseDecl->getDestructor())
          asImpl().visitUsedDecl(BaseDtor->getLocation(), BaseDtor);
    }
  }

  void VisitDeclStmt(DeclStmt *DS) {
    // Visit dtors called by variables that need destruction
    for (auto *D : DS->decls())
      if (auto *VD = dyn_cast<VarDecl>(D))
        if (VD->isThisDeclarationADefinition() &&
            VD->needsDestruction(S.Context)) {
          QualType VT = VD->getType();
          if (const auto *ClassDecl = VT->getAsCXXRecordDecl();
              ClassDecl && (ClassDecl->isBeingDefined() ||
                            ClassDecl->isCompleteDefinition()))
            if (CXXDestructorDecl *Dtor = ClassDecl->getDestructor())
              asImpl().visitUsedDecl(Dtor->getLocation(), Dtor);
        }

    Inherited::VisitDeclStmt(DS);
  }
  void checkVar(VarDecl *VD) {
    assert(VD->isFileVarDecl() &&
           "Should only check file-scope variables");
    if (auto *Init = VD->getInit()) {
      auto DevTy = OMPDeclareTargetDeclAttr::getDeviceType(VD);
      bool IsDev = DevTy && (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost ||
                             *DevTy == OMPDeclareTargetDeclAttr::DT_Any);
      if (IsDev)
        ++InOMPDeviceContext;
      this->Visit(Init);
      if (IsDev)
        --InOMPDeviceContext;
    }
  }

  void checkFunc(SourceLocation Loc, FunctionDecl *FD) {
    auto &Done = DoneMap[InOMPDeviceContext > 0 ? 1 : 0];
    FunctionDecl *Caller = UsePath.empty() ? nullptr : UsePath.back();
    if ((!ShouldEmitRootNode && !S.getLangOpts().OpenMP && !Caller) ||
        S.shouldIgnoreInHostDeviceCheck(FD) || InUsePath.count(FD))
      return;
    // Finalize analysis of OpenMP-specific constructs.
    if (Caller && S.LangOpts.OpenMP && UsePath.size() == 1 &&
        (ShouldEmitRootNode || InOMPDeviceContext))
      S.OpenMP().finalizeOpenMPDelayedAnalysis(Caller, FD, Loc);
    if (Caller)
      S.CUDA().DeviceKnownEmittedFns[FD] = {Caller, Loc};
    // Always emit deferred diagnostics for the direct users. This does not
    // lead to explosion of diagnostics since each user is visited at most
    // twice.
    if (ShouldEmitRootNode || InOMPDeviceContext)
      emitDeferredDiags(FD, Caller);
    // Do not revisit a function if the function body has been completely
    // visited before.
    if (!Done.insert(FD).second)
      return;
    InUsePath.insert(FD);
    UsePath.push_back(FD);
    if (auto *S = FD->getBody()) {
      this->Visit(S);
    }
    if (CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(FD))
      asImpl().VisitCalledDestructors(Dtor);
    UsePath.pop_back();
    InUsePath.erase(FD);
  }

  void checkRecordedDecl(Decl *D) {
    if (auto *FD = dyn_cast<FunctionDecl>(D)) {
      ShouldEmitRootNode = S.getEmissionStatus(FD, /*Final=*/true) ==
                           Sema::FunctionEmissionStatus::Emitted;
      checkFunc(SourceLocation(), FD);
    } else
      checkVar(cast<VarDecl>(D));
  }

  // Emit any deferred diagnostics for FD
  void emitDeferredDiags(FunctionDecl *FD, bool ShowCallStack) {
    auto It = S.DeviceDeferredDiags.find(FD);
    if (It == S.DeviceDeferredDiags.end())
      return;
    bool HasWarningOrError = false;
    bool FirstDiag = true;
    for (PartialDiagnosticAt &PDAt : It->second) {
      // Respect error limit.
      if (S.Diags.hasFatalErrorOccurred())
        return;
      const SourceLocation &Loc = PDAt.first;
      const PartialDiagnostic &PD = PDAt.second;
      HasWarningOrError |=
          S.getDiagnostics().getDiagnosticLevel(PD.getDiagID(), Loc) >=
          DiagnosticsEngine::Warning;
      {
        DiagnosticBuilder Builder(S.Diags.Report(Loc, PD.getDiagID()));
        PD.Emit(Builder);
      }
      // Emit the note on the first diagnostic in case too many diagnostics
      // cause the note not emitted.
      if (FirstDiag && HasWarningOrError && ShowCallStack) {
        emitCallStackNotes(S, FD);
        FirstDiag = false;
      }
    }
  }
};
} // namespace

void Sema::emitDeferredDiags() {
  if (ExternalSource)
    ExternalSource->ReadDeclsToCheckForDeferredDiags(
        DeclsToCheckForDeferredDiags);

  if ((DeviceDeferredDiags.empty() && !LangOpts.OpenMP) ||
      DeclsToCheckForDeferredDiags.empty())
    return;

  DeferredDiagnosticsEmitter DDE(*this);
  for (auto *D : DeclsToCheckForDeferredDiags)
    DDE.checkRecordedDecl(D);
}

// In CUDA, there are some constructs which may appear in semantically-valid
// code, but trigger errors if we ever generate code for the function in which
// they appear.  Essentially every construct you're not allowed to use on the
// device falls into this category, because you are allowed to use these
// constructs in a __host__ __device__ function, but only if that function is
// never codegen'ed on the device.
//
// To handle semantic checking for these constructs, we keep track of the set of
// functions we know will be emitted, either because we could tell a priori that
// they would be emitted, or because they were transitively called by a
// known-emitted function.
//
// We also keep a partial call graph of which not-known-emitted functions call
// which other not-known-emitted functions.
//
// When we see something which is illegal if the current function is emitted
// (usually by way of DiagIfDeviceCode, DiagIfHostCode, or
// CheckCall), we first check if the current function is known-emitted.  If
// so, we immediately output the diagnostic.
//
// Otherwise, we "defer" the diagnostic.  It sits in Sema::DeviceDeferredDiags
// until we discover that the function is known-emitted, at which point we take
// it out of this map and emit the diagnostic.

Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(Kind K, SourceLocation Loc,
                                                   unsigned DiagID,
                                                   const FunctionDecl *Fn,
                                                   Sema &S)
    : S(S), Loc(Loc), DiagID(DiagID), Fn(Fn),
      ShowCallStack(K == K_ImmediateWithCallStack || K == K_Deferred) {
  switch (K) {
  case K_Nop:
    break;
  case K_Immediate:
  case K_ImmediateWithCallStack:
    ImmediateDiag.emplace(
        ImmediateDiagBuilder(S.Diags.Report(Loc, DiagID), S, DiagID));
    break;
  case K_Deferred:
    assert(Fn && "Must have a function to attach the deferred diag to.");
    auto &Diags = S.DeviceDeferredDiags[Fn];
    PartialDiagId.emplace(Diags.size());
    Diags.emplace_back(Loc, S.PDiag(DiagID));
    break;
  }
}

Sema::SemaDiagnosticBuilder::SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D)
    : S(D.S), Loc(D.Loc), DiagID(D.DiagID), Fn(D.Fn),
      ShowCallStack(D.ShowCallStack), ImmediateDiag(D.ImmediateDiag),
      PartialDiagId(D.PartialDiagId) {
  // Clean the previous diagnostics.
  D.ShowCallStack = false;
  D.ImmediateDiag.reset();
  D.PartialDiagId.reset();
}

Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
  if (ImmediateDiag) {
    // Emit our diagnostic and, if it was a warning or error, output a callstack
    // if Fn isn't a priori known-emitted.
    ImmediateDiag.reset(); // Emit the immediate diag.

    if (ShowCallStack) {
      bool IsWarningOrError = S.getDiagnostics().getDiagnosticLevel(
                                  DiagID, Loc) >= DiagnosticsEngine::Warning;
      if (IsWarningOrError)
        emitCallStackNotes(S, Fn);
    }
  } else {
    assert((!PartialDiagId || ShowCallStack) &&
           "Must always show call stack for deferred diags.");
  }
}

Sema::SemaDiagnosticBuilder
Sema::targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD) {
  FD = FD ? FD : getCurFunctionDecl();
  if (LangOpts.OpenMP)
    return LangOpts.OpenMPIsTargetDevice
               ? OpenMP().diagIfOpenMPDeviceCode(Loc, DiagID, FD)
               : OpenMP().diagIfOpenMPHostCode(Loc, DiagID, FD);
  if (getLangOpts().CUDA)
    return getLangOpts().CUDAIsDevice ? CUDA().DiagIfDeviceCode(Loc, DiagID)
                                      : CUDA().DiagIfHostCode(Loc, DiagID);

  if (getLangOpts().SYCLIsDevice)
    return SYCL().DiagIfDeviceCode(Loc, DiagID);

  return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID,
                               FD, *this);
}

void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) {
  if (isUnevaluatedContext() || Ty.isNull())
    return;

  // The original idea behind checkTypeSupport function is that unused
  // declarations can be replaced with an array of bytes of the same size during
  // codegen, such replacement doesn't seem to be possible for types without
  // constant byte size like zero length arrays. So, do a deep check for SYCL.
  if (D && LangOpts.SYCLIsDevice) {
    llvm::DenseSet<QualType> Visited;
    SYCL().deepTypeCheckForDevice(Loc, Visited, D);
  }

  Decl *C = cast<Decl>(getCurLexicalContext());

  // Memcpy operations for structs containing a member with unsupported type
  // are ok, though.
  if (const auto *MD = dyn_cast<CXXMethodDecl>(C)) {
    if ((MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) &&
        MD->isTrivial())
      return;

    if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(MD))
      if (Ctor->isCopyOrMoveConstructor() && Ctor->isTrivial())
        return;
  }

  // Try to associate errors with the lexical context, if that is a function, or
  // the value declaration otherwise.
  const FunctionDecl *FD = isa<FunctionDecl>(C)
                               ? cast<FunctionDecl>(C)
                               : dyn_cast_or_null<FunctionDecl>(D);

  auto CheckDeviceType = [&](QualType Ty) {
    if (Ty->isDependentType())
      return;

    if (Ty->isBitIntType()) {
      if (!Context.getTargetInfo().hasBitIntType()) {
        PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
        if (D)
          PD << D;
        else
          PD << "expression";
        targetDiag(Loc, PD, FD)
            << false /*show bit size*/ << 0 /*bitsize*/ << false /*return*/
            << Ty << Context.getTargetInfo().getTriple().str();
      }
      return;
    }

    // Check if we are dealing with two 'long double' but with different
    // semantics.
    bool LongDoubleMismatched = false;
    if (Ty->isRealFloatingType() && Context.getTypeSize(Ty) == 128) {
      const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(Ty);
      if ((&Sem != &llvm::APFloat::PPCDoubleDouble() &&
           !Context.getTargetInfo().hasFloat128Type()) ||
          (&Sem == &llvm::APFloat::PPCDoubleDouble() &&
           !Context.getTargetInfo().hasIbm128Type()))
        LongDoubleMismatched = true;
    }

    if ((Ty->isFloat16Type() && !Context.getTargetInfo().hasFloat16Type()) ||
        (Ty->isFloat128Type() && !Context.getTargetInfo().hasFloat128Type()) ||
        (Ty->isIbm128Type() && !Context.getTargetInfo().hasIbm128Type()) ||
        (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 &&
         !Context.getTargetInfo().hasInt128Type()) ||
        (Ty->isBFloat16Type() && !Context.getTargetInfo().hasBFloat16Type() &&
         !LangOpts.CUDAIsDevice) ||
        LongDoubleMismatched) {
      PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
      if (D)
        PD << D;
      else
        PD << "expression";

      if (targetDiag(Loc, PD, FD)
          << true /*show bit size*/
          << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty
          << false /*return*/ << Context.getTargetInfo().getTriple().str()) {
        if (D)
          D->setInvalidDecl();
      }
      if (D)
        targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
    }
  };

  auto CheckType = [&](QualType Ty, bool IsRetTy = false) {
    if (LangOpts.SYCLIsDevice ||
        (LangOpts.OpenMP && LangOpts.OpenMPIsTargetDevice) ||
        LangOpts.CUDAIsDevice)
      CheckDeviceType(Ty);

    QualType UnqualTy = Ty.getCanonicalType().getUnqualifiedType();
    const TargetInfo &TI = Context.getTargetInfo();
    if (!TI.hasLongDoubleType() && UnqualTy == Context.LongDoubleTy) {
      PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
      if (D)
        PD << D;
      else
        PD << "expression";

      if (Diag(Loc, PD, FD)
          << false /*show bit size*/ << 0 << Ty << false /*return*/
          << TI.getTriple().str()) {
        if (D)
          D->setInvalidDecl();
      }
      if (D)
        targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
    }

    bool IsDouble = UnqualTy == Context.DoubleTy;
    bool IsFloat = UnqualTy == Context.FloatTy;
    if (IsRetTy && !TI.hasFPReturn() && (IsDouble || IsFloat)) {
      PartialDiagnostic PD = PDiag(diag::err_target_unsupported_type);
      if (D)
        PD << D;
      else
        PD << "expression";

      if (Diag(Loc, PD, FD)
          << false /*show bit size*/ << 0 << Ty << true /*return*/
          << TI.getTriple().str()) {
        if (D)
          D->setInvalidDecl();
      }
      if (D)
        targetDiag(D->getLocation(), diag::note_defined_here, FD) << D;
    }

    if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType() && FD) {
      llvm::StringMap<bool> CallerFeatureMap;
      Context.getFunctionFeatureMap(CallerFeatureMap, FD);
      RISCV().checkRVVTypeSupport(Ty, Loc, D, CallerFeatureMap);
    }

    // Don't allow SVE types in functions without a SVE target.
    if (Ty->isSVESizelessBuiltinType() && FD && !FD->getType().isNull()) {
      llvm::StringMap<bool> CallerFeatureMap;
      Context.getFunctionFeatureMap(CallerFeatureMap, FD);
      if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) {
        if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap))
          Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty;
        else if (!IsArmStreamingFunction(FD,
                                         /*IncludeLocallyStreaming=*/true))
          Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty;
      }
    }

    if (auto *VT = Ty->getAs<VectorType>();
        VT && FD &&
        (VT->getVectorKind() == VectorKind::SveFixedLengthData ||
         VT->getVectorKind() == VectorKind::SveFixedLengthPredicate) &&
        (LangOpts.VScaleMin != LangOpts.VScaleStreamingMin ||
         LangOpts.VScaleMax != LangOpts.VScaleStreamingMax)) {
      if (IsArmStreamingFunction(FD, /*IncludeLocallyStreaming=*/true)) {
        Diag(Loc, diag::err_sve_fixed_vector_in_streaming_function)
            << Ty << /*Streaming*/ 0;
      } else if (const auto *FTy = FD->getType()->getAs<FunctionProtoType>()) {
        if (FTy->getAArch64SMEAttributes() &
            FunctionType::SME_PStateSMCompatibleMask) {
          Diag(Loc, diag::err_sve_fixed_vector_in_streaming_function)
              << Ty << /*StreamingCompatible*/ 1;
        }
      }
    }
  };

  CheckType(Ty);
  if (const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) {
    for (const auto &ParamTy : FPTy->param_types())
      CheckType(ParamTy);
    CheckType(FPTy->getReturnType(), /*IsRetTy=*/true);
  }
  if (const auto *FNPTy = dyn_cast<FunctionNoProtoType>(Ty))
    CheckType(FNPTy->getReturnType(), /*IsRetTy=*/true);
}

bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) {
  SourceLocation loc = locref;
  if (!loc.isMacroID()) return false;

  // There's no good way right now to look at the intermediate
  // expansions, so just jump to the expansion location.
  loc = getSourceManager().getExpansionLoc(loc);

  // If that's written with the name, stop here.
  SmallString<16> buffer;
  if (getPreprocessor().getSpelling(loc, buffer) == name) {
    locref = loc;
    return true;
  }
  return false;
}

Scope *Sema::getScopeForContext(DeclContext *Ctx) {

  if (!Ctx)
    return nullptr;

  Ctx = Ctx->getPrimaryContext();
  for (Scope *S = getCurScope(); S; S = S->getParent()) {
    // Ignore scopes that cannot have declarations. This is important for
    // out-of-line definitions of static class members.
    if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope))
      if (DeclContext *Entity = S->getEntity())
        if (Ctx == Entity->getPrimaryContext())
          return S;
  }

  return nullptr;
}

/// Enter a new function scope
void Sema::PushFunctionScope() {
  if (FunctionScopes.empty() && CachedFunctionScope) {
    // Use CachedFunctionScope to avoid allocating memory when possible.
    CachedFunctionScope->Clear();
    FunctionScopes.push_back(CachedFunctionScope.release());
  } else {
    FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics()));
  }
  if (LangOpts.OpenMP)
    OpenMP().pushOpenMPFunctionRegion();
}

void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
  FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(),
                                              BlockScope, Block));
  CapturingFunctionScopes++;
}

LambdaScopeInfo *Sema::PushLambdaScope() {
  LambdaScopeInfo *const LSI = new LambdaScopeInfo(getDiagnostics());
  FunctionScopes.push_back(LSI);
  CapturingFunctionScopes++;
  return LSI;
}

void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
  if (LambdaScopeInfo *const LSI = getCurLambda()) {
    LSI->AutoTemplateParameterDepth = Depth;
    return;
  }
  llvm_unreachable(
      "Remove assertion if intentionally called in a non-lambda context.");
}

// Check that the type of the VarDecl has an accessible copy constructor and
// resolve its destructor's exception specification.
// This also performs initialization of block variables when they are moved
// to the heap. It uses the same rules as applicable for implicit moves
// according to the C++ standard in effect ([class.copy.elision]p3).
static void checkEscapingByref(VarDecl *VD, Sema &S) {
  QualType T = VD->getType();
  EnterExpressionEvaluationContext scope(
      S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
  SourceLocation Loc = VD->getLocation();
  Expr *VarRef =
      new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc);
  ExprResult Result;
  auto IE = InitializedEntity::InitializeBlock(Loc, T);
  if (S.getLangOpts().CPlusPlus23) {
    auto *E = ImplicitCastExpr::Create(S.Context, T, CK_NoOp, VarRef, nullptr,
                                       VK_XValue, FPOptionsOverride());
    Result = S.PerformCopyInitialization(IE, SourceLocation(), E);
  } else {
    Result = S.PerformMoveOrCopyInitialization(
        IE, Sema::NamedReturnInfo{VD, Sema::NamedReturnInfo::MoveEligible},
        VarRef);
  }

  if (!Result.isInvalid()) {
    Result = S.MaybeCreateExprWithCleanups(Result);
    Expr *Init = Result.getAs<Expr>();
    S.Context.setBlockVarCopyInit(VD, Init, S.canThrow(Init));
  }

  // The destructor's exception specification is needed when IRGen generates
  // block copy/destroy functions. Resolve it here.
  if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
    if (CXXDestructorDecl *DD = RD->getDestructor()) {
      auto *FPT = DD->getType()->castAs<FunctionProtoType>();
      S.ResolveExceptionSpec(Loc, FPT);
    }
}

static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) {
  // Set the EscapingByref flag of __block variables captured by
  // escaping blocks.
  for (const BlockDecl *BD : FSI.Blocks) {
    for (const BlockDecl::Capture &BC : BD->captures()) {
      VarDecl *VD = BC.getVariable();
      if (VD->hasAttr<BlocksAttr>()) {
        // Nothing to do if this is a __block variable captured by a
        // non-escaping block.
        if (BD->doesNotEscape())
          continue;
        VD->setEscapingByref();
      }
      // Check whether the captured variable is or contains an object of
      // non-trivial C union type.
      QualType CapType = BC.getVariable()->getType();
      if (CapType.hasNonTrivialToPrimitiveDestructCUnion() ||
          CapType.hasNonTrivialToPrimitiveCopyCUnion())
        S.checkNonTrivialCUnion(BC.getVariable()->getType(),
                                BD->getCaretLocation(),
                                NonTrivialCUnionContext::BlockCapture,
                                Sema::NTCUK_Destruct | Sema::NTCUK_Copy);
    }
  }

  for (VarDecl *VD : FSI.ByrefBlockVars) {
    // __block variables might require us to capture a copy-initializer.
    if (!VD->isEscapingByref())
      continue;
    // It's currently invalid to ever have a __block variable with an
    // array type; should we diagnose that here?
    // Regardless, we don't want to ignore array nesting when
    // constructing this copy.
    if (VD->getType()->isStructureOrClassType())
      checkEscapingByref(VD, S);
  }
}

Sema::PoppedFunctionScopePtr
Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
                           const Decl *D, QualType BlockType) {
  assert(!FunctionScopes.empty() && "mismatched push/pop!");

  markEscapingByrefs(*FunctionScopes.back(), *this);

  PoppedFunctionScopePtr Scope(FunctionScopes.pop_back_val(),
                               PoppedFunctionScopeDeleter(this));

  if (LangOpts.OpenMP)
    OpenMP().popOpenMPFunctionRegion(Scope.get());

  // Issue any analysis-based warnings.
  if (WP && D) {
    inferNoReturnAttr(*this, D);
    AnalysisWarnings.IssueWarnings(*WP, Scope.get(), D, BlockType);
  } else
    for (const auto &PUD : Scope->PossiblyUnreachableDiags)
      Diag(PUD.Loc, PUD.PD);

  return Scope;
}

void Sema::PoppedFunctionScopeDeleter::
operator()(sema::FunctionScopeInfo *Scope) const {
  if (!Scope->isPlainFunction())
    Self->CapturingFunctionScopes--;
  // Stash the function scope for later reuse if it's for a normal function.
  if (Scope->isPlainFunction() && !Self->CachedFunctionScope)
    Self->CachedFunctionScope.reset(Scope);
  else
    delete Scope;
}

void Sema::PushCompoundScope(bool IsStmtExpr) {
  getCurFunction()->CompoundScopes.push_back(
      CompoundScopeInfo(IsStmtExpr, getCurFPFeatures()));
}

void Sema::PopCompoundScope() {
  FunctionScopeInfo *CurFunction = getCurFunction();
  assert(!CurFunction->CompoundScopes.empty() && "mismatched push/pop");

  CurFunction->CompoundScopes.pop_back();
}

bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
  return getCurFunction()->hasUnrecoverableErrorOccurred();
}

void Sema::setFunctionHasBranchIntoScope() {
  if (!FunctionScopes.empty())
    FunctionScopes.back()->setHasBranchIntoScope();
}

void Sema::setFunctionHasBranchProtectedScope() {
  if (!FunctionScopes.empty())
    FunctionScopes.back()->setHasBranchProtectedScope();
}

void Sema::setFunctionHasIndirectGoto() {
  if (!FunctionScopes.empty())
    FunctionScopes.back()->setHasIndirectGoto();
}

void Sema::setFunctionHasMustTail() {
  if (!FunctionScopes.empty())
    FunctionScopes.back()->setHasMustTail();
}

BlockScopeInfo *Sema::getCurBlock() {
  if (FunctionScopes.empty())
    return nullptr;

  auto CurBSI = dyn_cast<BlockScopeInfo>(FunctionScopes.back());
  if (CurBSI && CurBSI->TheDecl &&
      !CurBSI->TheDecl->Encloses(CurContext)) {
    // We have switched contexts due to template instantiation.
    assert(!CodeSynthesisContexts.empty());
    return nullptr;
  }

  return CurBSI;
}

FunctionScopeInfo *Sema::getEnclosingFunction() const {
  if (FunctionScopes.empty())
    return nullptr;

  for (int e = FunctionScopes.size() - 1; e >= 0; --e) {
    if (isa<sema::BlockScopeInfo>(FunctionScopes[e]))
      continue;
    return FunctionScopes[e];
  }
  return nullptr;
}

CapturingScopeInfo *Sema::getEnclosingLambdaOrBlock() const {
  for (auto *Scope : llvm::reverse(FunctionScopes)) {
    if (auto *CSI = dyn_cast<CapturingScopeInfo>(Scope)) {
      auto *LSI = dyn_cast<LambdaScopeInfo>(CSI);
      if (LSI && LSI->Lambda && !LSI->Lambda->Encloses(CurContext) &&
          LSI->AfterParameterList) {
        // We have switched contexts due to template instantiation.
        // FIXME: We should swap out the FunctionScopes during code synthesis
        // so that we don't need to check for this.
        assert(!CodeSynthesisContexts.empty());
        return nullptr;
      }
      return CSI;
    }
  }
  return nullptr;
}

LambdaScopeInfo *Sema::getCurLambda(bool IgnoreNonLambdaCapturingScope) {
  if (FunctionScopes.empty())
    return nullptr;

  auto I = FunctionScopes.rbegin();
  if (IgnoreNonLambdaCapturingScope) {
    auto E = FunctionScopes.rend();
    while (I != E && isa<CapturingScopeInfo>(*I) && !isa<LambdaScopeInfo>(*I))
      ++I;
    if (I == E)
      return nullptr;
  }
  auto *CurLSI = dyn_cast<LambdaScopeInfo>(*I);
  if (CurLSI && CurLSI->Lambda && CurLSI->CallOperator &&
      !CurLSI->Lambda->Encloses(CurContext) && CurLSI->AfterParameterList) {
    // We have switched contexts due to template instantiation.
    assert(!CodeSynthesisContexts.empty());
    return nullptr;
  }

  return CurLSI;
}

// We have a generic lambda if we parsed auto parameters, or we have
// an associated template parameter list.
LambdaScopeInfo *Sema::getCurGenericLambda() {
  if (LambdaScopeInfo *LSI =  getCurLambda()) {
    return (LSI->TemplateParams.size() ||
                    LSI->GLTemplateParameterList) ? LSI : nullptr;
  }
  return nullptr;
}


void Sema::ActOnComment(SourceRange Comment) {
  if (!LangOpts.RetainCommentsFromSystemHeaders &&
      SourceMgr.isInSystemHeader(Comment.getBegin()))
    return;
  RawComment RC(SourceMgr, Comment, LangOpts.CommentOpts, false);
  if (RC.isAlmostTrailingComment() || RC.hasUnsupportedSplice(SourceMgr)) {
    SourceRange MagicMarkerRange(Comment.getBegin(),
                                 Comment.getBegin().getLocWithOffset(3));
    StringRef MagicMarkerText;
    switch (RC.getKind()) {
    case RawComment::RCK_OrdinaryBCPL:
      MagicMarkerText = "///<";
      break;
    case RawComment::RCK_OrdinaryC:
      MagicMarkerText = "/**<";
      break;
    case RawComment::RCK_Invalid:
      // FIXME: are there other scenarios that could produce an invalid
      // raw comment here?
      Diag(Comment.getBegin(), diag::warn_splice_in_doxygen_comment);
      return;
    default:
      llvm_unreachable("if this is an almost Doxygen comment, "
                       "it should be ordinary");
    }
    Diag(Comment.getBegin(), diag::warn_not_a_doxygen_trailing_member_comment) <<
      FixItHint::CreateReplacement(MagicMarkerRange, MagicMarkerText);
  }
  Context.addComment(RC);
}

// Pin this vtable to this file.
ExternalSemaSource::~ExternalSemaSource() {}
char ExternalSemaSource::ID;

void ExternalSemaSource::ReadMethodPool(Selector Sel) { }
void ExternalSemaSource::updateOutOfDateSelector(Selector Sel) { }

void ExternalSemaSource::ReadKnownNamespaces(
                           SmallVectorImpl<NamespaceDecl *> &Namespaces) {
}

void ExternalSemaSource::ReadUndefinedButUsed(
    llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {}

void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
    FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}

bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
                         UnresolvedSetImpl &OverloadSet) {
  ZeroArgCallReturnTy = QualType();
  OverloadSet.clear();

  const OverloadExpr *Overloads = nullptr;
  bool IsMemExpr = false;
  if (E.getType() == Context.OverloadTy) {
    OverloadExpr::FindResult FR = OverloadExpr::find(&E);

    // Ignore overloads that are pointer-to-member constants.
    if (FR.HasFormOfMemberPointer)
      return false;

    Overloads = FR.Expression;
  } else if (E.getType() == Context.BoundMemberTy) {
    Overloads = dyn_cast<UnresolvedMemberExpr>(E.IgnoreParens());
    IsMemExpr = true;
  }

  bool Ambiguous = false;
  bool IsMV = false;

  if (Overloads) {
    for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
         DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
      OverloadSet.addDecl(*it);

      // Check whether the function is a non-template, non-member which takes no
      // arguments.
      if (IsMemExpr)
        continue;
      if (const FunctionDecl *OverloadDecl
            = dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
        if (OverloadDecl->getMinRequiredArguments() == 0) {
          if (!ZeroArgCallReturnTy.isNull() && !Ambiguous &&
              (!IsMV || !(OverloadDecl->isCPUDispatchMultiVersion() ||
                          OverloadDecl->isCPUSpecificMultiVersion()))) {
            ZeroArgCallReturnTy = QualType();
            Ambiguous = true;
          } else {
            ZeroArgCallReturnTy = OverloadDecl->getReturnType();
            IsMV = OverloadDecl->isCPUDispatchMultiVersion() ||
                   OverloadDecl->isCPUSpecificMultiVersion();
          }
        }
      }
    }

    // If it's not a member, use better machinery to try to resolve the call
    if (!IsMemExpr)
      return !ZeroArgCallReturnTy.isNull();
  }

  // Attempt to call the member with no arguments - this will correctly handle
  // member templates with defaults/deduction of template arguments, overloads
  // with default arguments, etc.
  if (IsMemExpr && !E.isTypeDependent()) {
    Sema::TentativeAnalysisScope Trap(*this);
    ExprResult R = BuildCallToMemberFunction(nullptr, &E, SourceLocation(), {},
                                             SourceLocation());
    if (R.isUsable()) {
      ZeroArgCallReturnTy = R.get()->getType();
      return true;
    }
    return false;
  }

  if (const auto *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
    if (const auto *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
      if (Fun->getMinRequiredArguments() == 0)
        ZeroArgCallReturnTy = Fun->getReturnType();
      return true;
    }
  }

  // We don't have an expression that's convenient to get a FunctionDecl from,
  // but we can at least check if the type is "function of 0 arguments".
  QualType ExprTy = E.getType();
  const FunctionType *FunTy = nullptr;
  QualType PointeeTy = ExprTy->getPointeeType();
  if (!PointeeTy.isNull())
    FunTy = PointeeTy->getAs<FunctionType>();
  if (!FunTy)
    FunTy = ExprTy->getAs<FunctionType>();

  if (const auto *FPT = dyn_cast_if_present<FunctionProtoType>(FunTy)) {
    if (FPT->getNumParams() == 0)
      ZeroArgCallReturnTy = FunTy->getReturnType();
    return true;
  }
  return false;
}

/// Give notes for a set of overloads.
///
/// A companion to tryExprAsCall. In cases when the name that the programmer
/// wrote was an overloaded function, we may be able to make some guesses about
/// plausible overloads based on their return types; such guesses can be handed
/// off to this method to be emitted as notes.
///
/// \param Overloads - The overloads to note.
/// \param FinalNoteLoc - If we've suppressed printing some overloads due to
///  -fshow-overloads=best, this is the location to attach to the note about too
///  many candidates. Typically this will be the location of the original
///  ill-formed expression.
static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads,
                          const SourceLocation FinalNoteLoc) {
  unsigned ShownOverloads = 0;
  unsigned SuppressedOverloads = 0;
  for (UnresolvedSetImpl::iterator It = Overloads.begin(),
       DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
    if (ShownOverloads >= S.Diags.getNumOverloadCandidatesToShow()) {
      ++SuppressedOverloads;
      continue;
    }

    const NamedDecl *Fn = (*It)->getUnderlyingDecl();
    // Don't print overloads for non-default multiversioned functions.
    if (const auto *FD = Fn->getAsFunction()) {
      if (FD->isMultiVersion() && FD->hasAttr<TargetAttr>() &&
          !FD->getAttr<TargetAttr>()->isDefaultVersion())
        continue;
      if (FD->isMultiVersion() && FD->hasAttr<TargetVersionAttr>() &&
          !FD->getAttr<TargetVersionAttr>()->isDefaultVersion())
        continue;
    }
    S.Diag(Fn->getLocation(), diag::note_possible_target_of_call);
    ++ShownOverloads;
  }

  S.Diags.overloadCandidatesShown(ShownOverloads);

  if (SuppressedOverloads)
    S.Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates)
      << SuppressedOverloads;
}

static void notePlausibleOverloads(Sema &S, SourceLocation Loc,
                                   const UnresolvedSetImpl &Overloads,
                                   bool (*IsPlausibleResult)(QualType)) {
  if (!IsPlausibleResult)
    return noteOverloads(S, Overloads, Loc);

  UnresolvedSet<2> PlausibleOverloads;
  for (OverloadExpr::decls_iterator It = Overloads.begin(),
         DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) {
    const auto *OverloadDecl = cast<FunctionDecl>(*It);
    QualType OverloadResultTy = OverloadDecl->getReturnType();
    if (IsPlausibleResult(OverloadResultTy))
      PlausibleOverloads.addDecl(It.getDecl());
  }
  noteOverloads(S, PlausibleOverloads, Loc);
}

/// Determine whether the given expression can be called by just
/// putting parentheses after it.  Notably, expressions with unary
/// operators can't be because the unary operator will start parsing
/// outside the call.
static bool IsCallableWithAppend(const Expr *E) {
  E = E->IgnoreImplicit();
  return (!isa<CStyleCastExpr>(E) &&
          !isa<UnaryOperator>(E) &&
          !isa<BinaryOperator>(E) &&
          !isa<CXXOperatorCallExpr>(E));
}

static bool IsCPUDispatchCPUSpecificMultiVersion(const Expr *E) {
  if (const auto *UO = dyn_cast<UnaryOperator>(E))
    E = UO->getSubExpr();

  if (const auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
    if (ULE->getNumDecls() == 0)
      return false;

    const NamedDecl *ND = *ULE->decls_begin();
    if (const auto *FD = dyn_cast<FunctionDecl>(ND))
      return FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion();
  }
  return false;
}

bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
                                bool ForceComplain,
                                bool (*IsPlausibleResult)(QualType)) {
  SourceLocation Loc = E.get()->getExprLoc();
  SourceRange Range = E.get()->getSourceRange();
  UnresolvedSet<4> Overloads;

  // If this is a SFINAE context, don't try anything that might trigger ADL
  // prematurely.
  if (!isSFINAEContext()) {
    QualType ZeroArgCallTy;
    if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
        !ZeroArgCallTy.isNull() &&
        (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
      // At this point, we know E is potentially callable with 0
      // arguments and that it returns something of a reasonable type,
      // so we can emit a fixit and carry on pretending that E was
      // actually a CallExpr.
      SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
      bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
      Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
                    << (IsCallableWithAppend(E.get())
                            ? FixItHint::CreateInsertion(ParenInsertionLoc,
                                                         "()")
                            : FixItHint());
      if (!IsMV)
        notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);

      // FIXME: Try this before emitting the fixit, and suppress diagnostics
      // while doing so.
      E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), {},
                        Range.getEnd().getLocWithOffset(1));
      return true;
    }
  }
  if (!ForceComplain) return false;

  bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
  Diag(Loc, PD) << /*not zero-arg*/ 0 << IsMV << Range;
  if (!IsMV)
    notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
  E = ExprError();
  return true;
}

IdentifierInfo *Sema::getSuperIdentifier() const {
  if (!Ident_super)
    Ident_super = &Context.Idents.get("super");
  return Ident_super;
}

void Sema::PushCapturedRegionScope(Scope *S, CapturedDecl *CD, RecordDecl *RD,
                                   CapturedRegionKind K,
                                   unsigned OpenMPCaptureLevel) {
  auto *CSI = new CapturedRegionScopeInfo(
      getDiagnostics(), S, CD, RD, CD->getContextParam(), K,
      (getLangOpts().OpenMP && K == CR_OpenMP)
          ? OpenMP().getOpenMPNestingLevel()
          : 0,
      OpenMPCaptureLevel);
  CSI->ReturnType = Context.VoidTy;
  FunctionScopes.push_back(CSI);
  CapturingFunctionScopes++;
}

CapturedRegionScopeInfo *Sema::getCurCapturedRegion() {
  if (FunctionScopes.empty())
    return nullptr;

  return dyn_cast<CapturedRegionScopeInfo>(FunctionScopes.back());
}

const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
Sema::getMismatchingDeleteExpressions() const {
  return DeleteExprs;
}

Sema::FPFeaturesStateRAII::FPFeaturesStateRAII(Sema &S)
    : S(S), OldFPFeaturesState(S.CurFPFeatures),
      OldOverrides(S.FpPragmaStack.CurrentValue),
      OldEvalMethod(S.PP.getCurrentFPEvalMethod()),
      OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()) {}

Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() {
  S.CurFPFeatures = OldFPFeaturesState;
  S.FpPragmaStack.CurrentValue = OldOverrides;
  S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod);
}

bool Sema::isDeclaratorFunctionLike(Declarator &D) {
  assert(D.getCXXScopeSpec().isSet() &&
         "can only be called for qualified names");

  auto LR = LookupResult(*this, D.getIdentifier(), D.getBeginLoc(),
                         LookupOrdinaryName, forRedeclarationInCurContext());
  DeclContext *DC = computeDeclContext(D.getCXXScopeSpec(),
                                       !D.getDeclSpec().isFriendSpecified());
  if (!DC)
    return false;

  LookupQualifiedName(LR, DC);
  bool Result = llvm::all_of(LR, [](Decl *Dcl) {
    if (NamedDecl *ND = dyn_cast<NamedDecl>(Dcl)) {
      ND = ND->getUnderlyingDecl();
      return isa<FunctionDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
             isa<UsingDecl>(ND);
    }
    return false;
  });
  return Result;
}

Attr *Sema::CreateAnnotationAttr(const AttributeCommonInfo &CI, StringRef Annot,
                                 MutableArrayRef<Expr *> Args) {

  auto *A = AnnotateAttr::Create(Context, Annot, Args.data(), Args.size(), CI);
  if (!ConstantFoldAttrArgs(
          CI, MutableArrayRef<Expr *>(A->args_begin(), A->args_end()))) {
    return nullptr;
  }
  return A;
}

Attr *Sema::CreateAnnotationAttr(const ParsedAttr &AL) {
  // Make sure that there is a string literal as the annotation's first
  // argument.
  StringRef Str;
  if (!checkStringLiteralArgumentAttr(AL, 0, Str))
    return nullptr;

  llvm::SmallVector<Expr *, 4> Args;
  Args.reserve(AL.getNumArgs() - 1);
  for (unsigned Idx = 1; Idx < AL.getNumArgs(); Idx++) {
    assert(!AL.isArgIdent(Idx));
    Args.push_back(AL.getArgAsExpr(Idx));
  }

  return CreateAnnotationAttr(AL, Str, Args);
}
