diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 25c4c58ad4ae4..f3d3a57104ee0 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -76,168 +76,168 @@ #include namespace llvm { - class APSInt; - template class DenseSet; - class SmallBitVector; - struct InlineAsmIdentifierInfo; -} +class APSInt; +template class DenseSet; +class SmallBitVector; +struct InlineAsmIdentifierInfo; +} // namespace llvm namespace clang { - class ADLResult; - class ASTConsumer; - class ASTContext; - class ASTMutationListener; - class ASTReader; - class ASTWriter; - class ArrayType; - class ParsedAttr; - class BindingDecl; - class BlockDecl; - class CapturedDecl; - class CXXBasePath; - class CXXBasePaths; - class CXXBindTemporaryExpr; - typedef SmallVector CXXCastPath; - class CXXConstructorDecl; - class CXXConversionDecl; - class CXXDeleteExpr; - class CXXDestructorDecl; - class CXXFieldCollector; - class CXXMemberCallExpr; - class CXXMethodDecl; - class CXXScopeSpec; - class CXXTemporary; - class CXXTryStmt; - class CallExpr; - class ClassTemplateDecl; - class ClassTemplatePartialSpecializationDecl; - class ClassTemplateSpecializationDecl; - class VarTemplatePartialSpecializationDecl; - class CodeCompleteConsumer; - class CodeCompletionAllocator; - class CodeCompletionTUInfo; - class CodeCompletionResult; - class CoroutineBodyStmt; - class Decl; - class DeclAccessPair; - class DeclContext; - class DeclRefExpr; - class DeclaratorDecl; - class DeducedTemplateArgument; - class DependentDiagnostic; - class DesignatedInitExpr; - class Designation; - class EnableIfAttr; - class EnumConstantDecl; - class Expr; - class ExtVectorType; - class FormatAttr; - class FriendDecl; - class FunctionDecl; - class FunctionProtoType; - class FunctionTemplateDecl; - class ImplicitConversionSequence; - typedef MutableArrayRef ConversionSequenceList; - class InitListExpr; - class InitializationKind; - class InitializationSequence; - class InitializedEntity; - class IntegerLiteral; - class LabelStmt; - class LambdaExpr; - class LangOptions; - class LocalInstantiationScope; - class LookupResult; - class MacroInfo; - typedef ArrayRef> ModuleIdPath; - class ModuleLoader; - class MultiLevelTemplateArgumentList; - class NamedDecl; - class ObjCCategoryDecl; - class ObjCCategoryImplDecl; - class ObjCCompatibleAliasDecl; - class ObjCContainerDecl; - class ObjCImplDecl; - class ObjCImplementationDecl; - class ObjCInterfaceDecl; - class ObjCIvarDecl; - template class ObjCList; - class ObjCMessageExpr; - class ObjCMethodDecl; - class ObjCPropertyDecl; - class ObjCProtocolDecl; - class OMPThreadPrivateDecl; - class OMPRequiresDecl; - class OMPDeclareReductionDecl; - class OMPDeclareSimdDecl; - class OMPClause; - struct OMPVarListLocTy; - struct OverloadCandidate; - enum class OverloadCandidateParamOrder : char; - enum OverloadCandidateRewriteKind : unsigned; - class OverloadCandidateSet; - class OverloadExpr; - class ParenListExpr; - class ParmVarDecl; - class Preprocessor; - class PseudoDestructorTypeStorage; - class PseudoObjectExpr; - class QualType; - class StandardConversionSequence; - class Stmt; - class StringLiteral; - class SwitchStmt; - class TemplateArgument; - class TemplateArgumentList; - class TemplateArgumentLoc; - class TemplateDecl; - class TemplateInstantiationCallback; - class TemplateParameterList; - class TemplatePartialOrderingContext; - class TemplateTemplateParmDecl; - class Token; - class TypeAliasDecl; - class TypedefDecl; - class TypedefNameDecl; - class TypeLoc; - class TypoCorrectionConsumer; - class UnqualifiedId; - class UnresolvedLookupExpr; - class UnresolvedMemberExpr; - class UnresolvedSetImpl; - class UnresolvedSetIterator; - class UsingDecl; - class UsingShadowDecl; - class ValueDecl; - class VarDecl; - class VarTemplateSpecializationDecl; - class VisibilityAttr; - class VisibleDeclConsumer; - class IndirectFieldDecl; - struct DeductionFailureInfo; - class TemplateSpecCandidateSet; +class ADLResult; +class ASTConsumer; +class ASTContext; +class ASTMutationListener; +class ASTReader; +class ASTWriter; +class ArrayType; +class ParsedAttr; +class BindingDecl; +class BlockDecl; +class CapturedDecl; +class CXXBasePath; +class CXXBasePaths; +class CXXBindTemporaryExpr; +typedef SmallVector CXXCastPath; +class CXXConstructorDecl; +class CXXConversionDecl; +class CXXDeleteExpr; +class CXXDestructorDecl; +class CXXFieldCollector; +class CXXMemberCallExpr; +class CXXMethodDecl; +class CXXScopeSpec; +class CXXTemporary; +class CXXTryStmt; +class CallExpr; +class ClassTemplateDecl; +class ClassTemplatePartialSpecializationDecl; +class ClassTemplateSpecializationDecl; +class VarTemplatePartialSpecializationDecl; +class CodeCompleteConsumer; +class CodeCompletionAllocator; +class CodeCompletionTUInfo; +class CodeCompletionResult; +class CoroutineBodyStmt; +class Decl; +class DeclAccessPair; +class DeclContext; +class DeclRefExpr; +class DeclaratorDecl; +class DeducedTemplateArgument; +class DependentDiagnostic; +class DesignatedInitExpr; +class Designation; +class EnableIfAttr; +class EnumConstantDecl; +class Expr; +class ExtVectorType; +class FormatAttr; +class FriendDecl; +class FunctionDecl; +class FunctionProtoType; +class FunctionTemplateDecl; +class ImplicitConversionSequence; +typedef MutableArrayRef ConversionSequenceList; +class InitListExpr; +class InitializationKind; +class InitializationSequence; +class InitializedEntity; +class IntegerLiteral; +class LabelStmt; +class LambdaExpr; +class LangOptions; +class LocalInstantiationScope; +class LookupResult; +class MacroInfo; +typedef ArrayRef> ModuleIdPath; +class ModuleLoader; +class MultiLevelTemplateArgumentList; +class NamedDecl; +class ObjCCategoryDecl; +class ObjCCategoryImplDecl; +class ObjCCompatibleAliasDecl; +class ObjCContainerDecl; +class ObjCImplDecl; +class ObjCImplementationDecl; +class ObjCInterfaceDecl; +class ObjCIvarDecl; +template class ObjCList; +class ObjCMessageExpr; +class ObjCMethodDecl; +class ObjCPropertyDecl; +class ObjCProtocolDecl; +class OMPThreadPrivateDecl; +class OMPRequiresDecl; +class OMPDeclareReductionDecl; +class OMPDeclareSimdDecl; +class OMPClause; +struct OMPVarListLocTy; +struct OverloadCandidate; +enum class OverloadCandidateParamOrder : char; +enum OverloadCandidateRewriteKind : unsigned; +class OverloadCandidateSet; +class OverloadExpr; +class ParenListExpr; +class ParmVarDecl; +class Preprocessor; +class PseudoDestructorTypeStorage; +class PseudoObjectExpr; +class QualType; +class StandardConversionSequence; +class Stmt; +class StringLiteral; +class SwitchStmt; +class TemplateArgument; +class TemplateArgumentList; +class TemplateArgumentLoc; +class TemplateDecl; +class TemplateInstantiationCallback; +class TemplateParameterList; +class TemplatePartialOrderingContext; +class TemplateTemplateParmDecl; +class Token; +class TypeAliasDecl; +class TypedefDecl; +class TypedefNameDecl; +class TypeLoc; +class TypoCorrectionConsumer; +class UnqualifiedId; +class UnresolvedLookupExpr; +class UnresolvedMemberExpr; +class UnresolvedSetImpl; +class UnresolvedSetIterator; +class UsingDecl; +class UsingShadowDecl; +class ValueDecl; +class VarDecl; +class VarTemplateSpecializationDecl; +class VisibilityAttr; +class VisibleDeclConsumer; +class IndirectFieldDecl; +struct DeductionFailureInfo; +class TemplateSpecCandidateSet; namespace sema { - class AccessedEntity; - class BlockScopeInfo; - class Capture; - class CapturedRegionScopeInfo; - class CapturingScopeInfo; - class CompoundScopeInfo; - class DelayedDiagnostic; - class DelayedDiagnosticPool; - class FunctionScopeInfo; - class LambdaScopeInfo; - class PossiblyUnreachableDiag; - class RISCVIntrinsicManager; - class SemaPPCallbacks; - class TemplateDeductionInfo; -} +class AccessedEntity; +class BlockScopeInfo; +class Capture; +class CapturedRegionScopeInfo; +class CapturingScopeInfo; +class CompoundScopeInfo; +class DelayedDiagnostic; +class DelayedDiagnosticPool; +class FunctionScopeInfo; +class LambdaScopeInfo; +class PossiblyUnreachableDiag; +class RISCVIntrinsicManager; +class SemaPPCallbacks; +class TemplateDeductionInfo; +} // namespace sema namespace threadSafety { - class BeforeSet; - void threadSafetyCleanup(BeforeSet* Cache); -} +class BeforeSet; +void threadSafetyCleanup(BeforeSet *Cache); +} // namespace threadSafety // FIXME: No way to easily map from TemplateTypeParmTypes to // TemplateTypeParmDecls, so we have this horrible PointerUnion. @@ -422,591 +422,652 @@ enum class TemplateDeductionResult { }; /// Sema - This implements semantic analysis and AST building for C. +/// \nosubgrouping class Sema final { - Sema(const Sema &) = delete; - void operator=(const Sema &) = delete; - - ///Source of additional semantic information. - IntrusiveRefCntPtr ExternalSource; - - static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); - - /// Determine whether two declarations should be linked together, given that - /// the old declaration might not be visible and the new declaration might - /// not have external linkage. - bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old, - const NamedDecl *New) { - if (isVisible(Old)) - return true; - // See comment in below overload for why it's safe to compute the linkage - // of the new declaration here. - if (New->isExternallyDeclarable()) { - assert(Old->isExternallyDeclarable() && - "should not have found a non-externally-declarable previous decl"); - return true; - } - return false; - } - bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New); - - void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem, - QualType ResultTy, - ArrayRef Args); + // Table of Contents + // ----------------- + // 1. Semantic Analysis (Sema.cpp) + // 2. C++ Access Control (SemaAccess.cpp) + // 3. Attributes (SemaAttr.cpp) + // 4. Availability Attribute Handling (SemaAvailability.cpp) + // 5. Casts (SemaCast.cpp) + // 6. Extra Semantic Checking (SemaChecking.cpp) + // 7. C++ Coroutines (SemaCoroutine.cpp) + // 8. C++ Scope Specifiers (SemaCXXScopeSpec.cpp) + // 9. Declarations (SemaDecl.cpp) + // 10. Declaration Attribute Handling (SemaDeclAttr.cpp) + // 11. C++ Declarations (SemaDeclCXX.cpp) + // 12. C++ Exception Specifications (SemaExceptionSpec.cpp) + // 13. Expressions (SemaExpr.cpp) + // 14. C++ Expressions (SemaExprCXX.cpp) + // 15. Member Access Expressions (SemaExprMember.cpp) + // 16. Initializers (SemaInit.cpp) + // 17. C++ Lambda Expressions (SemaLambda.cpp) + // 18. Name Lookup (SemaLookup.cpp) + // 19. Modules (SemaModule.cpp) + // 20. C++ Overloading (SemaOverload.cpp) + // 21. Pseudo-Object (SemaPseudoObject.cpp) + // 22. Statements (SemaStmt.cpp) + // 23. `inline asm` Statement (SemaStmtAsm.cpp) + // 24. Statement Attribute Handling (SemaStmtAttr.cpp) + // 25. C++ Templates (SemaTemplate.cpp) + // 26. C++ Template Argument Deduction (SemaTemplateDeduction.cpp) + // 27. C++ Template Instantiation (SemaTemplateInstantiate.cpp) + // 28. C++ Template Declaration Instantiation + // (SemaTemplateInstantiateDecl.cpp) + // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp) + // 30. Constraints and Concepts (SemaConcept.cpp) + // 31. Types (SemaType.cpp) + // 32. ObjC Declarations (SemaDeclObjC.cpp) + // 33. ObjC Expressions (SemaExprObjC.cpp) + // 34. ObjC @property and @synthesize (SemaObjCProperty.cpp) + // 35. Code Completion (SemaCodeComplete.cpp) + // 36. FixIt Helpers (SemaFixItUtils.cpp) + // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) + // 38. CUDA (SemaCUDA.cpp) + // 39. HLSL Constructs (SemaHLSL.cpp) + // 40. OpenACC Constructs (SemaOpenACC.cpp) + // 41. OpenMP Directives and Clauses (SemaOpenMP.cpp) + // 42. SYCL Constructs (SemaSYCL.cpp) + + /// \name Semantic Analysis + /// Implementations are in Sema.cpp + ///@{ public: - /// The maximum alignment, same as in llvm::Value. We duplicate them here - /// because that allows us not to duplicate the constants in clang code, - /// which we must to since we can't directly use the llvm constants. - /// The value is verified against llvm here: lib/CodeGen/CGDecl.cpp - /// - /// This is the greatest alignment value supported by load, store, and alloca - /// instructions, and global values. - static const unsigned MaxAlignmentExponent = 32; - static const uint64_t MaximumAlignment = 1ull << MaxAlignmentExponent; - - typedef OpaquePtr DeclGroupPtrTy; - typedef OpaquePtr TemplateTy; - typedef OpaquePtr TypeTy; - - OpenCLOptions OpenCLFeatures; - FPOptions CurFPFeatures; - - const LangOptions &LangOpts; - Preprocessor &PP; - ASTContext &Context; - ASTConsumer &Consumer; - DiagnosticsEngine &Diags; - SourceManager &SourceMgr; - api_notes::APINotesManager APINotes; - - /// Flag indicating whether or not to collect detailed statistics. - bool CollectStats; - - /// Code-completion consumer. - CodeCompleteConsumer *CodeCompleter; + Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, + TranslationUnitKind TUKind = TU_Complete, + CodeCompleteConsumer *CompletionConsumer = nullptr); + ~Sema(); - /// CurContext - This is the current declaration context of parsing. - DeclContext *CurContext; + /// Perform initialization that occurs after the parser has been + /// initialized but before it parses anything. + void Initialize(); - /// Generally null except when we temporarily switch decl contexts, - /// like in \see ActOnObjCTemporaryExitContainerContext. - DeclContext *OriginalLexicalContext; + /// This virtual key function only exists to limit the emission of debug info + /// describing the Sema class. GCC and Clang only emit debug info for a class + /// with a vtable when the vtable is emitted. Sema is final and not + /// polymorphic, but the debug info size savings are so significant that it is + /// worth adding a vtable just to take advantage of this optimization. + virtual void anchor(); - /// VAListTagName - The declaration name corresponding to __va_list_tag. - /// This is used as part of a hack to omit that class from ADL results. - DeclarationName VAListTagName; + const LangOptions &getLangOpts() const { return LangOpts; } + OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; } + FPOptions &getCurFPFeatures() { return CurFPFeatures; } - bool MSStructPragmaOn; // True when \#pragma ms_struct on + DiagnosticsEngine &getDiagnostics() const { return Diags; } + SourceManager &getSourceManager() const { return SourceMgr; } + Preprocessor &getPreprocessor() const { return PP; } + ASTContext &getASTContext() const { return Context; } + ASTConsumer &getASTConsumer() const { return Consumer; } + ASTMutationListener *getASTMutationListener() const; + ExternalSemaSource *getExternalSource() const { return ExternalSource.get(); } - /// Controls member pointer representation format under the MS ABI. - LangOptions::PragmaMSPointersToMembersKind - MSPointerToMemberRepresentationMethod; + DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc, + StringRef Platform); + DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(); - /// Stack of active SEH __finally scopes. Can be empty. - SmallVector CurrentSEHFinally; + /// Registers an external source. If an external source already exists, + /// creates a multiplex external source and appends to it. + /// + ///\param[in] E - A non-null external sema source. + /// + void addExternalSource(ExternalSemaSource *E); - /// Source location for newly created implicit MSInheritanceAttrs - SourceLocation ImplicitMSInheritanceAttrLoc; + /// Helper class that creates diagnostics with optional + /// template instantiation stacks. + /// + /// This class provides a wrapper around the basic DiagnosticBuilder + /// class that emits diagnostics. ImmediateDiagBuilder is + /// responsible for emitting the diagnostic (as DiagnosticBuilder + /// does) and, if the diagnostic comes from inside a template + /// instantiation, printing the template instantiation stack as + /// well. + class ImmediateDiagBuilder : public DiagnosticBuilder { + Sema &SemaRef; + unsigned DiagID; - /// Holds TypoExprs that are created from `createDelayedTypo`. This is used by - /// `TransformTypos` in order to keep track of any TypoExprs that are created - /// recursively during typo correction and wipe them away if the correction - /// fails. - llvm::SmallVector TypoExprs; + public: + ImmediateDiagBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID) + : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {} + ImmediateDiagBuilder(DiagnosticBuilder &&DB, Sema &SemaRef, unsigned DiagID) + : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {} - /// pragma clang section kind - enum PragmaClangSectionKind { - PCSK_Invalid = 0, - PCSK_BSS = 1, - PCSK_Data = 2, - PCSK_Rodata = 3, - PCSK_Text = 4, - PCSK_Relro = 5 - }; + // This is a cunning lie. DiagnosticBuilder actually performs move + // construction in its copy constructor (but due to varied uses, it's not + // possible to conveniently express this as actual move construction). So + // the default copy ctor here is fine, because the base class disables the + // source anyway, so the user-defined ~ImmediateDiagBuilder is a safe no-op + // in that case anwyay. + ImmediateDiagBuilder(const ImmediateDiagBuilder &) = default; - enum PragmaClangSectionAction { - PCSA_Set = 0, - PCSA_Clear = 1 - }; + ~ImmediateDiagBuilder() { + // If we aren't active, there is nothing to do. + if (!isActive()) + return; - struct PragmaClangSection { - std::string SectionName; - bool Valid = false; - SourceLocation PragmaLocation; - }; + // Otherwise, we need to emit the diagnostic. First clear the diagnostic + // builder itself so it won't emit the diagnostic in its own destructor. + // + // This seems wasteful, in that as written the DiagnosticBuilder dtor will + // do its own needless checks to see if the diagnostic needs to be + // emitted. However, because we take care to ensure that the builder + // objects never escape, a sufficiently smart compiler will be able to + // eliminate that code. + Clear(); - PragmaClangSection PragmaClangBSSSection; - PragmaClangSection PragmaClangDataSection; - PragmaClangSection PragmaClangRodataSection; - PragmaClangSection PragmaClangRelroSection; - PragmaClangSection PragmaClangTextSection; + // Dispatch to Sema to emit the diagnostic. + SemaRef.EmitCurrentDiagnostic(DiagID); + } - enum PragmaMsStackAction { - PSK_Reset = 0x0, // #pragma () - PSK_Set = 0x1, // #pragma (value) - PSK_Push = 0x2, // #pragma (push[, id]) - PSK_Pop = 0x4, // #pragma (pop[, id]) - PSK_Show = 0x8, // #pragma (show) -- only for "pack"! - PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) - PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) - }; + /// Teach operator<< to produce an object of the correct type. + template + friend const ImmediateDiagBuilder & + operator<<(const ImmediateDiagBuilder &Diag, const T &Value) { + const DiagnosticBuilder &BaseDiag = Diag; + BaseDiag << Value; + return Diag; + } - struct PragmaPackInfo { - PragmaMsStackAction Action; - StringRef SlotLabel; - Token Alignment; + // It is necessary to limit this to rvalue reference to avoid calling this + // function with a bitfield lvalue argument since non-const reference to + // bitfield is not allowed. + template ::value>> + const ImmediateDiagBuilder &operator<<(T &&V) const { + const DiagnosticBuilder &BaseDiag = *this; + BaseDiag << std::move(V); + return *this; + } }; - // #pragma pack and align. - class AlignPackInfo { + /// A generic diagnostic builder for errors which may or may not be deferred. + /// + /// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch) + /// which are not allowed to appear inside __device__ functions and are + /// allowed to appear in __host__ __device__ functions only if the host+device + /// function is never codegen'ed. + /// + /// To handle this, we use the notion of "deferred diagnostics", where we + /// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed. + /// + /// This class lets you emit either a regular diagnostic, a deferred + /// diagnostic, or no diagnostic at all, according to an argument you pass to + /// its constructor, thus simplifying the process of creating these "maybe + /// deferred" diagnostics. + class SemaDiagnosticBuilder { public: - // `Native` represents default align mode, which may vary based on the - // platform. - enum Mode : unsigned char { Native, Natural, Packed, Mac68k }; - - // #pragma pack info constructor - AlignPackInfo(AlignPackInfo::Mode M, unsigned Num, bool IsXL) - : PackAttr(true), AlignMode(M), PackNumber(Num), XLStack(IsXL) { - assert(Num == PackNumber && "The pack number has been truncated."); - } - - // #pragma align info constructor - AlignPackInfo(AlignPackInfo::Mode M, bool IsXL) - : PackAttr(false), AlignMode(M), - PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {} + enum Kind { + /// Emit no diagnostics. + K_Nop, + /// Emit the diagnostic immediately (i.e., behave like Sema::Diag()). + K_Immediate, + /// Emit the diagnostic immediately, and, if it's a warning or error, also + /// emit a call stack showing how this function can be reached by an a + /// priori known-emitted function. + K_ImmediateWithCallStack, + /// Create a deferred diagnostic, which is emitted only if the function + /// it's attached to is codegen'ed. Also emit a call stack as with + /// K_ImmediateWithCallStack. + K_Deferred + }; - explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {} + SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID, + const FunctionDecl *Fn, Sema &S); + SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D); + SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default; - AlignPackInfo() : AlignPackInfo(Native, false) {} + // The copy and move assignment operator is defined as deleted pending + // further motivation. + SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete; + SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete; - // When a AlignPackInfo itself cannot be used, this returns an 32-bit - // integer encoding for it. This should only be passed to - // AlignPackInfo::getFromRawEncoding, it should not be inspected directly. - static uint32_t getRawEncoding(const AlignPackInfo &Info) { - std::uint32_t Encoding{}; - if (Info.IsXLStack()) - Encoding |= IsXLMask; + ~SemaDiagnosticBuilder(); - Encoding |= static_cast(Info.getAlignMode()) << 1; + bool isImmediate() const { return ImmediateDiag.has_value(); } - if (Info.IsPackAttr()) - Encoding |= PackAttrMask; + /// Convertible to bool: True if we immediately emitted an error, false if + /// we didn't emit an error or we created a deferred error. + /// + /// Example usage: + /// + /// if (SemaDiagnosticBuilder(...) << foo << bar) + /// return ExprError(); + /// + /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably + /// want to use these instead of creating a SemaDiagnosticBuilder yourself. + operator bool() const { return isImmediate(); } - Encoding |= static_cast(Info.getPackNumber()) << 4; - - return Encoding; + template + friend const SemaDiagnosticBuilder & + operator<<(const SemaDiagnosticBuilder &Diag, const T &Value) { + if (Diag.ImmediateDiag) + *Diag.ImmediateDiag << Value; + else if (Diag.PartialDiagId) + Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second + << Value; + return Diag; } - static AlignPackInfo getFromRawEncoding(unsigned Encoding) { - bool IsXL = static_cast(Encoding & IsXLMask); - AlignPackInfo::Mode M = - static_cast((Encoding & AlignModeMask) >> 1); - int PackNumber = (Encoding & PackNumMask) >> 4; + // It is necessary to limit this to rvalue reference to avoid calling this + // function with a bitfield lvalue argument since non-const reference to + // bitfield is not allowed. + template ::value>> + const SemaDiagnosticBuilder &operator<<(T &&V) const { + if (ImmediateDiag) + *ImmediateDiag << std::move(V); + else if (PartialDiagId) + S.DeviceDeferredDiags[Fn][*PartialDiagId].second << std::move(V); + return *this; + } - if (Encoding & PackAttrMask) - return AlignPackInfo(M, PackNumber, IsXL); + friend const SemaDiagnosticBuilder & + operator<<(const SemaDiagnosticBuilder &Diag, const PartialDiagnostic &PD) { + if (Diag.ImmediateDiag) + PD.Emit(*Diag.ImmediateDiag); + else if (Diag.PartialDiagId) + Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD; + return Diag; + } - return AlignPackInfo(M, IsXL); + void AddFixItHint(const FixItHint &Hint) const { + if (ImmediateDiag) + ImmediateDiag->AddFixItHint(Hint); + else if (PartialDiagId) + S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint); } - bool IsPackAttr() const { return PackAttr; } + friend ExprResult ExprError(const SemaDiagnosticBuilder &) { + return ExprError(); + } + friend StmtResult StmtError(const SemaDiagnosticBuilder &) { + return StmtError(); + } + operator ExprResult() const { return ExprError(); } + operator StmtResult() const { return StmtError(); } + operator TypeResult() const { return TypeError(); } + operator DeclResult() const { return DeclResult(true); } + operator MemInitResult() const { return MemInitResult(true); } - bool IsAlignAttr() const { return !PackAttr; } + private: + Sema &S; + SourceLocation Loc; + unsigned DiagID; + const FunctionDecl *Fn; + bool ShowCallStack; - Mode getAlignMode() const { return AlignMode; } + // Invariant: At most one of these Optionals has a value. + // FIXME: Switch these to a Variant once that exists. + std::optional ImmediateDiag; + std::optional PartialDiagId; + }; - unsigned getPackNumber() const { return PackNumber; } + void PrintStats() const; - bool IsPackSet() const { - // #pragma align, #pragma pack(), and #pragma pack(0) do not set the pack - // attriute on a decl. - return PackNumber != UninitPackVal && PackNumber != 0; - } + /// Warn that the stack is nearly exhausted. + void warnStackExhausted(SourceLocation Loc); - bool IsXLStack() const { return XLStack; } + /// Run some code with "sufficient" stack space. (Currently, at least 256K is + /// guaranteed). Produces a warning if we're low on stack space and allocates + /// more in that case. Use this in code that may recurse deeply (for example, + /// in template instantiation) to avoid stack overflow. + void runWithSufficientStackSpace(SourceLocation Loc, + llvm::function_ref Fn); - bool operator==(const AlignPackInfo &Info) const { - return std::tie(AlignMode, PackNumber, PackAttr, XLStack) == - std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr, - Info.XLStack); - } + /// Returns default addr space for method qualifiers. + LangAS getDefaultCXXMethodAddrSpace() const; - bool operator!=(const AlignPackInfo &Info) const { - return !(*this == Info); - } + /// Load weak undeclared identifiers from the external source. + void LoadExternalWeakUndeclaredIdentifiers(); - private: - /// \brief True if this is a pragma pack attribute, - /// not a pragma align attribute. - bool PackAttr; + /// Determine if VD, which must be a variable or function, is an external + /// symbol that nonetheless can't be referenced from outside this translation + /// unit because its type has no linkage and it's not extern "C". + bool isExternalWithNoLinkageType(const ValueDecl *VD) const; - /// \brief The alignment mode that is in effect. - Mode AlignMode; + /// Obtain a sorted list of functions that are undefined but ODR-used. + void getUndefinedButUsed( + SmallVectorImpl> &Undefined); - /// \brief The pack number of the stack. - unsigned char PackNumber; + typedef std::pair DeleteExprLoc; + typedef llvm::SmallVector DeleteLocs; + /// Retrieves list of suspicious delete-expressions that will be checked at + /// the end of translation unit. + const llvm::MapVector & + getMismatchingDeleteExpressions() const; - /// \brief True if it is a XL #pragma align/pack stack. - bool XLStack; + /// Cause the active diagnostic on the DiagosticsEngine to be + /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and + /// should not be used elsewhere. + void EmitCurrentDiagnostic(unsigned DiagID); - /// \brief Uninitialized pack value. - static constexpr unsigned char UninitPackVal = -1; + void addImplicitTypedef(StringRef Name, QualType T); - // Masks to encode and decode an AlignPackInfo. - static constexpr uint32_t IsXLMask{0x0000'0001}; - static constexpr uint32_t AlignModeMask{0x0000'0006}; - static constexpr uint32_t PackAttrMask{0x00000'0008}; - static constexpr uint32_t PackNumMask{0x0000'01F0}; - }; + /// Emit a diagnostic. + SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, + bool DeferHint = false); - template - struct PragmaStack { - struct Slot { - llvm::StringRef StackSlotLabel; - ValueType Value; - SourceLocation PragmaLocation; - SourceLocation PragmaPushLocation; - Slot(llvm::StringRef StackSlotLabel, ValueType Value, - SourceLocation PragmaLocation, SourceLocation PragmaPushLocation) - : StackSlotLabel(StackSlotLabel), Value(Value), - PragmaLocation(PragmaLocation), - PragmaPushLocation(PragmaPushLocation) {} - }; + /// Emit a partial diagnostic. + SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD, + bool DeferHint = false); - void Act(SourceLocation PragmaLocation, PragmaMsStackAction Action, - llvm::StringRef StackSlotLabel, ValueType Value) { - if (Action == PSK_Reset) { - CurrentValue = DefaultValue; - CurrentPragmaLocation = PragmaLocation; - return; - } - if (Action & PSK_Push) - Stack.emplace_back(StackSlotLabel, CurrentValue, CurrentPragmaLocation, - PragmaLocation); - else if (Action & PSK_Pop) { - if (!StackSlotLabel.empty()) { - // If we've got a label, try to find it and jump there. - auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { - return x.StackSlotLabel == StackSlotLabel; - }); - // If we found the label so pop from there. - if (I != Stack.rend()) { - CurrentValue = I->Value; - CurrentPragmaLocation = I->PragmaLocation; - Stack.erase(std::prev(I.base()), Stack.end()); - } - } else if (!Stack.empty()) { - // We do not have a label, just pop the last entry. - CurrentValue = Stack.back().Value; - CurrentPragmaLocation = Stack.back().PragmaLocation; - Stack.pop_back(); - } - } - if (Action & PSK_Set) { - CurrentValue = Value; - CurrentPragmaLocation = PragmaLocation; - } - } + /// Whether uncompilable error has occurred. This includes error happens + /// in deferred diagnostics. + bool hasUncompilableErrorOccurred() const; - // MSVC seems to add artificial slots to #pragma stacks on entering a C++ - // method body to restore the stacks on exit, so it works like this: - // - // struct S { - // #pragma (push, InternalPragmaSlot, ) - // void Method {} - // #pragma (pop, InternalPragmaSlot) - // }; - // - // It works even with #pragma vtordisp, although MSVC doesn't support - // #pragma vtordisp(push [, id], n) - // syntax. - // - // Push / pop a named sentinel slot. - void SentinelAction(PragmaMsStackAction Action, StringRef Label) { - assert((Action == PSK_Push || Action == PSK_Pop) && - "Can only push / pop #pragma stack sentinels!"); - Act(CurrentPragmaLocation, Action, Label, CurrentValue); - } + bool findMacroSpelling(SourceLocation &loc, StringRef name); - // Constructors. - explicit PragmaStack(const ValueType &Default) - : DefaultValue(Default), CurrentValue(Default) {} + /// Calls \c Lexer::getLocForEndOfToken() + SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0); - bool hasValue() const { return CurrentValue != DefaultValue; } + /// Retrieve the module loader associated with the preprocessor. + ModuleLoader &getModuleLoader() const; - SmallVector Stack; - ValueType DefaultValue; // Value used for PSK_Reset action. - ValueType CurrentValue; - SourceLocation CurrentPragmaLocation; - }; - // FIXME: We should serialize / deserialize these if they occur in a PCH (but - // we shouldn't do so if they're in a module). + /// Invent a new identifier for parameters of abbreviated templates. + IdentifierInfo * + InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName, + unsigned Index); - /// Whether to insert vtordisps prior to virtual bases in the Microsoft - /// C++ ABI. Possible values are 0, 1, and 2, which mean: - /// - /// 0: Suppress all vtordisps - /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial - /// structors - /// 2: Always insert vtordisps to support RTTI on partially constructed - /// objects - PragmaStack VtorDispStack; - PragmaStack AlignPackStack; - // The current #pragma align/pack values and locations at each #include. - struct AlignPackIncludeState { - AlignPackInfo CurrentValue; - SourceLocation CurrentPragmaLocation; - bool HasNonDefaultValue, ShouldWarnOnInclude; - }; - SmallVector AlignPackIncludeStack; - // Segment #pragmas. - PragmaStack DataSegStack; - PragmaStack BSSSegStack; - PragmaStack ConstSegStack; - PragmaStack CodeSegStack; + void emitAndClearUnusedLocalTypedefWarnings(); - // #pragma strict_gs_check. - PragmaStack StrictGuardStackCheckStack; + // Emit all deferred diagnostics. + void emitDeferredDiags(); - // This stack tracks the current state of Sema.CurFPFeatures. - PragmaStack FpPragmaStack; - FPOptionsOverride CurFPFeatureOverrides() { - FPOptionsOverride result; - if (!FpPragmaStack.hasValue()) { - result = FPOptionsOverride(); - } else { - result = FpPragmaStack.CurrentValue; - } - return result; - } - - // Saves the current floating-point pragma stack and clear it in this Sema. - class FpPragmaStackSaveRAII { - public: - FpPragmaStackSaveRAII(Sema &S) - : S(S), SavedStack(std::move(S.FpPragmaStack)) { - S.FpPragmaStack.Stack.clear(); - } - ~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); } - - private: - Sema &S; - PragmaStack SavedStack; + enum TUFragmentKind { + /// The global module fragment, between 'module;' and a module-declaration. + Global, + /// A normal translation unit fragment. For a non-module unit, this is the + /// entire translation unit. Otherwise, it runs from the module-declaration + /// to the private-module-fragment (if any) or the end of the TU (if not). + Normal, + /// The private module fragment, between 'module :private;' and the end of + /// the translation unit. + Private }; - void resetFPOptions(FPOptions FPO) { - CurFPFeatures = FPO; - FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts)); - } - - // RAII object to push / pop sentinel slots for all MS #pragma stacks. - // Actions should be performed only if we enter / exit a C++ method body. - class PragmaStackSentinelRAII { - public: - PragmaStackSentinelRAII(Sema &S, StringRef SlotLabel, bool ShouldAct); - ~PragmaStackSentinelRAII(); + void ActOnStartOfTranslationUnit(); + void ActOnEndOfTranslationUnit(); + void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind); - private: - Sema &S; - StringRef SlotLabel; - bool ShouldAct; - }; + Scope *getScopeForContext(DeclContext *Ctx); - /// A mapping that describes the nullability we've seen in each header file. - FileNullabilityMap NullabilityMap; + void PushFunctionScope(); + void PushBlockScope(Scope *BlockScope, BlockDecl *Block); + sema::LambdaScopeInfo *PushLambdaScope(); - /// Last section used with #pragma init_seg. - StringLiteral *CurInitSeg; - SourceLocation CurInitSegLoc; + /// This is used to inform Sema what the current TemplateParameterDepth + /// is during Parsing. Currently it is used to pass on the depth + /// when parsing generic lambda 'auto' parameters. + void RecordParsingTemplateParameterDepth(unsigned Depth); - /// Sections used with #pragma alloc_text. - llvm::StringMap> FunctionToSectionMap; + void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD, + RecordDecl *RD, CapturedRegionKind K, + unsigned OpenMPCaptureLevel = 0); - /// VisContext - Manages the stack for \#pragma GCC visibility. - void *VisContext; // Really a "PragmaVisStack*" + /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short + /// time after they've been popped. + class PoppedFunctionScopeDeleter { + Sema *Self; - /// This an attribute introduced by \#pragma clang attribute. - struct PragmaAttributeEntry { - SourceLocation Loc; - ParsedAttr *Attribute; - SmallVector MatchRules; - bool IsUsed; + public: + explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {} + void operator()(sema::FunctionScopeInfo *Scope) const; }; - /// A push'd group of PragmaAttributeEntries. - struct PragmaAttributeGroup { - /// The location of the push attribute. - SourceLocation Loc; - /// The namespace of this push group. - const IdentifierInfo *Namespace; - SmallVector Entries; - }; + using PoppedFunctionScopePtr = + std::unique_ptr; - SmallVector PragmaAttributeStack; + PoppedFunctionScopePtr + PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr, + const Decl *D = nullptr, + QualType BlockType = QualType()); - /// The declaration that is currently receiving an attribute from the - /// #pragma attribute stack. - const Decl *PragmaAttributeCurrentTargetDecl; + sema::FunctionScopeInfo *getEnclosingFunction() const; - /// This represents the last location of a "#pragma clang optimize off" - /// directive if such a directive has not been closed by an "on" yet. If - /// optimizations are currently "on", this is set to an invalid location. - SourceLocation OptimizeOffPragmaLocation; + void setFunctionHasBranchIntoScope(); + void setFunctionHasBranchProtectedScope(); + void setFunctionHasIndirectGoto(); + void setFunctionHasMustTail(); - /// The "on" or "off" argument passed by \#pragma optimize, that denotes - /// whether the optimizations in the list passed to the pragma should be - /// turned off or on. This boolean is true by default because command line - /// options are honored when `#pragma optimize("", on)`. - /// (i.e. `ModifyFnAttributeMSPragmaOptimze()` does nothing) - bool MSPragmaOptimizeIsOn = true; + void PushCompoundScope(bool IsStmtExpr); + void PopCompoundScope(); - /// Set of no-builtin functions listed by \#pragma function. - llvm::SmallSetVector MSFunctionNoBuiltins; + bool hasAnyUnrecoverableErrorsInThisFunction() const; - /// Flag indicating if Sema is building a recovery call expression. - /// - /// This flag is used to avoid building recovery call expressions - /// if Sema is already doing so, which would cause infinite recursions. - bool IsBuildingRecoveryCallExpr; + /// Retrieve the current block, if any. + sema::BlockScopeInfo *getCurBlock(); - /// Used to control the generation of ExprWithCleanups. - CleanupInfo Cleanup; + /// Get the innermost lambda enclosing the current location, if any. This + /// looks through intervening non-lambda scopes such as local functions and + /// blocks. + sema::LambdaScopeInfo *getEnclosingLambda() const; - /// ExprCleanupObjects - This is the stack of objects requiring - /// cleanup that are created by the current full expression. - SmallVector ExprCleanupObjects; + /// Retrieve the current lambda scope info, if any. + /// \param IgnoreNonLambdaCapturingScope true if should find the top-most + /// lambda scope info ignoring all inner capturing scopes that are not + /// lambda scopes. + sema::LambdaScopeInfo * + getCurLambda(bool IgnoreNonLambdaCapturingScope = false); - /// Store a set of either DeclRefExprs or MemberExprs that contain a reference - /// to a variable (constant) that may or may not be odr-used in this Expr, and - /// we won't know until all lvalue-to-rvalue and discarded value conversions - /// have been applied to all subexpressions of the enclosing full expression. - /// This is cleared at the end of each full expression. - using MaybeODRUseExprSet = llvm::SmallSetVector; - MaybeODRUseExprSet MaybeODRUseExprs; + /// Retrieve the current generic lambda info, if any. + sema::LambdaScopeInfo *getCurGenericLambda(); - std::unique_ptr CachedFunctionScope; + /// Retrieve the current captured region, if any. + sema::CapturedRegionScopeInfo *getCurCapturedRegion(); - /// Stack containing information about each of the nested - /// function, block, and method scopes that are currently active. - SmallVector FunctionScopes; + void ActOnComment(SourceRange Comment); - /// The index of the first FunctionScope that corresponds to the current - /// context. - unsigned FunctionScopesStart = 0; + /// Retrieve the parser's current scope. + /// + /// This routine must only be used when it is certain that semantic analysis + /// and the parser are in precisely the same context, which is not the case + /// when, e.g., we are performing any kind of template instantiation. + /// Therefore, the only safe places to use this scope are in the parser + /// itself and in routines directly invoked from the parser and *never* from + /// template substitution or instantiation. + Scope *getCurScope() const { return CurScope; } - /// Track the number of currently active capturing scopes. - unsigned CapturingFunctionScopes = 0; + IdentifierInfo *getSuperIdentifier() const; - ArrayRef getFunctionScopes() const { - return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart, - FunctionScopes.end()); + DeclContext *getCurLexicalContext() const { + return OriginalLexicalContext ? OriginalLexicalContext : CurContext; } - /// Stack containing information needed when in C++2a an 'auto' is encountered - /// in a function declaration parameter type specifier in order to invent a - /// corresponding template parameter in the enclosing abbreviated function - /// template. This information is also present in LambdaScopeInfo, stored in - /// the FunctionScopes stack. - SmallVector InventedParameterInfos; + SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, + const FunctionDecl *FD = nullptr); + SemaDiagnosticBuilder targetDiag(SourceLocation Loc, + const PartialDiagnostic &PD, + const FunctionDecl *FD = nullptr) { + return targetDiag(Loc, PD.getDiagID(), FD) << PD; + } - /// The index of the first InventedParameterInfo that refers to the current - /// context. - unsigned InventedParameterInfosStart = 0; + /// Check if the type is allowed to be used for the current target. + void checkTypeSupport(QualType Ty, SourceLocation Loc, + ValueDecl *D = nullptr); - ArrayRef getInventedParameterInfos() const { - return llvm::ArrayRef(InventedParameterInfos.begin() + - InventedParameterInfosStart, - InventedParameterInfos.end()); - } + /// The kind of conversion being performed. + enum CheckedConversionKind { + /// An implicit conversion. + CCK_ImplicitConversion, + /// A C-style cast. + CCK_CStyleCast, + /// A functional-style cast. + CCK_FunctionalCast, + /// A cast other than a C-style cast. + CCK_OtherCast, + /// A conversion for an operand of a builtin overloaded operator. + CCK_ForBuiltinOverloadedOp + }; - typedef LazyVector - ExtVectorDeclsType; + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit + /// cast. If there is already an implicit cast, merge into the existing one. + /// If isLvalue, the result of the cast is an lvalue. + ExprResult + ImpCastExprToType(Expr *E, QualType Type, CastKind CK, + ExprValueKind VK = VK_PRValue, + const CXXCastPath *BasePath = nullptr, + CheckedConversionKind CCK = CCK_ImplicitConversion); - /// ExtVectorDecls - This is a list all the extended vector types. This allows - /// us to associate a raw vector type with one of the ext_vector type names. - /// This is only necessary for issuing pretty diagnostics. - ExtVectorDeclsType ExtVectorDecls; + /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding + /// to the conversion from scalar type ScalarTy to the Boolean type. + static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy); - /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. - std::unique_ptr FieldCollector; + /// If \p AllowLambda is true, treat lambda as function. + DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const; - typedef llvm::SmallSetVector NamedDeclSetType; + /// Returns a pointer to the innermost enclosing function, or nullptr if the + /// current context is not inside a function. If \p AllowLambda is true, + /// this can return the call operator of an enclosing lambda, otherwise + /// lambdas are skipped when looking for an enclosing function. + FunctionDecl *getCurFunctionDecl(bool AllowLambda = false) const; - /// Set containing all declared private fields that are not used. - NamedDeclSetType UnusedPrivateFields; + /// getCurMethodDecl - If inside of a method body, this returns a pointer to + /// the method decl for the method being parsed. If we're currently + /// in a 'block', this returns the containing context. + ObjCMethodDecl *getCurMethodDecl(); - /// Set containing all typedefs that are likely unused. - llvm::SmallSetVector - UnusedLocalTypedefNameCandidates; + /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method + /// or C function we're in, otherwise return null. If we're currently + /// in a 'block', this returns the containing context. + NamedDecl *getCurFunctionOrMethodDecl() const; - /// Delete-expressions to be analyzed at the end of translation unit + /// Warn if we're implicitly casting from a _Nullable pointer type to a + /// _Nonnull one. + void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, + SourceLocation Loc); + + /// Warn when implicitly casting 0 to nullptr. + void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E); + + bool makeUnavailableInSystemHeader(SourceLocation loc, + UnavailableAttr::ImplicitReason reason); + + /// Retrieve a suitable printing policy for diagnostics. + PrintingPolicy getPrintingPolicy() const { + return getPrintingPolicy(Context, PP); + } + + /// Retrieve a suitable printing policy for diagnostics. + static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx, + const Preprocessor &PP); + + /// Scope actions. + void ActOnTranslationUnitScope(Scope *S); + + /// Determine whether \param D is function like (function or function + /// template) for parsing. + bool isDeclaratorFunctionLike(Declarator &D); + + /// The maximum alignment, same as in llvm::Value. We duplicate them here + /// because that allows us not to duplicate the constants in clang code, + /// which we must to since we can't directly use the llvm constants. + /// The value is verified against llvm here: lib/CodeGen/CGDecl.cpp /// - /// This list contains class members, and locations of delete-expressions - /// that could not be proven as to whether they mismatch with new-expression - /// used in initializer of the field. - typedef std::pair DeleteExprLoc; - typedef llvm::SmallVector DeleteLocs; - llvm::MapVector DeleteExprs; + /// This is the greatest alignment value supported by load, store, and alloca + /// instructions, and global values. + static const unsigned MaxAlignmentExponent = 32; + static const uint64_t MaximumAlignment = 1ull << MaxAlignmentExponent; - typedef llvm::SmallPtrSet RecordDeclSetTy; + /// Flag indicating whether or not to collect detailed statistics. + bool CollectStats; - /// PureVirtualClassDiagSet - a set of class declarations which we have - /// emitted a list of pure virtual functions. Used to prevent emitting the - /// same list more than once. - std::unique_ptr PureVirtualClassDiagSet; + std::unique_ptr CachedFunctionScope; - /// ParsingInitForAutoVars - a set of declarations with auto types for which - /// we are currently parsing the initializer. - llvm::SmallPtrSet ParsingInitForAutoVars; + /// Stack containing information about each of the nested + /// function, block, and method scopes that are currently active. + SmallVector FunctionScopes; - /// Look for a locally scoped extern "C" declaration by the given name. - NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name); + /// The index of the first FunctionScope that corresponds to the current + /// context. + unsigned FunctionScopesStart = 0; - typedef LazyVector - TentativeDefinitionsType; + /// Track the number of currently active capturing scopes. + unsigned CapturingFunctionScopes = 0; - /// All the tentative definitions encountered in the TU. - TentativeDefinitionsType TentativeDefinitions; + llvm::BumpPtrAllocator BumpAlloc; - /// All the external declarations encoutered and used in the TU. - SmallVector ExternalDeclarations; + /// The kind of translation unit we are processing. + /// + /// When we're processing a complete translation unit, Sema will perform + /// end-of-translation-unit semantic tasks (such as creating + /// initializers for tentative definitions in C) once parsing has + /// completed. Modules and precompiled headers perform different kinds of + /// checks. + const TranslationUnitKind TUKind; - typedef LazyVector - UnusedFileScopedDeclsType; + /// Translation Unit Scope - useful to Objective-C actions that need + /// to lookup file scope declarations in the "ordinary" C decl namespace. + /// For example, user-defined classes, built-in "id" type, etc. + Scope *TUScope; - /// The set of file scoped decls seen so far that have not been used - /// and must warn if not used. Only contains the first declaration. - UnusedFileScopedDeclsType UnusedFileScopedDecls; + bool WarnedStackExhausted = false; - typedef LazyVector - DelegatingCtorDeclsType; + void incrementMSManglingNumber() const { + return CurScope->incrementMSManglingNumber(); + } - /// All the delegating constructors seen so far in the file, used for - /// cycle detection at the end of the TU. - DelegatingCtorDeclsType DelegatingCtorDecls; + /// Try to recover by turning the given expression into a + /// call. Returns true if recovery was attempted or an error was + /// emitted; this may also leave the ExprResult invalid. + bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, + bool ForceComplain = false, + bool (*IsPlausibleResult)(QualType) = nullptr); - /// All the overriding functions seen during a class definition - /// that had their exception spec checks delayed, plus the overridden - /// function. - SmallVector, 2> - DelayedOverridingExceptionSpecChecks; + /// Figure out if an expression could be turned into a call. + bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, + UnresolvedSetImpl &NonTemplateOverloads); - /// All the function redeclarations seen during a class definition that had - /// their exception spec checks delayed, plus the prior declaration they - /// should be checked against. Except during error recovery, the new decl - /// should always be a friend declaration, as that's the only valid way to - /// redeclare a special member before its class is complete. - SmallVector, 2> - DelayedEquivalentExceptionSpecChecks; + typedef OpaquePtr DeclGroupPtrTy; + typedef OpaquePtr TemplateTy; + typedef OpaquePtr TypeTy; - typedef llvm::MapVector> - LateParsedTemplateMapT; - LateParsedTemplateMapT LateParsedTemplateMap; + OpenCLOptions OpenCLFeatures; + FPOptions CurFPFeatures; + + const LangOptions &LangOpts; + Preprocessor &PP; + ASTContext &Context; + ASTConsumer &Consumer; + DiagnosticsEngine &Diags; + SourceManager &SourceMgr; + api_notes::APINotesManager APINotes; + + /// A RAII object to enter scope of a compound statement. + class CompoundScopeRAII { + public: + CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) { + S.ActOnStartOfCompoundStmt(IsStmtExpr); + } + + ~CompoundScopeRAII() { S.ActOnFinishOfCompoundStmt(); } + + private: + Sema &S; + }; + + /// An RAII helper that pops function a function scope on exit. + struct FunctionScopeRAII { + Sema &S; + bool Active; + FunctionScopeRAII(Sema &S) : S(S), Active(true) {} + ~FunctionScopeRAII() { + if (Active) + S.PopFunctionScopeInfo(); + } + void disable() { Active = false; } + }; + + /// Build a partial diagnostic. + PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h + + sema::FunctionScopeInfo *getCurFunction() const { + return FunctionScopes.empty() ? nullptr : FunctionScopes.back(); + } + + /// Worker object for performing CFG-based warnings. + sema::AnalysisBasedWarnings AnalysisWarnings; + threadSafety::BeforeSet *ThreadSafetyDeclCache; /// Callback to the parser to parse templated functions when needed. typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT); @@ -1016,8 +1077,7 @@ class Sema final { void *OpaqueParser; void SetLateTemplateParser(LateTemplateParserCB *LTP, - LateTemplateParserCleanupCB *LTPCleanup, - void *P) { + LateTemplateParserCleanupCB *LTPCleanup, void *P) { LateTemplateParser = LTP; LateTemplateParserCleanup = LTPCleanup; OpaqueParser = P; @@ -1027,6 +1087,14 @@ class Sema final { std::function ParseTypeFromStringCallback; + /// VAListTagName - The declaration name corresponding to __va_list_tag. + /// This is used as part of a hack to omit that class from ADL results. + DeclarationName VAListTagName; + + /// Is the last error level diagnostic immediate. This is used to determined + /// whether the next info diagnostic should be immediate. + bool IsLastErrorImmediate = true; + class DelayedDiagnostics; class DelayedDiagnosticsState { @@ -1053,9 +1121,7 @@ class Sema final { bool shouldDelayDiagnostics() { return CurPool != nullptr; } /// Returns the current delayed-diagnostics pool. - sema::DelayedDiagnosticPool *getCurrentPool() const { - return CurPool; - } + sema::DelayedDiagnosticPool *getCurrentPool() const { return CurPool; } /// Enter a new scope. Access and deprecation diagnostics will be /// collected in this pool. @@ -1089,1657 +1155,1626 @@ class Sema final { } } DelayedDiagnostics; - enum CUDAFunctionTarget { - CFT_Device, - CFT_Global, - CFT_Host, - CFT_HostDevice, - CFT_InvalidTarget - }; + ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { + return DelayedDiagnostics.push(pool); + } - /// A RAII object to temporarily push a declaration context. - class ContextRAII { - private: - Sema &S; - DeclContext *SavedContext; - ProcessingContextState SavedContextState; - QualType SavedCXXThisTypeOverride; - unsigned SavedFunctionScopesStart; - unsigned SavedInventedParameterInfosStart; + /// CurContext - This is the current declaration context of parsing. + DeclContext *CurContext; - public: - ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true) - : S(S), SavedContext(S.CurContext), - SavedContextState(S.DelayedDiagnostics.pushUndelayed()), - SavedCXXThisTypeOverride(S.CXXThisTypeOverride), - SavedFunctionScopesStart(S.FunctionScopesStart), - SavedInventedParameterInfosStart(S.InventedParameterInfosStart) - { - assert(ContextToPush && "pushing null context"); - S.CurContext = ContextToPush; - if (NewThisContext) - S.CXXThisTypeOverride = QualType(); - // Any saved FunctionScopes do not refer to this context. - S.FunctionScopesStart = S.FunctionScopes.size(); - S.InventedParameterInfosStart = S.InventedParameterInfos.size(); - } +protected: + friend class Parser; + friend class InitializationSequence; + friend class ASTReader; + friend class ASTDeclReader; + friend class ASTWriter; - void pop() { - if (!SavedContext) return; - S.CurContext = SavedContext; - S.DelayedDiagnostics.popUndelayed(SavedContextState); - S.CXXThisTypeOverride = SavedCXXThisTypeOverride; - S.FunctionScopesStart = SavedFunctionScopesStart; - S.InventedParameterInfosStart = SavedInventedParameterInfosStart; - SavedContext = nullptr; - } +private: + std::optional> CachedDarwinSDKInfo; + bool WarnedDarwinSDKInfoMissing = false; - ~ContextRAII() { - pop(); - } - }; + Sema(const Sema &) = delete; + void operator=(const Sema &) = delete; - /// RAII object to handle the state changes required to synthesize - /// a function body. - class SynthesizedFunctionScope { - Sema &S; - Sema::ContextRAII SavedContext; - bool PushedCodeSynthesisContext = false; + /// Source of additional semantic information. + IntrusiveRefCntPtr ExternalSource; - public: - SynthesizedFunctionScope(Sema &S, DeclContext *DC) - : S(S), SavedContext(S, DC) { - auto *FD = dyn_cast(DC); - S.PushFunctionScope(); - S.PushExpressionEvaluationContext( - (FD && FD->isConsteval()) - ? ExpressionEvaluationContext::ImmediateFunctionContext - : ExpressionEvaluationContext::PotentiallyEvaluated); - if (FD) { - FD->setWillHaveBody(true); - S.ExprEvalContexts.back().InImmediateFunctionContext = - FD->isImmediateFunction() || - S.ExprEvalContexts[S.ExprEvalContexts.size() - 2] - .isConstantEvaluated(); - S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext = - S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating(); - } else - assert(isa(DC)); - } + /// The handler for the FileChanged preprocessor events. + /// + /// Used for diagnostics that implement custom semantic analysis for #include + /// directives, like -Wpragma-pack. + sema::SemaPPCallbacks *SemaPPCallbackHandler; - void addContextNote(SourceLocation UseLoc) { - assert(!PushedCodeSynthesisContext); + /// The parser's current scope. + /// + /// The parser maintains this state here. + Scope *CurScope; - Sema::CodeSynthesisContext Ctx; - Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction; - Ctx.PointOfInstantiation = UseLoc; - Ctx.Entity = cast(S.CurContext); - S.pushCodeSynthesisContext(Ctx); + mutable IdentifierInfo *Ident_super; - PushedCodeSynthesisContext = true; - } + ///@} - ~SynthesizedFunctionScope() { - if (PushedCodeSynthesisContext) - S.popCodeSynthesisContext(); - if (auto *FD = dyn_cast(S.CurContext)) { - FD->setWillHaveBody(false); - S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction()); - } - S.PopExpressionEvaluationContext(); - S.PopFunctionScopeInfo(); - } + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name C++ Access Control + /// Implementations are in SemaAccess.cpp + ///@{ + +public: + enum AccessResult { + AR_accessible, + AR_inaccessible, + AR_dependent, + AR_delayed }; - /// WeakUndeclaredIdentifiers - Identifiers contained in \#pragma weak before - /// declared. Rare. May alias another identifier, declared or undeclared. - /// - /// For aliases, the target identifier is used as a key for eventual - /// processing when the target is declared. For the single-identifier form, - /// the sole identifier is used as the key. Each entry is a `SetVector` - /// (ordered by parse order) of aliases (identified by the alias name) in case - /// of multiple aliases to the same undeclared identifier. - llvm::MapVector< - IdentifierInfo *, - llvm::SetVector< - WeakInfo, llvm::SmallVector, - llvm::SmallDenseSet>> - WeakUndeclaredIdentifiers; + bool SetMemberAccessSpecifier(NamedDecl *MemberDecl, + NamedDecl *PrevMemberDecl, + AccessSpecifier LexicalAS); - /// ExtnameUndeclaredIdentifiers - Identifiers contained in - /// \#pragma redefine_extname before declared. Used in Solaris system headers - /// to define functions that occur in multiple standards to call the version - /// in the currently selected standard. - llvm::DenseMap ExtnameUndeclaredIdentifiers; + AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + DeclAccessPair FoundDecl); + AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + DeclAccessPair FoundDecl); + AccessResult CheckAllocationAccess(SourceLocation OperatorLoc, + SourceRange PlacementRange, + CXXRecordDecl *NamingClass, + DeclAccessPair FoundDecl, + bool Diagnose = true); + AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, + DeclAccessPair FoundDecl, + const InitializedEntity &Entity, + bool IsCopyBindingRefToTemp = false); + AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, + DeclAccessPair FoundDecl, + const InitializedEntity &Entity, + const PartialDiagnostic &PDiag); + AccessResult CheckDestructorAccess(SourceLocation Loc, + CXXDestructorDecl *Dtor, + const PartialDiagnostic &PDiag, + QualType objectType = QualType()); + AccessResult CheckFriendAccess(NamedDecl *D); + AccessResult CheckMemberAccess(SourceLocation UseLoc, + CXXRecordDecl *NamingClass, + DeclAccessPair Found); + AccessResult + CheckStructuredBindingMemberAccess(SourceLocation UseLoc, + CXXRecordDecl *DecomposedClass, + DeclAccessPair Field); + AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, + const SourceRange &, + DeclAccessPair FoundDecl); + AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, + Expr *ArgExpr, + DeclAccessPair FoundDecl); + AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, + ArrayRef ArgExprs, + DeclAccessPair FoundDecl); + AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr, + DeclAccessPair FoundDecl); + AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, + QualType Derived, const CXXBasePath &Path, + unsigned DiagID, bool ForceCheck = false, + bool ForceUnprivileged = false); + void CheckLookupAccess(const LookupResult &R); + bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass, + QualType BaseType); + bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, + DeclAccessPair Found, QualType ObjectType, + SourceLocation Loc, + const PartialDiagnostic &Diag); + bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, + DeclAccessPair Found, + QualType ObjectType) { + return isMemberAccessibleForDeletion(NamingClass, Found, ObjectType, + SourceLocation(), PDiag()); + } + void HandleDependentAccessCheck( + const DependentDiagnostic &DD, + const MultiLevelTemplateArgumentList &TemplateArgs); + void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); - /// Load weak undeclared identifiers from the external source. - void LoadExternalWeakUndeclaredIdentifiers(); + ///@} - /// WeakTopLevelDecl - Translation-unit scoped declarations generated by - /// \#pragma weak during processing of other Decls. - /// I couldn't figure out a clean way to generate these in-line, so - /// we store them here and handle separately -- which is a hack. - /// It would be best to refactor this. - SmallVector WeakTopLevelDecl; + // + // + // ------------------------------------------------------------------------- + // + // - IdentifierResolver IdResolver; + /// \name Attributes + /// Implementations are in SemaAttr.cpp + ///@{ - /// Translation Unit Scope - useful to Objective-C actions that need - /// to lookup file scope declarations in the "ordinary" C decl namespace. - /// For example, user-defined classes, built-in "id" type, etc. - Scope *TUScope; +public: + /// Controls member pointer representation format under the MS ABI. + LangOptions::PragmaMSPointersToMembersKind + MSPointerToMemberRepresentationMethod; - /// The C++ "std" namespace, where the standard library resides. - LazyDeclPtr StdNamespace; + bool MSStructPragmaOn; // True when \#pragma ms_struct on - /// The C++ "std::bad_alloc" class, which is defined by the C++ - /// standard library. - LazyDeclPtr StdBadAlloc; + /// Source location for newly created implicit MSInheritanceAttrs + SourceLocation ImplicitMSInheritanceAttrLoc; - /// The C++ "std::align_val_t" enum class, which is defined by the C++ - /// standard library. - LazyDeclPtr StdAlignValT; + /// pragma clang section kind + enum PragmaClangSectionKind { + PCSK_Invalid = 0, + PCSK_BSS = 1, + PCSK_Data = 2, + PCSK_Rodata = 3, + PCSK_Text = 4, + PCSK_Relro = 5 + }; - /// The C++ "std::initializer_list" template, which is defined in - /// \. - ClassTemplateDecl *StdInitializerList; + enum PragmaClangSectionAction { PCSA_Set = 0, PCSA_Clear = 1 }; - /// The C++ "std::coroutine_traits" template, which is defined in - /// \ - ClassTemplateDecl *StdCoroutineTraitsCache; + struct PragmaClangSection { + std::string SectionName; + bool Valid = false; + SourceLocation PragmaLocation; + }; - /// The C++ "type_info" declaration, which is defined in \. - RecordDecl *CXXTypeInfoDecl; + PragmaClangSection PragmaClangBSSSection; + PragmaClangSection PragmaClangDataSection; + PragmaClangSection PragmaClangRodataSection; + PragmaClangSection PragmaClangRelroSection; + PragmaClangSection PragmaClangTextSection; - /// The C++ "std::source_location::__impl" struct, defined in - /// \. - RecordDecl *StdSourceLocationImplDecl; + enum PragmaMsStackAction { + PSK_Reset = 0x0, // #pragma () + PSK_Set = 0x1, // #pragma (value) + PSK_Push = 0x2, // #pragma (push[, id]) + PSK_Pop = 0x4, // #pragma (pop[, id]) + PSK_Show = 0x8, // #pragma (show) -- only for "pack"! + PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value) + PSK_Pop_Set = PSK_Pop | PSK_Set, // #pragma (pop[, id], value) + }; - /// Caches identifiers/selectors for NSFoundation APIs. - std::unique_ptr NSAPIObj; + struct PragmaPackInfo { + PragmaMsStackAction Action; + StringRef SlotLabel; + Token Alignment; + }; - /// The declaration of the Objective-C NSNumber class. - ObjCInterfaceDecl *NSNumberDecl; + // #pragma pack and align. + class AlignPackInfo { + public: + // `Native` represents default align mode, which may vary based on the + // platform. + enum Mode : unsigned char { Native, Natural, Packed, Mac68k }; - /// The declaration of the Objective-C NSValue class. - ObjCInterfaceDecl *NSValueDecl; + // #pragma pack info constructor + AlignPackInfo(AlignPackInfo::Mode M, unsigned Num, bool IsXL) + : PackAttr(true), AlignMode(M), PackNumber(Num), XLStack(IsXL) { + assert(Num == PackNumber && "The pack number has been truncated."); + } - /// Pointer to NSNumber type (NSNumber *). - QualType NSNumberPointer; + // #pragma align info constructor + AlignPackInfo(AlignPackInfo::Mode M, bool IsXL) + : PackAttr(false), AlignMode(M), + PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {} - /// Pointer to NSValue type (NSValue *). - QualType NSValuePointer; + explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {} - /// The Objective-C NSNumber methods used to create NSNumber literals. - ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; + AlignPackInfo() : AlignPackInfo(Native, false) {} - /// The declaration of the Objective-C NSString class. - ObjCInterfaceDecl *NSStringDecl; + // When a AlignPackInfo itself cannot be used, this returns an 32-bit + // integer encoding for it. This should only be passed to + // AlignPackInfo::getFromRawEncoding, it should not be inspected directly. + static uint32_t getRawEncoding(const AlignPackInfo &Info) { + std::uint32_t Encoding{}; + if (Info.IsXLStack()) + Encoding |= IsXLMask; - /// Pointer to NSString type (NSString *). - QualType NSStringPointer; + Encoding |= static_cast(Info.getAlignMode()) << 1; - /// The declaration of the stringWithUTF8String: method. - ObjCMethodDecl *StringWithUTF8StringMethod; + if (Info.IsPackAttr()) + Encoding |= PackAttrMask; - /// The declaration of the valueWithBytes:objCType: method. - ObjCMethodDecl *ValueWithBytesObjCTypeMethod; + Encoding |= static_cast(Info.getPackNumber()) << 4; - /// The declaration of the Objective-C NSArray class. - ObjCInterfaceDecl *NSArrayDecl; + return Encoding; + } - /// The declaration of the arrayWithObjects:count: method. - ObjCMethodDecl *ArrayWithObjectsMethod; + static AlignPackInfo getFromRawEncoding(unsigned Encoding) { + bool IsXL = static_cast(Encoding & IsXLMask); + AlignPackInfo::Mode M = + static_cast((Encoding & AlignModeMask) >> 1); + int PackNumber = (Encoding & PackNumMask) >> 4; - /// The declaration of the Objective-C NSDictionary class. - ObjCInterfaceDecl *NSDictionaryDecl; + if (Encoding & PackAttrMask) + return AlignPackInfo(M, PackNumber, IsXL); - /// The declaration of the dictionaryWithObjects:forKeys:count: method. - ObjCMethodDecl *DictionaryWithObjectsMethod; + return AlignPackInfo(M, IsXL); + } - /// id type. - QualType QIDNSCopying; + bool IsPackAttr() const { return PackAttr; } - /// will hold 'respondsToSelector:' - Selector RespondsToSelectorSel; + bool IsAlignAttr() const { return !PackAttr; } - /// A flag to remember whether the implicit forms of operator new and delete - /// have been declared. - bool GlobalNewDeleteDeclared; + Mode getAlignMode() const { return AlignMode; } - /// Describes how the expressions currently being parsed are - /// evaluated at run-time, if at all. - enum class ExpressionEvaluationContext { - /// The current expression and its subexpressions occur within an - /// unevaluated operand (C++11 [expr]p7), such as the subexpression of - /// \c sizeof, where the type of the expression may be significant but - /// no code will be generated to evaluate the value of the expression at - /// run time. - Unevaluated, + unsigned getPackNumber() const { return PackNumber; } - /// The current expression occurs within a braced-init-list within - /// an unevaluated operand. This is mostly like a regular unevaluated - /// context, except that we still instantiate constexpr functions that are - /// referenced here so that we can perform narrowing checks correctly. - UnevaluatedList, - - /// The current expression occurs within a discarded statement. - /// This behaves largely similarly to an unevaluated operand in preventing - /// definitions from being required, but not in other ways. - DiscardedStatement, + bool IsPackSet() const { + // #pragma align, #pragma pack(), and #pragma pack(0) do not set the pack + // attriute on a decl. + return PackNumber != UninitPackVal && PackNumber != 0; + } - /// The current expression occurs within an unevaluated - /// operand that unconditionally permits abstract references to - /// fields, such as a SIZE operator in MS-style inline assembly. - UnevaluatedAbstract, + bool IsXLStack() const { return XLStack; } - /// The current context is "potentially evaluated" in C++11 terms, - /// but the expression is evaluated at compile-time (like the values of - /// cases in a switch statement). - ConstantEvaluated, + bool operator==(const AlignPackInfo &Info) const { + return std::tie(AlignMode, PackNumber, PackAttr, XLStack) == + std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr, + Info.XLStack); + } - /// In addition of being constant evaluated, the current expression - /// occurs in an immediate function context - either a consteval function - /// or a consteval if statement. - ImmediateFunctionContext, + bool operator!=(const AlignPackInfo &Info) const { + return !(*this == Info); + } - /// The current expression is potentially evaluated at run time, - /// which means that code may be generated to evaluate the value of the - /// expression at run time. - PotentiallyEvaluated, + private: + /// \brief True if this is a pragma pack attribute, + /// not a pragma align attribute. + bool PackAttr; - /// The current expression is potentially evaluated, but any - /// declarations referenced inside that expression are only used if - /// in fact the current expression is used. - /// - /// This value is used when parsing default function arguments, for which - /// we would like to provide diagnostics (e.g., passing non-POD arguments - /// through varargs) but do not want to mark declarations as "referenced" - /// until the default argument is used. - PotentiallyEvaluatedIfUsed - }; + /// \brief The alignment mode that is in effect. + Mode AlignMode; - using ImmediateInvocationCandidate = llvm::PointerIntPair; + /// \brief The pack number of the stack. + unsigned char PackNumber; - /// Data structure used to record current or nested - /// expression evaluation contexts. - struct ExpressionEvaluationContextRecord { - /// The expression evaluation context. - ExpressionEvaluationContext Context; + /// \brief True if it is a XL #pragma align/pack stack. + bool XLStack; - /// Whether the enclosing context needed a cleanup. - CleanupInfo ParentCleanup; + /// \brief Uninitialized pack value. + static constexpr unsigned char UninitPackVal = -1; - /// The number of active cleanup objects when we entered - /// this expression evaluation context. - unsigned NumCleanupObjects; + // Masks to encode and decode an AlignPackInfo. + static constexpr uint32_t IsXLMask{0x0000'0001}; + static constexpr uint32_t AlignModeMask{0x0000'0006}; + static constexpr uint32_t PackAttrMask{0x00000'0008}; + static constexpr uint32_t PackNumMask{0x0000'01F0}; + }; - /// The number of typos encountered during this expression evaluation - /// context (i.e. the number of TypoExprs created). - unsigned NumTypos; + template struct PragmaStack { + struct Slot { + llvm::StringRef StackSlotLabel; + ValueType Value; + SourceLocation PragmaLocation; + SourceLocation PragmaPushLocation; + Slot(llvm::StringRef StackSlotLabel, ValueType Value, + SourceLocation PragmaLocation, SourceLocation PragmaPushLocation) + : StackSlotLabel(StackSlotLabel), Value(Value), + PragmaLocation(PragmaLocation), + PragmaPushLocation(PragmaPushLocation) {} + }; - MaybeODRUseExprSet SavedMaybeODRUseExprs; + void Act(SourceLocation PragmaLocation, PragmaMsStackAction Action, + llvm::StringRef StackSlotLabel, ValueType Value) { + if (Action == PSK_Reset) { + CurrentValue = DefaultValue; + CurrentPragmaLocation = PragmaLocation; + return; + } + if (Action & PSK_Push) + Stack.emplace_back(StackSlotLabel, CurrentValue, CurrentPragmaLocation, + PragmaLocation); + else if (Action & PSK_Pop) { + if (!StackSlotLabel.empty()) { + // If we've got a label, try to find it and jump there. + auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { + return x.StackSlotLabel == StackSlotLabel; + }); + // If we found the label so pop from there. + if (I != Stack.rend()) { + CurrentValue = I->Value; + CurrentPragmaLocation = I->PragmaLocation; + Stack.erase(std::prev(I.base()), Stack.end()); + } + } else if (!Stack.empty()) { + // We do not have a label, just pop the last entry. + CurrentValue = Stack.back().Value; + CurrentPragmaLocation = Stack.back().PragmaLocation; + Stack.pop_back(); + } + } + if (Action & PSK_Set) { + CurrentValue = Value; + CurrentPragmaLocation = PragmaLocation; + } + } - /// The lambdas that are present within this context, if it - /// is indeed an unevaluated context. - SmallVector Lambdas; + // MSVC seems to add artificial slots to #pragma stacks on entering a C++ + // method body to restore the stacks on exit, so it works like this: + // + // struct S { + // #pragma (push, InternalPragmaSlot, ) + // void Method {} + // #pragma (pop, InternalPragmaSlot) + // }; + // + // It works even with #pragma vtordisp, although MSVC doesn't support + // #pragma vtordisp(push [, id], n) + // syntax. + // + // Push / pop a named sentinel slot. + void SentinelAction(PragmaMsStackAction Action, StringRef Label) { + assert((Action == PSK_Push || Action == PSK_Pop) && + "Can only push / pop #pragma stack sentinels!"); + Act(CurrentPragmaLocation, Action, Label, CurrentValue); + } - /// The declaration that provides context for lambda expressions - /// and block literals if the normal declaration context does not - /// suffice, e.g., in a default function argument. - Decl *ManglingContextDecl; + // Constructors. + explicit PragmaStack(const ValueType &Default) + : DefaultValue(Default), CurrentValue(Default) {} - /// If we are processing a decltype type, a set of call expressions - /// for which we have deferred checking the completeness of the return type. - SmallVector DelayedDecltypeCalls; + bool hasValue() const { return CurrentValue != DefaultValue; } - /// If we are processing a decltype type, a set of temporary binding - /// expressions for which we have deferred checking the destructor. - SmallVector DelayedDecltypeBinds; + SmallVector Stack; + ValueType DefaultValue; // Value used for PSK_Reset action. + ValueType CurrentValue; + SourceLocation CurrentPragmaLocation; + }; + // FIXME: We should serialize / deserialize these if they occur in a PCH (but + // we shouldn't do so if they're in a module). - llvm::SmallPtrSet PossibleDerefs; + /// Whether to insert vtordisps prior to virtual bases in the Microsoft + /// C++ ABI. Possible values are 0, 1, and 2, which mean: + /// + /// 0: Suppress all vtordisps + /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial + /// structors + /// 2: Always insert vtordisps to support RTTI on partially constructed + /// objects + PragmaStack VtorDispStack; + PragmaStack AlignPackStack; + // The current #pragma align/pack values and locations at each #include. + struct AlignPackIncludeState { + AlignPackInfo CurrentValue; + SourceLocation CurrentPragmaLocation; + bool HasNonDefaultValue, ShouldWarnOnInclude; + }; + SmallVector AlignPackIncludeStack; + // Segment #pragmas. + PragmaStack DataSegStack; + PragmaStack BSSSegStack; + PragmaStack ConstSegStack; + PragmaStack CodeSegStack; - /// Expressions appearing as the LHS of a volatile assignment in this - /// context. We produce a warning for these when popping the context if - /// they are not discarded-value expressions nor unevaluated operands. - SmallVector VolatileAssignmentLHSs; + // #pragma strict_gs_check. + PragmaStack StrictGuardStackCheckStack; - /// Set of candidates for starting an immediate invocation. - llvm::SmallVector ImmediateInvocationCandidates; + // This stack tracks the current state of Sema.CurFPFeatures. + PragmaStack FpPragmaStack; + FPOptionsOverride CurFPFeatureOverrides() { + FPOptionsOverride result; + if (!FpPragmaStack.hasValue()) { + result = FPOptionsOverride(); + } else { + result = FpPragmaStack.CurrentValue; + } + return result; + } - /// Set of DeclRefExprs referencing a consteval function when used in a - /// context not already known to be immediately invoked. - llvm::SmallPtrSet ReferenceToConsteval; + enum PragmaSectionKind { + PSK_DataSeg, + PSK_BSSSeg, + PSK_ConstSeg, + PSK_CodeSeg, + }; - /// P2718R0 - Lifetime extension in range-based for loops. - /// MaterializeTemporaryExprs in for-range-init expressions which need to - /// extend lifetime. Add MaterializeTemporaryExpr* if the value of - /// InLifetimeExtendingContext is true. - SmallVector ForRangeLifetimeExtendTemps; + // RAII object to push / pop sentinel slots for all MS #pragma stacks. + // Actions should be performed only if we enter / exit a C++ method body. + class PragmaStackSentinelRAII { + public: + PragmaStackSentinelRAII(Sema &S, StringRef SlotLabel, bool ShouldAct); + ~PragmaStackSentinelRAII(); - /// \brief Describes whether we are in an expression constext which we have - /// to handle differently. - enum ExpressionKind { - EK_Decltype, EK_TemplateArgument, EK_Other - } ExprContext; + private: + Sema &S; + StringRef SlotLabel; + bool ShouldAct; + }; - // A context can be nested in both a discarded statement context and - // an immediate function context, so they need to be tracked independently. - bool InDiscardedStatement; - bool InImmediateFunctionContext; - bool InImmediateEscalatingFunctionContext; + /// Last section used with #pragma init_seg. + StringLiteral *CurInitSeg; + SourceLocation CurInitSegLoc; - bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false; + /// Sections used with #pragma alloc_text. + llvm::StringMap> FunctionToSectionMap; - // We are in a constant context, but we also allow - // non constant expressions, for example for array bounds (which may be - // VLAs). - bool InConditionallyConstantEvaluateContext = false; + /// VisContext - Manages the stack for \#pragma GCC visibility. + void *VisContext; // Really a "PragmaVisStack*" - /// Whether we are currently in a context in which all temporaries must be - /// lifetime-extended, even if they're not bound to a reference (for - /// example, in a for-range initializer). - bool InLifetimeExtendingContext = false; + /// This an attribute introduced by \#pragma clang attribute. + struct PragmaAttributeEntry { + SourceLocation Loc; + ParsedAttr *Attribute; + SmallVector MatchRules; + bool IsUsed; + }; - /// Whether we are currently in a context in which all temporaries must be - /// materialized. - /// - /// [class.temporary]/p2: - /// The materialization of a temporary object is generally delayed as long - /// as possible in order to avoid creating unnecessary temporary objects. - /// - /// Temporary objects are materialized: - /// (2.1) when binding a reference to a prvalue ([dcl.init.ref], - /// [expr.type.conv], [expr.dynamic.cast], [expr.static.cast], - /// [expr.const.cast], [expr.cast]), - /// - /// (2.2) when performing member access on a class prvalue ([expr.ref], - /// [expr.mptr.oper]), - /// - /// (2.3) when performing an array-to-pointer conversion or subscripting - /// on an array prvalue ([conv.array], [expr.sub]), - /// - /// (2.4) when initializing an object of type - /// std​::​initializer_list from a braced-init-list - /// ([dcl.init.list]), - /// - /// (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof]) - /// - /// (2.6) when a prvalue that has type other than cv void appears as a - /// discarded-value expression ([expr.context]). - bool InMaterializeTemporaryObjectContext = false; + /// A push'd group of PragmaAttributeEntries. + struct PragmaAttributeGroup { + /// The location of the push attribute. + SourceLocation Loc; + /// The namespace of this push group. + const IdentifierInfo *Namespace; + SmallVector Entries; + }; - // When evaluating immediate functions in the initializer of a default - // argument or default member initializer, this is the declaration whose - // default initializer is being evaluated and the location of the call - // or constructor definition. - struct InitializationContext { - InitializationContext(SourceLocation Loc, ValueDecl *Decl, - DeclContext *Context) - : Loc(Loc), Decl(Decl), Context(Context) { - assert(Decl && Context && "invalid initialization context"); - } + SmallVector PragmaAttributeStack; - SourceLocation Loc; - ValueDecl *Decl = nullptr; - DeclContext *Context = nullptr; - }; - std::optional DelayedDefaultInitializationContext; + /// The declaration that is currently receiving an attribute from the + /// #pragma attribute stack. + const Decl *PragmaAttributeCurrentTargetDecl; - ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, - unsigned NumCleanupObjects, - CleanupInfo ParentCleanup, - Decl *ManglingContextDecl, - ExpressionKind ExprContext) - : Context(Context), ParentCleanup(ParentCleanup), - NumCleanupObjects(NumCleanupObjects), NumTypos(0), - ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext), - InDiscardedStatement(false), InImmediateFunctionContext(false), - InImmediateEscalatingFunctionContext(false) {} + /// This represents the last location of a "#pragma clang optimize off" + /// directive if such a directive has not been closed by an "on" yet. If + /// optimizations are currently "on", this is set to an invalid location. + SourceLocation OptimizeOffPragmaLocation; - bool isUnevaluated() const { - return Context == ExpressionEvaluationContext::Unevaluated || - Context == ExpressionEvaluationContext::UnevaluatedAbstract || - Context == ExpressionEvaluationContext::UnevaluatedList; - } + /// Get the location for the currently active "\#pragma clang optimize + /// off". If this location is invalid, then the state of the pragma is "on". + SourceLocation getOptimizeOffPragmaLocation() const { + return OptimizeOffPragmaLocation; + } - bool isConstantEvaluated() const { - return Context == ExpressionEvaluationContext::ConstantEvaluated || - Context == ExpressionEvaluationContext::ImmediateFunctionContext; - } + /// The "on" or "off" argument passed by \#pragma optimize, that denotes + /// whether the optimizations in the list passed to the pragma should be + /// turned off or on. This boolean is true by default because command line + /// options are honored when `#pragma optimize("", on)`. + /// (i.e. `ModifyFnAttributeMSPragmaOptimze()` does nothing) + bool MSPragmaOptimizeIsOn = true; - bool isImmediateFunctionContext() const { - return Context == ExpressionEvaluationContext::ImmediateFunctionContext || - (Context == ExpressionEvaluationContext::DiscardedStatement && - InImmediateFunctionContext) || - // C++23 [expr.const]p14: - // An expression or conversion is in an immediate function - // context if it is potentially evaluated and either: - // * its innermost enclosing non-block scope is a function - // parameter scope of an immediate function, or - // * its enclosing statement is enclosed by the compound- - // statement of a consteval if statement. - (Context == ExpressionEvaluationContext::PotentiallyEvaluated && - InImmediateFunctionContext); - } + /// Set of no-builtin functions listed by \#pragma function. + llvm::SmallSetVector MSFunctionNoBuiltins; - bool isDiscardedStatementContext() const { - return Context == ExpressionEvaluationContext::DiscardedStatement || - (Context == - ExpressionEvaluationContext::ImmediateFunctionContext && - InDiscardedStatement); - } - }; + /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to + /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'. + void AddAlignmentAttributesForRecord(RecordDecl *RD); - /// A stack of expression evaluation contexts. - SmallVector ExprEvalContexts; + /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record. + void AddMsStructLayoutForRecord(RecordDecl *RD); - // Set of failed immediate invocations to avoid double diagnosing. - llvm::SmallPtrSet FailedImmediateInvocations; + /// Add gsl::Pointer attribute to std::container::iterator + /// \param ND The declaration that introduces the name + /// std::container::iterator. \param UnderlyingRecord The record named by ND. + void inferGslPointerAttribute(NamedDecl *ND, CXXRecordDecl *UnderlyingRecord); - /// Emit a warning for all pending noderef expressions that we recorded. - void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec); + /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types. + void inferGslOwnerPointerAttribute(CXXRecordDecl *Record); - /// Compute the mangling number context for a lambda expression or - /// block literal. Also return the extra mangling decl if any. - /// - /// \param DC - The DeclContext containing the lambda expression or - /// block literal. - std::tuple - getCurrentMangleNumberContext(const DeclContext *DC); + /// Add [[gsl::Pointer]] attributes for std:: types. + void inferGslPointerAttribute(TypedefNameDecl *TD); + enum PragmaOptionsAlignKind { + POAK_Native, // #pragma options align=native + POAK_Natural, // #pragma options align=natural + POAK_Packed, // #pragma options align=packed + POAK_Power, // #pragma options align=power + POAK_Mac68k, // #pragma options align=mac68k + POAK_Reset // #pragma options align=reset + }; - /// SpecialMemberOverloadResult - The overloading result for a special member - /// function. - /// - /// This is basically a wrapper around PointerIntPair. The lowest bits of the - /// integer are used to determine whether overload resolution succeeded. - class SpecialMemberOverloadResult { - public: - enum Kind { - NoMemberOrDeleted, - Ambiguous, - Success - }; + /// ActOnPragmaClangSection - Called on well formed \#pragma clang section + void ActOnPragmaClangSection(SourceLocation PragmaLoc, + PragmaClangSectionAction Action, + PragmaClangSectionKind SecKind, + StringRef SecName); - private: - llvm::PointerIntPair Pair; + /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align. + void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, + SourceLocation PragmaLoc); - public: - SpecialMemberOverloadResult() {} - SpecialMemberOverloadResult(CXXMethodDecl *MD) - : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {} + /// ActOnPragmaPack - Called on well formed \#pragma pack(...). + void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, + StringRef SlotLabel, Expr *Alignment); - CXXMethodDecl *getMethod() const { return Pair.getPointer(); } - void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); } + /// ConstantFoldAttrArgs - Folds attribute arguments into ConstantExprs + /// (unless they are value dependent or type dependent). Returns false + /// and emits a diagnostic if one or more of the arguments could not be + /// folded into a constant. + bool ConstantFoldAttrArgs(const AttributeCommonInfo &CI, + MutableArrayRef Args); - Kind getKind() const { return static_cast(Pair.getInt()); } - void setKind(Kind K) { Pair.setInt(K); } + enum class PragmaAlignPackDiagnoseKind { + NonDefaultStateAtInclude, + ChangedStateAtExit }; - class SpecialMemberOverloadResultEntry - : public llvm::FastFoldingSetNode, - public SpecialMemberOverloadResult { - public: - SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID) - : FastFoldingSetNode(ID) - {} - }; + void DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind, + SourceLocation IncludeLoc); + void DiagnoseUnterminatedPragmaAlignPack(); - /// A cache of special member function overload resolution results - /// for C++ records. - llvm::FoldingSet SpecialMemberCache; + /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off]. + void ActOnPragmaMSStruct(PragmaMSStructKind Kind); - /// A cache of the flags available in enumerations with the flag_bits - /// attribute. - mutable llvm::DenseMap FlagBitsCache; + /// ActOnPragmaMSComment - Called on well formed + /// \#pragma comment(kind, "arg"). + void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind, + StringRef Arg); - /// The kind of translation unit we are processing. - /// - /// When we're processing a complete translation unit, Sema will perform - /// end-of-translation-unit semantic tasks (such as creating - /// initializers for tentative definitions in C) once parsing has - /// completed. Modules and precompiled headers perform different kinds of - /// checks. - const TranslationUnitKind TUKind; + /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch + void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, + StringRef Value); - llvm::BumpPtrAllocator BumpAlloc; + /// Are precise floating point semantics currently enabled? + bool isPreciseFPEnabled() { + return !CurFPFeatures.getAllowFPReassociate() && + !CurFPFeatures.getNoSignedZero() && + !CurFPFeatures.getAllowReciprocal() && + !CurFPFeatures.getAllowApproxFunc(); + } - /// The number of SFINAE diagnostics that have been trapped. - unsigned NumSFINAEErrors; + void ActOnPragmaFPEvalMethod(SourceLocation Loc, + LangOptions::FPEvalMethodKind Value); - typedef llvm::DenseMap> - UnparsedDefaultArgInstantiationsMap; + /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control + void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action, + PragmaFloatControlKind Value); - /// A mapping from parameters with unparsed default arguments to the - /// set of instantiations of each parameter. - /// - /// This mapping is a temporary data structure used when parsing - /// nested class templates or nested classes of class templates, - /// where we might end up instantiating an inner class before the - /// default arguments of its methods have been parsed. - UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations; + /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma + /// pointers_to_members(representation method[, general purpose + /// representation]). + void ActOnPragmaMSPointersToMembers( + LangOptions::PragmaMSPointersToMembersKind Kind, + SourceLocation PragmaLoc); - // Contains the locations of the beginning of unparsed default - // argument locations. - llvm::DenseMap UnparsedDefaultArgLocs; + /// Called on well formed \#pragma vtordisp(). + void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, + SourceLocation PragmaLoc, MSVtorDispMode Value); - /// UndefinedInternals - all the used, undefined objects which require a - /// definition in this translation unit. - llvm::MapVector UndefinedButUsed; - - /// Determine if VD, which must be a variable or function, is an external - /// symbol that nonetheless can't be referenced from outside this translation - /// unit because its type has no linkage and it's not extern "C". - bool isExternalWithNoLinkageType(const ValueDecl *VD) const; + bool UnifySection(StringRef SectionName, int SectionFlags, + NamedDecl *TheDecl); + bool UnifySection(StringRef SectionName, int SectionFlags, + SourceLocation PragmaSectionLocation); - /// Obtain a sorted list of functions that are undefined but ODR-used. - void getUndefinedButUsed( - SmallVectorImpl > &Undefined); + /// Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg. + void ActOnPragmaMSSeg(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + llvm::StringRef StackSlotLabel, + StringLiteral *SegmentName, llvm::StringRef PragmaName); - /// Retrieves list of suspicious delete-expressions that will be checked at - /// the end of translation unit. - const llvm::MapVector & - getMismatchingDeleteExpressions() const; + /// Called on well formed \#pragma section(). + void ActOnPragmaMSSection(SourceLocation PragmaLocation, int SectionFlags, + StringLiteral *SegmentName); - class GlobalMethodPool { - public: - using Lists = std::pair; - using iterator = llvm::DenseMap::iterator; - iterator begin() { return Methods.begin(); } - iterator end() { return Methods.end(); } - iterator find(Selector Sel) { return Methods.find(Sel); } - std::pair insert(std::pair &&Val) { - return Methods.insert(Val); - } - int count(Selector Sel) const { return Methods.count(Sel); } - bool empty() const { return Methods.empty(); } + /// Called on well-formed \#pragma init_seg(). + void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, + StringLiteral *SegmentName); - private: - llvm::DenseMap Methods; - }; + /// Called on well-formed \#pragma alloc_text(). + void ActOnPragmaMSAllocText( + SourceLocation PragmaLocation, StringRef Section, + const SmallVector> + &Functions); - /// Method Pool - allows efficient lookup when typechecking messages to "id". - /// We need to maintain a list, since selectors can have differing signatures - /// across classes. In Cocoa, this happens to be extremely uncommon (only 1% - /// of selectors are "overloaded"). - /// At the head of the list it is recorded whether there were 0, 1, or >= 2 - /// methods inside categories with a particular selector. - GlobalMethodPool MethodPool; + /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma + /// strict_gs_check. + void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation, + PragmaMsStackAction Action, + bool Value); - /// Method selectors used in a \@selector expression. Used for implementation - /// of -Wselector. - llvm::MapVector ReferencedSelectors; + /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'. + void ActOnPragmaUnused(const Token &Identifier, Scope *curScope, + SourceLocation PragmaLoc); - /// List of SourceLocations where 'self' is implicitly retained inside a - /// block. - llvm::SmallVector, 1> - ImplicitlyRetainedSelfLocs; + /// AddCFAuditedAttribute - Check whether we're currently within + /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding + /// the appropriate attribute. + void AddCFAuditedAttribute(Decl *D); - /// Kinds of C++ special members. - enum CXXSpecialMember { - CXXDefaultConstructor, - CXXCopyConstructor, - CXXMoveConstructor, - CXXCopyAssignment, - CXXMoveAssignment, - CXXDestructor, - CXXInvalid - }; + void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute, + SourceLocation PragmaLoc, + attr::ParsedSubjectMatchRuleSet Rules); + void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, + const IdentifierInfo *Namespace); - typedef llvm::PointerIntPair - SpecialMemberDecl; + /// Called on well-formed '\#pragma clang attribute pop'. + void ActOnPragmaAttributePop(SourceLocation PragmaLoc, + const IdentifierInfo *Namespace); - /// The C++ special members which we are currently in the process of - /// declaring. If this process recursively triggers the declaration of the - /// same special member, we should act as if it is not yet declared. - llvm::SmallPtrSet SpecialMembersBeingDeclared; + /// Adds the attributes that have been specified using the + /// '\#pragma clang attribute push' directives to the given declaration. + void AddPragmaAttributes(Scope *S, Decl *D); - /// Kinds of defaulted comparison operator functions. - enum class DefaultedComparisonKind : unsigned char { - /// This is not a defaultable comparison operator. - None, - /// This is an operator== that should be implemented as a series of - /// subobject comparisons. - Equal, - /// This is an operator<=> that should be implemented as a series of - /// subobject comparisons. - ThreeWay, - /// This is an operator!= that should be implemented as a rewrite in terms - /// of a == comparison. - NotEqual, - /// This is an <, <=, >, or >= that should be implemented as a rewrite in - /// terms of a <=> comparison. - Relational, - }; + void PrintPragmaAttributeInstantiationPoint(); - /// The function definitions which were renamed as part of typo-correction - /// to match their respective declarations. We want to keep track of them - /// to ensure that we don't emit a "redefinition" error if we encounter a - /// correctly named definition after the renamed definition. - llvm::SmallPtrSet TypoCorrectedFunctionDefinitions; + void DiagnoseUnterminatedPragmaAttribute(); - /// Stack of types that correspond to the parameter entities that are - /// currently being copy-initialized. Can be empty. - llvm::SmallVector CurrentParameterCopyTypes; + /// Called on well formed \#pragma clang optimize. + void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc); - void ReadMethodPool(Selector Sel); - void updateOutOfDateSelector(Selector Sel); + /// #pragma optimize("[optimization-list]", on | off). + void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn); - /// Private Helper predicate to check for 'self'. - bool isSelfExpr(Expr *RExpr); - bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method); + /// Call on well formed \#pragma function. + void + ActOnPragmaMSFunction(SourceLocation Loc, + const llvm::SmallVectorImpl &NoBuiltins); - /// Cause the active diagnostic on the DiagosticsEngine to be - /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and - /// should not be used elsewhere. - void EmitCurrentDiagnostic(unsigned DiagID); + /// Only called on function definitions; if there is a pragma in scope + /// with the effect of a range-based optnone, consider marking the function + /// with attribute optnone. + void AddRangeBasedOptnone(FunctionDecl *FD); - /// Records and restores the CurFPFeatures state on entry/exit of compound - /// statements. - class FPFeaturesStateRAII { - public: - FPFeaturesStateRAII(Sema &S); - ~FPFeaturesStateRAII(); - FPOptionsOverride getOverrides() { return OldOverrides; } + /// Only called on function definitions; if there is a `#pragma alloc_text` + /// that decides which code section the function should be in, add + /// attribute section to the function. + void AddSectionMSAllocText(FunctionDecl *FD); - private: - Sema& S; - FPOptions OldFPFeaturesState; - FPOptionsOverride OldOverrides; - LangOptions::FPEvalMethodKind OldEvalMethod; - SourceLocation OldFPPragmaLocation; - }; + /// Adds the 'optnone' attribute to the function declaration if there + /// are no conflicts; Loc represents the location causing the 'optnone' + /// attribute to be added (usually because of a pragma). + void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc); - void addImplicitTypedef(StringRef Name, QualType T); + /// Only called on function definitions; if there is a MSVC #pragma optimize + /// in scope, consider changing the function's attributes based on the + /// optimization list passed to the pragma. + void ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD); - bool WarnedStackExhausted = false; + /// Only called on function definitions; if there is a pragma in scope + /// with the effect of a range-based no_builtin, consider marking the function + /// with attribute no_builtin. + void AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD); - /// Increment when we find a reference; decrement when we find an ignored - /// assignment. Ultimately the value is 0 if every reference is an ignored - /// assignment. - llvm::DenseMap RefsMinusAssignments; + /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used, + /// add an appropriate visibility attribute. + void AddPushedVisibilityAttribute(Decl *RD); - /// Indicate RISC-V vector builtin functions enabled or not. - bool DeclareRISCVVBuiltins = false; + /// FreeVisContext - Deallocate and null out VisContext. + void FreeVisContext(); - /// Indicate RISC-V SiFive vector builtin functions enabled or not. - bool DeclareRISCVSiFiveVectorBuiltins = false; + /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... . + void ActOnPragmaVisibility(const IdentifierInfo *VisType, + SourceLocation PragmaLoc); -private: - std::unique_ptr RVIntrinsicManager; + /// ActOnPragmaFPContract - Called on well formed + /// \#pragma {STDC,OPENCL} FP_CONTRACT and + /// \#pragma clang fp contract + void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC); - std::optional> CachedDarwinSDKInfo; + /// Called on well formed + /// \#pragma clang fp reassociate + /// or + /// \#pragma clang fp reciprocal + void ActOnPragmaFPValueChangingOption(SourceLocation Loc, PragmaFPKind Kind, + bool IsEnabled); - bool WarnedDarwinSDKInfoMissing = false; + /// ActOnPragmaFenvAccess - Called on well formed + /// \#pragma STDC FENV_ACCESS + void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled); -public: - Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, - TranslationUnitKind TUKind = TU_Complete, - CodeCompleteConsumer *CompletionConsumer = nullptr); - ~Sema(); + /// ActOnPragmaCXLimitedRange - Called on well formed + /// \#pragma STDC CX_LIMITED_RANGE + void ActOnPragmaCXLimitedRange(SourceLocation Loc, + LangOptions::ComplexRangeKind Range); - /// Perform initialization that occurs after the parser has been - /// initialized but before it parses anything. - void Initialize(); + /// Called on well formed '\#pragma clang fp' that has option 'exceptions'. + void ActOnPragmaFPExceptions(SourceLocation Loc, + LangOptions::FPExceptionModeKind); - /// This virtual key function only exists to limit the emission of debug info - /// describing the Sema class. GCC and Clang only emit debug info for a class - /// with a vtable when the vtable is emitted. Sema is final and not - /// polymorphic, but the debug info size savings are so significant that it is - /// worth adding a vtable just to take advantage of this optimization. - virtual void anchor(); + /// Called to set constant rounding mode for floating point operations. + void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode); - const LangOptions &getLangOpts() const { return LangOpts; } - OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; } - FPOptions &getCurFPFeatures() { return CurFPFeatures; } + /// Called to set exception behavior for floating point operations. + void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind); - DiagnosticsEngine &getDiagnostics() const { return Diags; } - SourceManager &getSourceManager() const { return SourceMgr; } - Preprocessor &getPreprocessor() const { return PP; } - ASTContext &getASTContext() const { return Context; } - ASTConsumer &getASTConsumer() const { return Consumer; } - ASTMutationListener *getASTMutationListener() const; - ExternalSemaSource *getExternalSource() const { return ExternalSource.get(); } + /// PushNamespaceVisibilityAttr - Note that we've entered a + /// namespace with a visibility attribute. + void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, + SourceLocation Loc); - DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc, - StringRef Platform); - DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(); + /// PopPragmaVisibility - Pop the top element of the visibility stack; used + /// for '\#pragma GCC visibility' and visibility attributes on namespaces. + void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc); - ///Registers an external source. If an external source already exists, - /// creates a multiplex external source and appends to it. - /// - ///\param[in] E - A non-null external sema source. - /// - void addExternalSource(ExternalSemaSource *E); + /// Handles semantic checking for features that are common to all attributes, + /// such as checking whether a parameter was properly specified, or the + /// correct number of arguments were passed, etc. Returns true if the + /// attribute has been diagnosed. + bool checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A, + bool SkipArgCountCheck = false); + bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, + bool SkipArgCountCheck = false); - void PrintStats() const; + ///@} - /// Warn that the stack is nearly exhausted. - void warnStackExhausted(SourceLocation Loc); + // + // + // ------------------------------------------------------------------------- + // + // - /// Run some code with "sufficient" stack space. (Currently, at least 256K is - /// guaranteed). Produces a warning if we're low on stack space and allocates - /// more in that case. Use this in code that may recurse deeply (for example, - /// in template instantiation) to avoid stack overflow. - void runWithSufficientStackSpace(SourceLocation Loc, - llvm::function_ref Fn); + /// \name Availability Attribute Handling + /// Implementations are in SemaAvailability.cpp + ///@{ - /// Helper class that creates diagnostics with optional - /// template instantiation stacks. - /// - /// This class provides a wrapper around the basic DiagnosticBuilder - /// class that emits diagnostics. ImmediateDiagBuilder is - /// responsible for emitting the diagnostic (as DiagnosticBuilder - /// does) and, if the diagnostic comes from inside a template - /// instantiation, printing the template instantiation stack as - /// well. - class ImmediateDiagBuilder : public DiagnosticBuilder { - Sema &SemaRef; - unsigned DiagID; +public: + /// Issue any -Wunguarded-availability warnings in \c FD + void DiagnoseUnguardedAvailabilityViolations(Decl *FD); - public: - ImmediateDiagBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID) - : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {} - ImmediateDiagBuilder(DiagnosticBuilder &&DB, Sema &SemaRef, unsigned DiagID) - : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {} + void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); - // This is a cunning lie. DiagnosticBuilder actually performs move - // construction in its copy constructor (but due to varied uses, it's not - // possible to conveniently express this as actual move construction). So - // the default copy ctor here is fine, because the base class disables the - // source anyway, so the user-defined ~ImmediateDiagBuilder is a safe no-op - // in that case anwyay. - ImmediateDiagBuilder(const ImmediateDiagBuilder &) = default; + /// Retrieve the current function, if any, that should be analyzed for + /// potential availability violations. + sema::FunctionScopeInfo *getCurFunctionAvailabilityContext(); - ~ImmediateDiagBuilder() { - // If we aren't active, there is nothing to do. - if (!isActive()) return; + void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef Locs, + const ObjCInterfaceDecl *UnknownObjCClass, + bool ObjCPropertyAccess, + bool AvoidPartialAvailabilityChecks = false, + ObjCInterfaceDecl *ClassReceiver = nullptr); - // Otherwise, we need to emit the diagnostic. First clear the diagnostic - // builder itself so it won't emit the diagnostic in its own destructor. - // - // This seems wasteful, in that as written the DiagnosticBuilder dtor will - // do its own needless checks to see if the diagnostic needs to be - // emitted. However, because we take care to ensure that the builder - // objects never escape, a sufficiently smart compiler will be able to - // eliminate that code. - Clear(); + ///@} - // Dispatch to Sema to emit the diagnostic. - SemaRef.EmitCurrentDiagnostic(DiagID); - } + // + // + // ------------------------------------------------------------------------- + // + // - /// Teach operator<< to produce an object of the correct type. - template - friend const ImmediateDiagBuilder & - operator<<(const ImmediateDiagBuilder &Diag, const T &Value) { - const DiagnosticBuilder &BaseDiag = Diag; - BaseDiag << Value; - return Diag; - } + /// \name Casts + /// Implementations are in SemaCast.cpp + ///@{ - // It is necessary to limit this to rvalue reference to avoid calling this - // function with a bitfield lvalue argument since non-const reference to - // bitfield is not allowed. - template ::value>> - const ImmediateDiagBuilder &operator<<(T &&V) const { - const DiagnosticBuilder &BaseDiag = *this; - BaseDiag << std::move(V); - return *this; - } - }; +public: + static bool isCast(CheckedConversionKind CCK) { + return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast || + CCK == CCK_OtherCast; + } - /// A generic diagnostic builder for errors which may or may not be deferred. - /// - /// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch) - /// which are not allowed to appear inside __device__ functions and are - /// allowed to appear in __host__ __device__ functions only if the host+device - /// function is never codegen'ed. - /// - /// To handle this, we use the notion of "deferred diagnostics", where we - /// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed. - /// - /// This class lets you emit either a regular diagnostic, a deferred - /// diagnostic, or no diagnostic at all, according to an argument you pass to - /// its constructor, thus simplifying the process of creating these "maybe - /// deferred" diagnostics. - class SemaDiagnosticBuilder { - public: - enum Kind { - /// Emit no diagnostics. - K_Nop, - /// Emit the diagnostic immediately (i.e., behave like Sema::Diag()). - K_Immediate, - /// Emit the diagnostic immediately, and, if it's a warning or error, also - /// emit a call stack showing how this function can be reached by an a - /// priori known-emitted function. - K_ImmediateWithCallStack, - /// Create a deferred diagnostic, which is emitted only if the function - /// it's attached to is codegen'ed. Also emit a call stack as with - /// K_ImmediateWithCallStack. - K_Deferred - }; + /// ActOnCXXNamedCast - Parse + /// {dynamic,static,reinterpret,const,addrspace}_cast's. + ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, + SourceLocation LAngleBracketLoc, Declarator &D, + SourceLocation RAngleBracketLoc, + SourceLocation LParenLoc, Expr *E, + SourceLocation RParenLoc); - SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID, - const FunctionDecl *Fn, Sema &S); - SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D); - SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default; + ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, + TypeSourceInfo *Ty, Expr *E, + SourceRange AngleBrackets, SourceRange Parens); - // The copy and move assignment operator is defined as deleted pending - // further motivation. - SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete; - SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete; + ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl, + ExprResult Operand, + SourceLocation RParenLoc); - ~SemaDiagnosticBuilder(); + ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI, + Expr *Operand, SourceLocation RParenLoc); - bool isImmediate() const { return ImmediateDiag.has_value(); } + // Checks that reinterpret casts don't have undefined behavior. + void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, + bool IsDereference, SourceRange Range); - /// Convertible to bool: True if we immediately emitted an error, false if - /// we didn't emit an error or we created a deferred error. - /// - /// Example usage: - /// - /// if (SemaDiagnosticBuilder(...) << foo << bar) - /// return ExprError(); - /// - /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably - /// want to use these instead of creating a SemaDiagnosticBuilder yourself. - operator bool() const { return isImmediate(); } + // Checks that the vector type should be initialized from a scalar + // by splatting the value rather than populating a single element. + // This is the case for AltiVecVector types as well as with + // AltiVecPixel and AltiVecBool when -faltivec-src-compat=xl is specified. + bool ShouldSplatAltivecScalarInCast(const VectorType *VecTy); - template - friend const SemaDiagnosticBuilder & - operator<<(const SemaDiagnosticBuilder &Diag, const T &Value) { - if (Diag.ImmediateDiag) - *Diag.ImmediateDiag << Value; - else if (Diag.PartialDiagId) - Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second - << Value; - return Diag; - } + // Checks if the -faltivec-src-compat=gcc option is specified. + // If so, AltiVecVector, AltiVecBool and AltiVecPixel types are + // treated the same way as they are when trying to initialize + // these vectors on gcc (an error is emitted). + bool CheckAltivecInitFromScalar(SourceRange R, QualType VecTy, + QualType SrcTy); - // It is necessary to limit this to rvalue reference to avoid calling this - // function with a bitfield lvalue argument since non-const reference to - // bitfield is not allowed. - template ::value>> - const SemaDiagnosticBuilder &operator<<(T &&V) const { - if (ImmediateDiag) - *ImmediateDiag << std::move(V); - else if (PartialDiagId) - S.DeviceDeferredDiags[Fn][*PartialDiagId].second << std::move(V); - return *this; - } + ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, + SourceLocation RParenLoc, Expr *Op); - friend const SemaDiagnosticBuilder & - operator<<(const SemaDiagnosticBuilder &Diag, const PartialDiagnostic &PD) { - if (Diag.ImmediateDiag) - PD.Emit(*Diag.ImmediateDiag); - else if (Diag.PartialDiagId) - Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD; - return Diag; - } + ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type, + SourceLocation LParenLoc, + Expr *CastExpr, + SourceLocation RParenLoc); - void AddFixItHint(const FixItHint &Hint) const { - if (ImmediateDiag) - ImmediateDiag->AddFixItHint(Hint); - else if (PartialDiagId) - S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint); - } + ///@} - friend ExprResult ExprError(const SemaDiagnosticBuilder &) { - return ExprError(); - } - friend StmtResult StmtError(const SemaDiagnosticBuilder &) { - return StmtError(); - } - operator ExprResult() const { return ExprError(); } - operator StmtResult() const { return StmtError(); } - operator TypeResult() const { return TypeError(); } - operator DeclResult() const { return DeclResult(true); } - operator MemInitResult() const { return MemInitResult(true); } + // + // + // ------------------------------------------------------------------------- + // + // - private: - Sema &S; - SourceLocation Loc; - unsigned DiagID; - const FunctionDecl *Fn; - bool ShowCallStack; + /// \name Extra Semantic Checking + /// Implementations are in SemaChecking.cpp + ///@{ - // Invariant: At most one of these Optionals has a value. - // FIXME: Switch these to a Variant once that exists. - std::optional ImmediateDiag; - std::optional PartialDiagId; - }; +public: + /// Used to change context to isConstantEvaluated without pushing a heavy + /// ExpressionEvaluationContextRecord object. + bool isConstantEvaluatedOverride = false; - /// Is the last error level diagnostic immediate. This is used to determined - /// whether the next info diagnostic should be immediate. - bool IsLastErrorImmediate = true; + bool isConstantEvaluatedContext() const { + return currentEvaluationContext().isConstantEvaluated() || + isConstantEvaluatedOverride; + } - /// Emit a diagnostic. - SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, - bool DeferHint = false); + SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL, + unsigned ByteNo) const; - /// Emit a partial diagnostic. - SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD, - bool DeferHint = false); + enum FormatArgumentPassingKind { + FAPK_Fixed, // values to format are fixed (no C-style variadic arguments) + FAPK_Variadic, // values to format are passed as variadic arguments + FAPK_VAList, // values to format are passed in a va_list + }; - /// Build a partial diagnostic. - PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h + // Used to grab the relevant information from a FormatAttr and a + // FunctionDeclaration. + struct FormatStringInfo { + unsigned FormatIdx; + unsigned FirstDataArg; + FormatArgumentPassingKind ArgPassingKind; + }; - /// Whether deferrable diagnostics should be deferred. - bool DeferDiags = false; + static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, + bool IsVariadic, FormatStringInfo *FSI); - /// RAII class to control scope of DeferDiags. - class DeferDiagsRAII { - Sema &S; - bool SavedDeferDiags = false; + // Used by C++ template instantiation. + ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); + ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc); - public: - DeferDiagsRAII(Sema &S, bool DeferDiags) - : S(S), SavedDeferDiags(S.DeferDiags) { - S.DeferDiags = DeferDiags; - } - ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; } + enum FormatStringType { + FST_Scanf, + FST_Printf, + FST_NSString, + FST_Strftime, + FST_Strfmon, + FST_Kprintf, + FST_FreeBSDKPrintf, + FST_OSTrace, + FST_OSLog, + FST_Unknown }; + static FormatStringType GetFormatStringType(const FormatAttr *Format); - /// Whether uncompilable error has occurred. This includes error happens - /// in deferred diagnostics. - bool hasUncompilableErrorOccurred() const; + bool FormatStringHasSArg(const StringLiteral *FExpr); - bool findMacroSpelling(SourceLocation &loc, StringRef name); + static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx); - /// Get a string to suggest for zero-initialization of a type. - std::string - getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const; - std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const; + void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS, + BinaryOperatorKind Opcode); - /// Calls \c Lexer::getLocForEndOfToken() - SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0); + /// Register a magic integral constant to be used as a type tag. + void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, + uint64_t MagicValue, QualType Type, + bool LayoutCompatible, bool MustBeNull); - /// Retrieve the module loader associated with the preprocessor. - ModuleLoader &getModuleLoader() const; + struct TypeTagData { + TypeTagData() {} - /// Invent a new identifier for parameters of abbreviated templates. - IdentifierInfo * - InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName, - unsigned Index); + TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) + : Type(Type), LayoutCompatible(LayoutCompatible), + MustBeNull(MustBeNull) {} - void emitAndClearUnusedLocalTypedefWarnings(); + QualType Type; - private: - /// Function or variable declarations to be checked for whether the deferred - /// diagnostics should be emitted. - llvm::SmallSetVector DeclsToCheckForDeferredDiags; + /// If true, \c Type should be compared with other expression's types for + /// layout-compatibility. + LLVM_PREFERRED_TYPE(bool) + unsigned LayoutCompatible : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned MustBeNull : 1; + }; - public: - // Emit all deferred diagnostics. - void emitDeferredDiags(); + /// A pair of ArgumentKind identifier and magic value. This uniquely + /// identifies the magic value. + typedef std::pair TypeTagMagicValue; - enum TUFragmentKind { - /// The global module fragment, between 'module;' and a module-declaration. - Global, - /// A normal translation unit fragment. For a non-module unit, this is the - /// entire translation unit. Otherwise, it runs from the module-declaration - /// to the private-module-fragment (if any) or the end of the TU (if not). - Normal, - /// The private module fragment, between 'module :private;' and the end of - /// the translation unit. - Private - }; + /// Diagnoses the current set of gathered accesses. This typically + /// happens at full expression level. The set is cleared after emitting the + /// diagnostics. + void DiagnoseMisalignedMembers(); - void ActOnStartOfTranslationUnit(); - void ActOnEndOfTranslationUnit(); - void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind); + /// This function checks if the expression is in the sef of potentially + /// misaligned members and it is converted to some pointer type T with lower + /// or equal alignment requirements. If so it removes it. This is used when + /// we do not want to diagnose such misaligned access (e.g. in conversions to + /// void*). + void DiscardMisalignedMemberAddress(const Type *T, Expr *E); - void CheckDelegatingCtorCycles(); + /// This function calls Action when it determines that E designates a + /// misaligned member due to the packed attribute. This is used to emit + /// local diagnostics like in reference binding. + void RefersToMemberWithReducedAlignment( + Expr *E, + llvm::function_ref + Action); - Scope *getScopeForContext(DeclContext *Ctx); + enum class AtomicArgumentOrder { API, AST }; + ExprResult + BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, + SourceLocation RParenLoc, MultiExprArg Args, + AtomicExpr::AtomicOp Op, + AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API); - void PushFunctionScope(); - void PushBlockScope(Scope *BlockScope, BlockDecl *Block); - sema::LambdaScopeInfo *PushLambdaScope(); + /// Check to see if a given expression could have '.c_str()' called on it. + bool hasCStrMethod(const Expr *E); - /// This is used to inform Sema what the current TemplateParameterDepth - /// is during Parsing. Currently it is used to pass on the depth - /// when parsing generic lambda 'auto' parameters. - void RecordParsingTemplateParameterDepth(unsigned Depth); + void DiagnoseAlwaysNonNullPointer(Expr *E, + Expr::NullPointerConstantKind NullType, + bool IsEqual, SourceRange Range); - void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD, - RecordDecl *RD, CapturedRegionKind K, - unsigned OpenMPCaptureLevel = 0); + bool CheckParmsForFunctionDef(ArrayRef Parameters, + bool CheckParameterNames); - /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short - /// time after they've been popped. - class PoppedFunctionScopeDeleter { - Sema *Self; + void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); - public: - explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {} - void operator()(sema::FunctionScopeInfo *Scope) const; - }; + /// checkRetainCycles - Check whether an Objective-C message send + /// might create an obvious retain cycle. + void checkRetainCycles(ObjCMessageExpr *msg); + void checkRetainCycles(Expr *receiver, Expr *argument); + void checkRetainCycles(VarDecl *Var, Expr *Init); - using PoppedFunctionScopePtr = - std::unique_ptr; + /// checkUnsafeAssigns - Check whether +1 expr is being assigned + /// to weak/__unsafe_unretained type. + bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS); - PoppedFunctionScopePtr - PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr, - const Decl *D = nullptr, - QualType BlockType = QualType()); + /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned + /// to weak/__unsafe_unretained expression. + void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS); - sema::FunctionScopeInfo *getCurFunction() const { - return FunctionScopes.empty() ? nullptr : FunctionScopes.back(); - } + /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null + /// statement as a \p Body, and it is located on the same line. + /// + /// This helps prevent bugs due to typos, such as: + /// if (condition); + /// do_stuff(); + void DiagnoseEmptyStmtBody(SourceLocation StmtLoc, const Stmt *Body, + unsigned DiagID); - sema::FunctionScopeInfo *getEnclosingFunction() const; + /// Warn if a for/while loop statement \p S, which is followed by + /// \p PossibleBody, has a suspicious null statement as a body. + void DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody); - void setFunctionHasBranchIntoScope(); - void setFunctionHasBranchProtectedScope(); - void setFunctionHasIndirectGoto(); - void setFunctionHasMustTail(); + /// Warn if a value is moved to itself. + void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, + SourceLocation OpLoc); - void PushCompoundScope(bool IsStmtExpr); - void PopCompoundScope(); + // Used for emitting the right warning by DefaultVariadicArgumentPromotion + enum VariadicCallType { + VariadicFunction, + VariadicBlock, + VariadicMethod, + VariadicConstructor, + VariadicDoesNotApply + }; - sema::CompoundScopeInfo &getCurCompoundScope() const; + bool IsLayoutCompatible(QualType T1, QualType T2) const; - bool hasAnyUnrecoverableErrorsInThisFunction() const; +private: + void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, + const ArraySubscriptExpr *ASE = nullptr, + bool AllowOnePastEnd = true, bool IndexNegated = false); + void CheckArrayAccess(const Expr *E); - /// Retrieve the current block, if any. - sema::BlockScopeInfo *getCurBlock(); + bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); + bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, + ArrayRef Args); + bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); + bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto); + void CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, + ArrayRef Args, + const FunctionProtoType *Proto, SourceLocation Loc); - /// Get the innermost lambda enclosing the current location, if any. This - /// looks through intervening non-lambda scopes such as local functions and - /// blocks. - sema::LambdaScopeInfo *getEnclosingLambda() const; + void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg); - /// Retrieve the current lambda scope info, if any. - /// \param IgnoreNonLambdaCapturingScope true if should find the top-most - /// lambda scope info ignoring all inner capturing scopes that are not - /// lambda scopes. - sema::LambdaScopeInfo * - getCurLambda(bool IgnoreNonLambdaCapturingScope = false); + void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl, + StringRef ParamName, QualType ArgTy, QualType ParamTy); - /// Retrieve the current generic lambda info, if any. - sema::LambdaScopeInfo *getCurGenericLambda(); + void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, + const Expr *ThisArg, ArrayRef Args, + bool IsMemberFunction, SourceLocation Loc, SourceRange Range, + VariadicCallType CallType); - /// Retrieve the current captured region, if any. - sema::CapturedRegionScopeInfo *getCurCapturedRegion(); + bool CheckObjCString(Expr *Arg); + ExprResult CheckOSLogFormatStringArg(Expr *Arg); - /// Retrieve the current function, if any, that should be analyzed for - /// potential availability violations. - sema::FunctionScopeInfo *getCurFunctionAvailabilityContext(); + ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, + CallExpr *TheCall); - /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls - SmallVectorImpl &WeakTopLevelDecls() { return WeakTopLevelDecl; } + bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); - /// Called before parsing a function declarator belonging to a function - /// declaration. - void ActOnStartFunctionDeclarationDeclarator(Declarator &D, - unsigned TemplateParameterDepth); + void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall); - /// Called after parsing a function declarator belonging to a function - /// declaration. - void ActOnFinishFunctionDeclarationDeclarator(Declarator &D); + bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, + unsigned MaxWidth); + bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool ParseSVEImmChecks(CallExpr *TheCall, + SmallVector, 3> &ImmChecks); + bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, + bool WantCDE); + bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); - void ActOnComment(SourceRange Comment); + bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall); + bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall); + bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinTileArguments(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall, + ArrayRef ArgNums); + bool CheckX86BuiltinTileDuplicate(CallExpr *TheCall, ArrayRef ArgNums); + bool CheckX86BuiltinTileRangeAndDuplicate(CallExpr *TheCall, + ArrayRef ArgNums); + bool CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); + bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); + void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D); + bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, + unsigned BuiltinID, CallExpr *TheCall); + bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, + unsigned BuiltinID, + CallExpr *TheCall); + bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, + CallExpr *TheCall); - //===--------------------------------------------------------------------===// - // Type Analysis / Processing: SemaType.cpp. - // + bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall); + bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call); + bool SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID); + bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, + unsigned BuiltinID); + bool SemaBuiltinComplex(CallExpr *TheCall); + bool SemaBuiltinVSX(CallExpr *TheCall); + bool SemaBuiltinOSLogFormat(CallExpr *TheCall); + bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum); - QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs, - const DeclSpec *DS = nullptr); - QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, - const DeclSpec *DS = nullptr); - QualType BuildPointerType(QualType T, - SourceLocation Loc, DeclarationName Entity); - QualType BuildReferenceType(QualType T, bool LValueRef, - SourceLocation Loc, DeclarationName Entity); - QualType BuildArrayType(QualType T, ArraySizeModifier ASM, Expr *ArraySize, - unsigned Quals, SourceRange Brackets, - DeclarationName Entity); - QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc); - QualType BuildExtVectorType(QualType T, Expr *ArraySize, - SourceLocation AttrLoc); - QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns, - SourceLocation AttrLoc); + bool SemaBuiltinPrefetch(CallExpr *TheCall); + bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall); + bool SemaBuiltinArithmeticFence(CallExpr *TheCall); + bool SemaBuiltinAssume(CallExpr *TheCall); + bool SemaBuiltinAssumeAligned(CallExpr *TheCall); + bool SemaBuiltinLongjmp(CallExpr *TheCall); + bool SemaBuiltinSetjmp(CallExpr *TheCall); + ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult); + ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult); + ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult, + AtomicExpr::AtomicOp Op); + bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, + llvm::APSInt &Result); + bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, + int High, bool RangeIsError = true); + bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, + unsigned Multiple); + bool SemaBuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum); + bool SemaBuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum, + unsigned ArgBits); + bool SemaBuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, + unsigned ArgBits); + bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, + int ArgNum, unsigned ExpectedFieldNum, + bool AllowName); + bool SemaBuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall); + bool SemaBuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID, + const char *TypeDesc); - QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, - SourceLocation AttrLoc); + bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc); - /// Same as above, but constructs the AddressSpace index if not provided. - QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, - SourceLocation AttrLoc); + bool SemaBuiltinElementwiseMath(CallExpr *TheCall); + bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall, + bool CheckForFloatArgs = true); + bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall); + bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall); - CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E); - bool CheckRebuiltStmtAttributes(ArrayRef Attrs); + bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall); - bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc); + // Matrix builtin handling. + ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall, + ExprResult CallResult); + ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall, + ExprResult CallResult); + ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall, + ExprResult CallResult); - bool CheckFunctionReturnType(QualType T, SourceLocation Loc); + // WebAssembly builtin handling. + bool BuiltinWasmRefNullExtern(CallExpr *TheCall); + bool BuiltinWasmRefNullFunc(CallExpr *TheCall); + bool BuiltinWasmTableGet(CallExpr *TheCall); + bool BuiltinWasmTableSet(CallExpr *TheCall); + bool BuiltinWasmTableSize(CallExpr *TheCall); + bool BuiltinWasmTableGrow(CallExpr *TheCall); + bool BuiltinWasmTableFill(CallExpr *TheCall); + bool BuiltinWasmTableCopy(CallExpr *TheCall); - /// Check an argument list for placeholders that we won't try to - /// handle later. - bool CheckArgsForPlaceholders(MultiExprArg args); + bool CheckFormatArguments(const FormatAttr *Format, + ArrayRef Args, bool IsCXXMember, + VariadicCallType CallType, SourceLocation Loc, + SourceRange Range, + llvm::SmallBitVector &CheckedVarArgs); + bool CheckFormatArguments(ArrayRef Args, + FormatArgumentPassingKind FAPK, unsigned format_idx, + unsigned firstDataArg, FormatStringType Type, + VariadicCallType CallType, SourceLocation Loc, + SourceRange range, + llvm::SmallBitVector &CheckedVarArgs); - /// Build a function type. - /// - /// This routine checks the function type according to C++ rules and - /// under the assumption that the result type and parameter types have - /// just been instantiated from a template. It therefore duplicates - /// some of the behavior of GetTypeForDeclarator, but in a much - /// simpler form that is only suitable for this narrow use case. - /// - /// \param T The return type of the function. - /// - /// \param ParamTypes The parameter types of the function. This array - /// will be modified to account for adjustments to the types of the - /// function parameters. - /// - /// \param Loc The location of the entity whose type involves this - /// function type or, if there is no such entity, the location of the - /// type that will have function type. - /// - /// \param Entity The name of the entity that involves the function - /// type, if known. - /// - /// \param EPI Extra information about the function type. Usually this will - /// be taken from an existing function with the same prototype. - /// - /// \returns A suitable function type, if there are no errors. The - /// unqualified type will always be a FunctionProtoType. - /// Otherwise, returns a NULL type. - QualType BuildFunctionType(QualType T, - MutableArrayRef ParamTypes, - SourceLocation Loc, DeclarationName Entity, - const FunctionProtoType::ExtProtoInfo &EPI); + void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl); - QualType BuildMemberPointerType(QualType T, QualType Class, - SourceLocation Loc, - DeclarationName Entity); - QualType BuildBlockPointerType(QualType T, - SourceLocation Loc, DeclarationName Entity); - QualType BuildParenType(QualType T); - QualType BuildAtomicType(QualType T, SourceLocation Loc); - QualType BuildReadPipeType(QualType T, - SourceLocation Loc); - QualType BuildWritePipeType(QualType T, - SourceLocation Loc); - QualType BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc); + void CheckAbsoluteValueFunction(const CallExpr *Call, + const FunctionDecl *FDecl); - TypeSourceInfo *GetTypeForDeclarator(Declarator &D); - TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); + void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl); - /// Package the given type and TSI into a ParsedType. - ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); - DeclarationNameInfo GetNameForDeclarator(Declarator &D); - DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name); - static QualType GetTypeFromParser(ParsedType Ty, - TypeSourceInfo **TInfo = nullptr); - CanThrowResult canThrow(const Stmt *E); - /// Determine whether the callee of a particular function call can throw. - /// E, D and Loc are all optional. - static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, - SourceLocation Loc = SourceLocation()); - const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, - const FunctionProtoType *FPT); - void UpdateExceptionSpec(FunctionDecl *FD, - const FunctionProtoType::ExceptionSpecInfo &ESI); - bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range); - bool CheckDistantExceptionSpec(QualType T); - bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); - bool CheckEquivalentExceptionSpec( - const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, SourceLocation NewLoc); - bool CheckEquivalentExceptionSpec( - const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, - const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, SourceLocation NewLoc); - bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); - bool CheckExceptionSpecSubset( - const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, - const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, - const FunctionProtoType *Superset, bool SkipSupersetFirstParameter, - SourceLocation SuperLoc, const FunctionProtoType *Subset, - bool SkipSubsetFirstParameter, SourceLocation SubLoc); - bool CheckParamExceptionSpec( - const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, - const FunctionProtoType *Target, bool SkipTargetFirstParameter, - SourceLocation TargetLoc, const FunctionProtoType *Source, - bool SkipSourceFirstParameter, SourceLocation SourceLoc); + void CheckMemaccessArguments(const CallExpr *Call, unsigned BId, + IdentifierInfo *FnName); - TypeResult ActOnTypeName(Declarator &D); + void CheckStrlcpycatArguments(const CallExpr *Call, IdentifierInfo *FnName); - /// The parser has parsed the context-sensitive type 'instancetype' - /// in an Objective-C message declaration. Return the appropriate type. - ParsedType ActOnObjCInstanceType(SourceLocation Loc); + void CheckStrncatArguments(const CallExpr *Call, IdentifierInfo *FnName); - /// Abstract class used to diagnose incomplete types. - struct TypeDiagnoser { - TypeDiagnoser() {} + void CheckFreeArguments(const CallExpr *E); - virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0; - virtual ~TypeDiagnoser() {} - }; + void CheckReturnValExpr(Expr *RetValExp, QualType lhsType, + SourceLocation ReturnLoc, bool isObjCMethod = false, + const AttrVec *Attrs = nullptr, + const FunctionDecl *FD = nullptr); - static int getPrintable(int I) { return I; } - static unsigned getPrintable(unsigned I) { return I; } - static bool getPrintable(bool B) { return B; } - static const char * getPrintable(const char *S) { return S; } - static StringRef getPrintable(StringRef S) { return S; } - static const std::string &getPrintable(const std::string &S) { return S; } - static const IdentifierInfo *getPrintable(const IdentifierInfo *II) { - return II; - } - static DeclarationName getPrintable(DeclarationName N) { return N; } - static QualType getPrintable(QualType T) { return T; } - static SourceRange getPrintable(SourceRange R) { return R; } - static SourceRange getPrintable(SourceLocation L) { return L; } - static SourceRange getPrintable(const Expr *E) { return E->getSourceRange(); } - static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();} + void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); + void CheckBoolLikeConversion(Expr *E, SourceLocation CC); + void CheckForIntOverflow(const Expr *E); + void CheckUnsequencedOperations(const Expr *E); - template class BoundTypeDiagnoser : public TypeDiagnoser { - protected: - unsigned DiagID; - std::tuple Args; - - template - void emit(const SemaDiagnosticBuilder &DB, - std::index_sequence) const { - // Apply all tuple elements to the builder in order. - bool Dummy[] = {false, (DB << getPrintable(std::get(Args)))...}; - (void)Dummy; - } + /// Perform semantic checks on a completed expression. This will either + /// be a full-expression or a default argument expression. + void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(), + bool IsConstexpr = false); - public: - BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args) - : TypeDiagnoser(), DiagID(DiagID), Args(Args...) { - assert(DiagID != 0 && "no diagnostic for type diagnoser"); - } + void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field, + Expr *Init); + /// Check whether receiver is mutable ObjC container which + /// attempts to add itself into the container + void CheckObjCCircularContainer(ObjCMessageExpr *Message); - void diagnose(Sema &S, SourceLocation Loc, QualType T) override { - const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID); - emit(DB, std::index_sequence_for()); - DB << T; - } - }; + void CheckTCBEnforcement(const SourceLocation CallExprLoc, + const NamedDecl *Callee); - /// Do a check to make sure \p Name looks like a legal argument for the - /// swift_name attribute applied to decl \p D. Raise a diagnostic if the name - /// is invalid for the given declaration. - /// - /// \p AL is used to provide caret diagnostics in case of a malformed name. - /// - /// \returns true if the name is a valid swift name for \p D, false otherwise. - bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc, - const ParsedAttr &AL, bool IsAsync); + /// A map from magic value to type information. + std::unique_ptr> + TypeTagForDatatypeMagicValues; - /// A derivative of BoundTypeDiagnoser for which the diagnostic's type - /// parameter is preceded by a 0/1 enum that is 1 if the type is sizeless. - /// For example, a diagnostic with no other parameters would generally have - /// the form "...%select{incomplete|sizeless}0 type %1...". - template - class SizelessTypeDiagnoser : public BoundTypeDiagnoser { - public: - SizelessTypeDiagnoser(unsigned DiagID, const Ts &... Args) - : BoundTypeDiagnoser(DiagID, Args...) {} + /// Peform checks on a call of a function with argument_with_type_tag + /// or pointer_with_type_tag attributes. + void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, + const ArrayRef ExprArgs, + SourceLocation CallSiteLoc); - void diagnose(Sema &S, SourceLocation Loc, QualType T) override { - const SemaDiagnosticBuilder &DB = S.Diag(Loc, this->DiagID); - this->emit(DB, std::index_sequence_for()); - DB << T->isSizelessType() << T; - } - }; + /// Check if we are taking the address of a packed field + /// as this may be a problem if the pointer value is dereferenced. + void CheckAddressOfPackedMember(Expr *rhs); - enum class CompleteTypeKind { - /// Apply the normal rules for complete types. In particular, - /// treat all sizeless types as incomplete. - Normal, + /// Helper class that collects misaligned member designations and + /// their location info for delayed diagnostics. + struct MisalignedMember { + Expr *E; + RecordDecl *RD; + ValueDecl *MD; + CharUnits Alignment; - /// Relax the normal rules for complete types so that they include - /// sizeless built-in types. - AcceptSizeless, + MisalignedMember() : E(), RD(), MD() {} + MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD, + CharUnits Alignment) + : E(E), RD(RD), MD(MD), Alignment(Alignment) {} + explicit MisalignedMember(Expr *E) + : MisalignedMember(E, nullptr, nullptr, CharUnits()) {} - // FIXME: Eventually we should flip the default to Normal and opt in - // to AcceptSizeless rather than opt out of it. - Default = AcceptSizeless + bool operator==(const MisalignedMember &m) { return this->E == m.E; } }; + /// Small set of gathered accesses to potentially misaligned members + /// due to the packed attribute. + SmallVector MisalignedMembers; - enum class AcceptableKind { Visible, Reachable }; + /// Adds an expression to the set of gathered misaligned members. + void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD, + CharUnits Alignment); + ///@} -private: - /// Methods for marking which expressions involve dereferencing a pointer - /// marked with the 'noderef' attribute. Expressions are checked bottom up as - /// they are parsed, meaning that a noderef pointer may not be accessed. For - /// example, in `&*p` where `p` is a noderef pointer, we will first parse the - /// `*p`, but need to check that `address of` is called on it. This requires - /// keeping a container of all pending expressions and checking if the address - /// of them are eventually taken. - void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E); - void CheckAddressOfNoDeref(const Expr *E); - void CheckMemberAccessOfNoDeref(const MemberExpr *E); + // + // + // ------------------------------------------------------------------------- + // + // - bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, - CompleteTypeKind Kind, TypeDiagnoser *Diagnoser); + /// \name C++ Coroutines + /// Implementations are in SemaCoroutine.cpp + ///@{ - struct ModuleScope { - SourceLocation BeginLoc; - clang::Module *Module = nullptr; - VisibleModuleSet OuterVisibleModules; - }; - /// The modules we're currently parsing. - llvm::SmallVector ModuleScopes; +public: + /// The C++ "std::coroutine_traits" template, which is defined in + /// \ + ClassTemplateDecl *StdCoroutineTraitsCache; - /// For an interface unit, this is the implicitly imported interface unit. - clang::Module *ThePrimaryInterface = nullptr; + bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, + StringRef Keyword); + ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E); + ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E); + StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E); - /// The explicit global module fragment of the current translation unit. - /// The explicit Global Module Fragment, as specified in C++ - /// [module.global.frag]. - clang::Module *TheGlobalModuleFragment = nullptr; + ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc); + ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E, + UnresolvedLookupExpr *Lookup); + ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, + Expr *Awaiter, bool IsImplicit = false); + ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, + UnresolvedLookupExpr *Lookup); + ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E); + StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, + bool IsImplicit = false); + StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs); + bool buildCoroutineParameterMoves(SourceLocation Loc); + VarDecl *buildCoroutinePromise(SourceLocation Loc); + void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); - /// The implicit global module fragments of the current translation unit. - /// - /// The contents in the implicit global module fragment can't be discarded. - clang::Module *TheImplicitGlobalModuleFragment = nullptr; + // As a clang extension, enforces that a non-coroutine function must be marked + // with [[clang::coro_wrapper]] if it returns a type marked with + // [[clang::coro_return_type]]. + // Expects that FD is not a coroutine. + void CheckCoroutineWrapper(FunctionDecl *FD); + /// Lookup 'coroutine_traits' in std namespace and std::experimental + /// namespace. The namespace found is recorded in Namespace. + ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc); + /// Check that the expression co_await promise.final_suspend() shall not be + /// potentially-throwing. + bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend); - /// Namespace definitions that we will export when they finish. - llvm::SmallPtrSet DeferredExportedNamespaces; + ///@} - /// In a C++ standard module, inline declarations require a definition to be - /// present at the end of a definition domain. This set holds the decls to - /// be checked at the end of the TU. - llvm::SmallPtrSet PendingInlineFuncDecls; + // + // + // ------------------------------------------------------------------------- + // + // - /// Helper function to judge if we are in module purview. - /// Return false if we are not in a module. - bool isCurrentModulePurview() const; + /// \name C++ Scope Specifiers + /// Implementations are in SemaCXXScopeSpec.cpp + ///@{ - /// Enter the scope of the explicit global module fragment. - Module *PushGlobalModuleFragment(SourceLocation BeginLoc); - /// Leave the scope of the explicit global module fragment. - void PopGlobalModuleFragment(); +public: + // Marks SS invalid if it represents an incomplete type. + bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC); + // Complete an enum decl, maybe without a scope spec. + bool RequireCompleteEnumDecl(EnumDecl *D, SourceLocation L, + CXXScopeSpec *SS = nullptr); - /// Enter the scope of an implicit global module fragment. - Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc); - /// Leave the scope of an implicit global module fragment. - void PopImplicitGlobalModuleFragment(); + DeclContext *computeDeclContext(QualType T); + DeclContext *computeDeclContext(const CXXScopeSpec &SS, + bool EnteringContext = false); + bool isDependentScopeSpecifier(const CXXScopeSpec &SS); + CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); - VisibleModuleSet VisibleModules; + /// The parser has parsed a global nested-name-specifier '::'. + /// + /// \param CCLoc The location of the '::'. + /// + /// \param SS The nested-name-specifier, which will be updated in-place + /// to reflect the parsed nested-name-specifier. + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS); - /// Cache for module units which is usable for current module. - llvm::DenseSet UsableModuleUnitsCache; + /// The parser has parsed a '__super' nested-name-specifier. + /// + /// \param SuperLoc The location of the '__super' keyword. + /// + /// \param ColonColonLoc The location of the '::'. + /// + /// \param SS The nested-name-specifier, which will be updated in-place + /// to reflect the parsed nested-name-specifier. + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc, + SourceLocation ColonColonLoc, CXXScopeSpec &SS); - bool isUsableModule(const Module *M); + bool isAcceptableNestedNameSpecifier(const NamedDecl *SD, + bool *CanCorrect = nullptr); + NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); - bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind); + /// Keeps information about an identifier in a nested-name-spec. + /// + struct NestedNameSpecInfo { + /// The type of the object, if we're parsing nested-name-specifier in + /// a member access expression. + ParsedType ObjectType; -public: - /// Get the module unit whose scope we are currently within. - Module *getCurrentModule() const { - return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module; - } + /// The identifier preceding the '::'. + IdentifierInfo *Identifier; - /// Is the module scope we are an implementation unit? - bool currentModuleIsImplementation() const { - return ModuleScopes.empty() - ? false - : ModuleScopes.back().Module->isModuleImplementation(); - } + /// The location of the identifier. + SourceLocation IdentifierLoc; - /// Is the module scope we are in a C++ Header Unit? - bool currentModuleIsHeaderUnit() const { - return ModuleScopes.empty() ? false - : ModuleScopes.back().Module->isHeaderUnit(); - } + /// The location of the '::'. + SourceLocation CCLoc; - /// Get the module owning an entity. - Module *getOwningModule(const Decl *Entity) { - return Entity->getOwningModule(); - } + /// Creates info object for the most typical case. + NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc, + SourceLocation ColonColonLoc, + ParsedType ObjectType = ParsedType()) + : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc), + CCLoc(ColonColonLoc) {} - /// Make a merged definition of an existing hidden definition \p ND - /// visible at the specified location. - void makeMergedDefinitionVisible(NamedDecl *ND); + NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc, + SourceLocation ColonColonLoc, QualType ObjectType) + : ObjectType(ParsedType::make(ObjectType)), Identifier(II), + IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {} + }; - bool isModuleVisible(const Module *M, bool ModulePrivate = false); + bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, + bool EnteringContext, CXXScopeSpec &SS, + NamedDecl *ScopeLookupResult, + bool ErrorRecoveryLookup, + bool *IsCorrectedToColon = nullptr, + bool OnlyNamespace = false); - // When loading a non-modular PCH files, this is used to restore module - // visibility. - void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) { - VisibleModules.setVisible(Mod, ImportLoc); - } + /// The parser has parsed a nested-name-specifier 'identifier::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param IdInfo Parser information about an identifier in the + /// nested-name-spec. + /// + /// \param EnteringContext Whether we're entering the context nominated by + /// this nested-name-specifier. + /// + /// \param SS The nested-name-specifier, which is both an input + /// parameter (the nested-name-specifier before this type) and an + /// output parameter (containing the full nested-name-specifier, + /// including this new type). + /// + /// \param IsCorrectedToColon If not null, suggestions to replace '::' -> ':' + /// are allowed. The bool value pointed by this parameter is set to 'true' + /// if the identifier is treated as if it was followed by ':', not '::'. + /// + /// \param OnlyNamespace If true, only considers namespaces in lookup. + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, + bool EnteringContext, CXXScopeSpec &SS, + bool *IsCorrectedToColon = nullptr, + bool OnlyNamespace = false); - /// Determine whether a declaration is visible to name lookup. - bool isVisible(const NamedDecl *D) { - return D->isUnconditionallyVisible() || - isAcceptableSlow(D, AcceptableKind::Visible); - } + /// The parser has parsed a nested-name-specifier + /// 'template[opt] template-name < template-args >::'. + /// + /// \param S The scope in which this nested-name-specifier occurs. + /// + /// \param SS The nested-name-specifier, which is both an input + /// parameter (the nested-name-specifier before this type) and an + /// output parameter (containing the full nested-name-specifier, + /// including this new type). + /// + /// \param TemplateKWLoc the location of the 'template' keyword, if any. + /// \param TemplateName the template name. + /// \param TemplateNameLoc The location of the template name. + /// \param LAngleLoc The location of the opening angle bracket ('<'). + /// \param TemplateArgs The template arguments. + /// \param RAngleLoc The location of the closing angle bracket ('>'). + /// \param CCLoc The location of the '::'. + /// + /// \param EnteringContext Whether we're entering the context of the + /// nested-name-specifier. + /// + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnCXXNestedNameSpecifier( + Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + TemplateTy TemplateName, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, SourceLocation CCLoc, bool EnteringContext); - /// Determine whether a declaration is reachable. - bool isReachable(const NamedDecl *D) { - // All visible declarations are reachable. - return D->isUnconditionallyVisible() || - isAcceptableSlow(D, AcceptableKind::Reachable); - } + bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, const DeclSpec &DS, + SourceLocation ColonColonLoc); - /// Determine whether a declaration is acceptable (visible/reachable). - bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) { - return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D); - } + bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS, + const DeclSpec &DS, + SourceLocation ColonColonLoc, + QualType Type); - /// Determine whether any declaration of an entity is visible. - bool - hasVisibleDeclaration(const NamedDecl *D, - llvm::SmallVectorImpl *Modules = nullptr) { - return isVisible(D) || hasVisibleDeclarationSlow(D, Modules); - } + bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, + NestedNameSpecInfo &IdInfo, + bool EnteringContext); - bool hasVisibleDeclarationSlow(const NamedDecl *D, - llvm::SmallVectorImpl *Modules); - /// Determine whether any declaration of an entity is reachable. - bool - hasReachableDeclaration(const NamedDecl *D, - llvm::SmallVectorImpl *Modules = nullptr) { - return isReachable(D) || hasReachableDeclarationSlow(D, Modules); - } - bool hasReachableDeclarationSlow( - const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); + /// Given a C++ nested-name-specifier, produce an annotation value + /// that the parser can use later to reconstruct the given + /// nested-name-specifier. + /// + /// \param SS A nested-name-specifier. + /// + /// \returns A pointer containing all of the information in the + /// nested-name-specifier \p SS. + void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS); - bool hasVisibleMergedDefinition(const NamedDecl *Def); - bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def); + /// Given an annotation pointer for a nested-name-specifier, restore + /// the nested-name-specifier structure. + /// + /// \param Annotation The annotation pointer, produced by + /// \c SaveNestedNameSpecifierAnnotation(). + /// + /// \param AnnotationRange The source range corresponding to the annotation. + /// + /// \param SS The nested-name-specifier that will be updated with the contents + /// of the annotation pointer. + void RestoreNestedNameSpecifierAnnotation(void *Annotation, + SourceRange AnnotationRange, + CXXScopeSpec &SS); - /// Determine if \p D and \p Suggested have a structurally compatible - /// layout as described in C11 6.2.7/1. - bool hasStructuralCompatLayout(Decl *D, Decl *Suggested); + bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS); - /// Determine if \p D has a visible definition. If not, suggest a declaration - /// that should be made visible to expose the definition. - bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, - bool OnlyNeedComplete = false); - bool hasVisibleDefinition(const NamedDecl *D) { - NamedDecl *Hidden; - return hasVisibleDefinition(const_cast(D), &Hidden); - } + /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global + /// scope or nested-name-specifier) is parsed, part of a declarator-id. + /// After this method is called, according to [C++ 3.4.3p3], names should be + /// looked up in the declarator-id's scope, until the declarator is parsed and + /// ActOnCXXExitDeclaratorScope is called. + /// The 'SS' should be a non-empty valid CXXScopeSpec. + bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS); - /// Determine if \p D has a reachable definition. If not, suggest a - /// declaration that should be made reachable to expose the definition. - bool hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested, - bool OnlyNeedComplete = false); - bool hasReachableDefinition(NamedDecl *D) { - NamedDecl *Hidden; - return hasReachableDefinition(D, &Hidden); - } + /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously + /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same + /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. + /// Used to indicate that names should revert to being looked up in the + /// defining scope. + void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS); - bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested, - AcceptableKind Kind, - bool OnlyNeedComplete = false); - bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) { - NamedDecl *Hidden; - return hasAcceptableDefinition(D, &Hidden, Kind); - } + ///@} - /// Determine if the template parameter \p D has a visible default argument. - bool - hasVisibleDefaultArgument(const NamedDecl *D, - llvm::SmallVectorImpl *Modules = nullptr); - /// Determine if the template parameter \p D has a reachable default argument. - bool hasReachableDefaultArgument( - const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); - /// Determine if the template parameter \p D has a reachable default argument. - bool hasAcceptableDefaultArgument(const NamedDecl *D, - llvm::SmallVectorImpl *Modules, - Sema::AcceptableKind Kind); + // + // + // ------------------------------------------------------------------------- + // + // - /// Determine if there is a visible declaration of \p D that is an explicit - /// specialization declaration for a specialization of a template. (For a - /// member specialization, use hasVisibleMemberSpecialization.) - bool hasVisibleExplicitSpecialization( - const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); - /// Determine if there is a reachable declaration of \p D that is an explicit - /// specialization declaration for a specialization of a template. (For a - /// member specialization, use hasReachableMemberSpecialization.) - bool hasReachableExplicitSpecialization( - const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); + /// \name Declarations + /// Implementations are in SemaDecl.cpp + ///@{ - /// Determine if there is a visible declaration of \p D that is a member - /// specialization declaration (as opposed to an instantiated declaration). - bool hasVisibleMemberSpecialization( - const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); - /// Determine if there is a reachable declaration of \p D that is a member - /// specialization declaration (as opposed to an instantiated declaration). - bool hasReachableMemberSpecialization( - const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); +public: + IdentifierResolver IdResolver; - /// Determine if \p A and \p B are equivalent internal linkage declarations - /// from different modules, and thus an ambiguity error can be downgraded to - /// an extension warning. - bool isEquivalentInternalLinkageDeclaration(const NamedDecl *A, - const NamedDecl *B); - void diagnoseEquivalentInternalLinkageDeclarations( - SourceLocation Loc, const NamedDecl *D, - ArrayRef Equiv); + /// The index of the first InventedParameterInfo that refers to the current + /// context. + unsigned InventedParameterInfosStart = 0; - bool isUsualDeallocationFunction(const CXXMethodDecl *FD); + /// A RAII object to temporarily push a declaration context. + class ContextRAII { + private: + Sema &S; + DeclContext *SavedContext; + ProcessingContextState SavedContextState; + QualType SavedCXXThisTypeOverride; + unsigned SavedFunctionScopesStart; + unsigned SavedInventedParameterInfosStart; - // Check whether the size of array element of type \p EltTy is a multiple of - // its alignment and return false if it isn't. - bool checkArrayElementAlignment(QualType EltTy, SourceLocation Loc); + public: + ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true) + : S(S), SavedContext(S.CurContext), + SavedContextState(S.DelayedDiagnostics.pushUndelayed()), + SavedCXXThisTypeOverride(S.CXXThisTypeOverride), + SavedFunctionScopesStart(S.FunctionScopesStart), + SavedInventedParameterInfosStart(S.InventedParameterInfosStart) { + assert(ContextToPush && "pushing null context"); + S.CurContext = ContextToPush; + if (NewThisContext) + S.CXXThisTypeOverride = QualType(); + // Any saved FunctionScopes do not refer to this context. + S.FunctionScopesStart = S.FunctionScopes.size(); + S.InventedParameterInfosStart = S.InventedParameterInfos.size(); + } - bool isCompleteType(SourceLocation Loc, QualType T, - CompleteTypeKind Kind = CompleteTypeKind::Default) { - return !RequireCompleteTypeImpl(Loc, T, Kind, nullptr); - } - bool RequireCompleteType(SourceLocation Loc, QualType T, - CompleteTypeKind Kind, TypeDiagnoser &Diagnoser); - bool RequireCompleteType(SourceLocation Loc, QualType T, - CompleteTypeKind Kind, unsigned DiagID); + void pop() { + if (!SavedContext) + return; + S.CurContext = SavedContext; + S.DelayedDiagnostics.popUndelayed(SavedContextState); + S.CXXThisTypeOverride = SavedCXXThisTypeOverride; + S.FunctionScopesStart = SavedFunctionScopesStart; + S.InventedParameterInfosStart = SavedInventedParameterInfosStart; + SavedContext = nullptr; + } - bool RequireCompleteType(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser) { - return RequireCompleteType(Loc, T, CompleteTypeKind::Default, Diagnoser); - } - bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID) { - return RequireCompleteType(Loc, T, CompleteTypeKind::Default, DiagID); - } + ~ContextRAII() { pop(); } + }; - template - bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID, - const Ts &...Args) { - BoundTypeDiagnoser Diagnoser(DiagID, Args...); - return RequireCompleteType(Loc, T, Diagnoser); - } + void DiagnoseInvalidJumps(Stmt *Body); - template - bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID, - const Ts &... Args) { - SizelessTypeDiagnoser Diagnoser(DiagID, Args...); - return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser); - } + /// The function definitions which were renamed as part of typo-correction + /// to match their respective declarations. We want to keep track of them + /// to ensure that we don't emit a "redefinition" error if we encounter a + /// correctly named definition after the renamed definition. + llvm::SmallPtrSet TypoCorrectedFunctionDefinitions; - /// Get the type of expression E, triggering instantiation to complete the - /// type if necessary -- that is, if the expression refers to a templated - /// static data member of incomplete array type. - /// - /// May still return an incomplete type if instantiation was not possible or - /// if the type is incomplete for a different reason. Use - /// RequireCompleteExprType instead if a diagnostic is expected for an - /// incomplete expression type. - QualType getCompletedType(Expr *E); + /// A cache of the flags available in enumerations with the flag_bits + /// attribute. + mutable llvm::DenseMap FlagBitsCache; - void completeExprArrayBound(Expr *E); - bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind, - TypeDiagnoser &Diagnoser); - bool RequireCompleteExprType(Expr *E, unsigned DiagID); + /// WeakUndeclaredIdentifiers - Identifiers contained in \#pragma weak before + /// declared. Rare. May alias another identifier, declared or undeclared. + /// + /// For aliases, the target identifier is used as a key for eventual + /// processing when the target is declared. For the single-identifier form, + /// the sole identifier is used as the key. Each entry is a `SetVector` + /// (ordered by parse order) of aliases (identified by the alias name) in case + /// of multiple aliases to the same undeclared identifier. + llvm::MapVector< + IdentifierInfo *, + llvm::SetVector< + WeakInfo, llvm::SmallVector, + llvm::SmallDenseSet>> + WeakUndeclaredIdentifiers; - template - bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) { - BoundTypeDiagnoser Diagnoser(DiagID, Args...); - return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser); - } + /// ExtnameUndeclaredIdentifiers - Identifiers contained in + /// \#pragma redefine_extname before declared. Used in Solaris system headers + /// to define functions that occur in multiple standards to call the version + /// in the currently selected standard. + llvm::DenseMap ExtnameUndeclaredIdentifiers; - template - bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID, - const Ts &... Args) { - SizelessTypeDiagnoser Diagnoser(DiagID, Args...); - return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser); - } + /// Set containing all typedefs that are likely unused. + llvm::SmallSetVector + UnusedLocalTypedefNameCandidates; - bool RequireLiteralType(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser); - bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID); + typedef LazyVector + UnusedFileScopedDeclsType; - template - bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID, - const Ts &...Args) { - BoundTypeDiagnoser Diagnoser(DiagID, Args...); - return RequireLiteralType(Loc, T, Diagnoser); - } + /// The set of file scoped decls seen so far that have not been used + /// and must warn if not used. Only contains the first declaration. + UnusedFileScopedDeclsType UnusedFileScopedDecls; - QualType getElaboratedType(ElaboratedTypeKeyword Keyword, - const CXXScopeSpec &SS, QualType T, - TagDecl *OwnedTagDecl = nullptr); + typedef LazyVector + TentativeDefinitionsType; - // Returns the underlying type of a decltype with the given expression. - QualType getDecltypeForExpr(Expr *E); + /// All the tentative definitions encountered in the TU. + TentativeDefinitionsType TentativeDefinitions; - QualType BuildTypeofExprType(Expr *E, TypeOfKind Kind); - /// If AsUnevaluated is false, E is treated as though it were an evaluated - /// context, such as when building a type for decltype(auto). - QualType BuildDecltypeType(Expr *E, bool AsUnevaluated = true); + /// All the external declarations encoutered and used in the TU. + SmallVector ExternalDeclarations; - QualType ActOnPackIndexingType(QualType Pattern, Expr *IndexExpr, - SourceLocation Loc, - SourceLocation EllipsisLoc); - QualType BuildPackIndexingType(QualType Pattern, Expr *IndexExpr, - SourceLocation Loc, SourceLocation EllipsisLoc, - bool FullySubstituted = false, - ArrayRef Expansions = {}); + /// Generally null except when we temporarily switch decl contexts, + /// like in \see ActOnObjCTemporaryExitContainerContext. + DeclContext *OriginalLexicalContext; - using UTTKind = UnaryTransformType::UTTKind; - QualType BuildUnaryTransformType(QualType BaseType, UTTKind UKind, - SourceLocation Loc); - QualType BuiltinEnumUnderlyingType(QualType BaseType, SourceLocation Loc); - QualType BuiltinAddPointer(QualType BaseType, SourceLocation Loc); - QualType BuiltinRemovePointer(QualType BaseType, SourceLocation Loc); - QualType BuiltinDecay(QualType BaseType, SourceLocation Loc); - QualType BuiltinAddReference(QualType BaseType, UTTKind UKind, - SourceLocation Loc); - QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind, - SourceLocation Loc); - QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind, - SourceLocation Loc); - QualType BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind, - SourceLocation Loc); - QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind, - SourceLocation Loc); + /// Is the module scope we are in a C++ Header Unit? + bool currentModuleIsHeaderUnit() const { + return ModuleScopes.empty() ? false + : ModuleScopes.back().Module->isHeaderUnit(); + } - //===--------------------------------------------------------------------===// - // Symbol table / Decl tracking callbacks: SemaDecl.cpp. - // + /// Get the module owning an entity. + Module *getOwningModule(const Decl *Entity) { + return Entity->getOwningModule(); + } struct SkipBodyInfo { SkipBodyInfo() = default; @@ -2751,8 +2786,6 @@ class Sema final { DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr); - void DiagnoseUseOfUnimplementedSelectors(); - ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS = nullptr, bool isClassName = false, bool HasTrailingDot = false, @@ -2765,10 +2798,8 @@ class Sema final { IdentifierInfo **CorrectedII = nullptr); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S); - void DiagnoseUnknownTypeName(IdentifierInfo *&II, - SourceLocation IILoc, - Scope *S, - CXXScopeSpec *SS, + void DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc, + Scope *S, CXXScopeSpec *SS, ParsedType &SuggestedType, bool IsTemplateName = false); @@ -2837,9 +2868,7 @@ class Sema final { NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {} - static NameClassification Error() { - return NameClassification(NC_Error); - } + static NameClassification Error() { return NameClassification(NC_Error); } static NameClassification Unknown() { return NameClassification(NC_Unknown); @@ -3013,9 +3042,6 @@ class Sema final { // diagnoseExprIntendedAsTemplateName. return false; } - void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, - SourceLocation Less, - SourceLocation Greater); void warnOnReservedIdentifier(const NamedDecl *D); @@ -3023,8 +3049,8 @@ class Sema final { NamedDecl *HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists); - bool tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, - QualType &T, SourceLocation Loc, + bool tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, QualType &T, + SourceLocation Loc, unsigned FailedFoldDiagID); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S); bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); @@ -3032,16 +3058,7 @@ class Sema final { DeclarationName Name, SourceLocation Loc, TemplateIdAnnotation *TemplateId, bool IsMemberSpecialization); - void - diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, - SourceLocation FallbackLoc, - SourceLocation ConstQualLoc = SourceLocation(), - SourceLocation VolatileQualLoc = SourceLocation(), - SourceLocation RestrictQualLoc = SourceLocation(), - SourceLocation AtomicQualLoc = SourceLocation(), - SourceLocation UnalignedQualLoc = SourceLocation()); - static bool adjustContextForLocalExternDecl(DeclContext *&DC); void DiagnoseFunctionSpecifiers(const DeclSpec &DS); NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D, const LookupResult &R); @@ -3058,68 +3075,35 @@ class Sema final { void DiagnoseShadowingLambdaDecls(const sema::LambdaScopeInfo *LSI); -private: - /// Map of current shadowing declarations to shadowed declarations. Warn if - /// it looks like the user is trying to modify the shadowing declaration. - llvm::DenseMap ShadowingDecls; - -public: - void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); void handleTagNumbering(const TagDecl *Tag, Scope *TagScope); void setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec, TypedefNameDecl *NewTD); void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D); - NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, + NamedDecl *ActOnTypedefDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous); - NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D, + NamedDecl *ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *D, LookupResult &Previous, bool &Redeclaration); NamedDecl *ActOnVariableDeclarator( Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &AddToScope, ArrayRef Bindings = std::nullopt); - NamedDecl * - ActOnDecompositionDeclarator(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParamLists); - void DiagPlaceholderVariableDefinition(SourceLocation Loc); - bool DiagRedefinedPlaceholderFieldDecl(SourceLocation Loc, - RecordDecl *ClassDecl, - const IdentifierInfo *Name); + // Returns true if the variable declaration is a redeclaration bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckVariableDeclarationType(VarDecl *NewVD); - bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, - Expr *Init); void CheckCompleteVariableDeclaration(VarDecl *VD); - void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD); - void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); - NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, + NamedDecl *ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &AddToScope); bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); - enum class CheckConstexprKind { - /// Diagnose issues that are non-constant or that are extensions. - Diagnose, - /// Identify whether this function satisfies the formal rules for constexpr - /// functions in the current lanugage mode (with no extensions). - CheckValid - }; - - bool CheckConstexprFunctionDefinition(const FunctionDecl *FD, - CheckConstexprKind Kind); - - void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD); - void FindHiddenVirtualMethods(CXXMethodDecl *MD, - SmallVectorImpl &OverloadedMethods); - void NoteHiddenVirtualMethods(CXXMethodDecl *MD, - SmallVectorImpl &OverloadedMethods); // Returns true if the function declaration is a redeclaration - bool CheckFunctionDeclaration(Scope *S, - FunctionDecl *NewFD, LookupResult &Previous, + bool CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, + LookupResult &Previous, bool IsMemberSpecialization, bool DeclIsDefn); bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl); bool canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD, @@ -3138,8 +3122,7 @@ class Sema final { void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); Decl *ActOnParamDeclarator(Scope *S, Declarator &D, SourceLocation ExplicitThisLoc = {}); - ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, - SourceLocation Loc, + ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); QualType AdjustParameterTypeForObjCAutoRefCount(QualType T, SourceLocation NameLoc, @@ -3148,17 +3131,6 @@ class Sema final { SourceLocation NameLoc, IdentifierInfo *Name, QualType T, TypeSourceInfo *TSInfo, StorageClass SC); - void ActOnParamDefaultArgument(Decl *param, - SourceLocation EqualLoc, - Expr *defarg); - void ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc, - SourceLocation ArgLoc); - void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc, - Expr* DefaultArg); - ExprResult ConvertParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, - SourceLocation EqualLoc); - void SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, - SourceLocation EqualLoc); // Contexts where using non-trivial C union types can be disallowed. This is // passed to err_non_trivial_c_union_in_invalid_context. @@ -3206,13 +3178,11 @@ class Sema final { void ActOnUninitializedDecl(Decl *dcl); void ActOnInitializerError(Decl *Dcl); - void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); void ActOnCXXForRangeDecl(Decl *D); StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, IdentifierInfo *Ident, ParsedAttributes &Attrs); - void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); - void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc); + void CheckStaticLocalForDllExport(VarDecl *VD); void CheckThreadLocalForLargeAlignment(VarDecl *VD); void FinalizeDeclaration(Decl *D); @@ -3249,14 +3219,6 @@ class Sema final { Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D, SkipBodyInfo *SkipBody = nullptr, FnBodyKind BodyKind = FnBodyKind::Other); - void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind); - void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D); - ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr); - ExprResult ActOnRequiresClause(ExprResult ConstraintExpr); - void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); - bool isObjCMethodDecl(Decl *D) { - return D && isa(D); - } /// Determine whether we can delay parsing the body of a function or /// function template until it is used, assuming we don't care about emitting @@ -3277,10 +3239,6 @@ class Sema final { /// \c constexpr in C++11 or has an 'auto' return type in C++14). bool canSkipFunctionBody(Decl *D); - /// Determine whether \param D is function like (function or function - /// template) for parsing. - bool isDeclaratorFunctionLike(Declarator &D); - void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); @@ -3302,159 +3260,29 @@ class Sema final { DiagnoseSizeOfParametersAndReturnValue(ArrayRef Parameters, QualType ReturnTy, NamedDecl *D); - void DiagnoseInvalidJumps(Stmt *Body); - Decl *ActOnFileScopeAsmDecl(Expr *expr, - SourceLocation AsmLoc, + Decl *ActOnFileScopeAsmDecl(Expr *expr, SourceLocation AsmLoc, SourceLocation RParenLoc); Decl *ActOnTopLevelStmtDecl(Stmt *Statement); - /// Handle a C++11 empty-declaration and attribute-declaration. - Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList, - SourceLocation SemiLoc); + void ActOnPopScope(SourceLocation Loc, Scope *S); - enum class ModuleDeclKind { - Interface, ///< 'export module X;' - Implementation, ///< 'module X;' - PartitionInterface, ///< 'export module X:Y;' - PartitionImplementation, ///< 'module X:Y;' - }; + Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, + const ParsedAttributesView &DeclAttrs, + RecordDecl *&AnonRecord); + Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, + const ParsedAttributesView &DeclAttrs, + MultiTemplateParamsArg TemplateParams, + bool IsExplicitInstantiation, + RecordDecl *&AnonRecord); - /// An enumeration to represent the transition of states in parsing module - /// fragments and imports. If we are not parsing a C++20 TU, or we find - /// an error in state transition, the state is set to NotACXX20Module. - enum class ModuleImportState { - FirstDecl, ///< Parsing the first decl in a TU. - GlobalFragment, ///< after 'module;' but before 'module X;' - ImportAllowed, ///< after 'module X;' but before any non-import decl. - ImportFinished, ///< after any non-import decl. - PrivateFragmentImportAllowed, ///< after 'module :private;' but before any - ///< non-import decl. - PrivateFragmentImportFinished, ///< after 'module :private;' but a - ///< non-import decl has already been seen. - NotACXX20Module ///< Not a C++20 TU, or an invalid state was found. - }; + Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, + RecordDecl *Record, + const PrintingPolicy &Policy); -private: - /// The parser has begun a translation unit to be compiled as a C++20 - /// Header Unit, helper for ActOnStartOfTranslationUnit() only. - void HandleStartOfHeaderUnit(); - -public: - /// The parser has processed a module-declaration that begins the definition - /// of a module interface or implementation. - DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc, - SourceLocation ModuleLoc, ModuleDeclKind MDK, - ModuleIdPath Path, ModuleIdPath Partition, - ModuleImportState &ImportState); - - /// The parser has processed a global-module-fragment declaration that begins - /// the definition of the global module fragment of the current module unit. - /// \param ModuleLoc The location of the 'module' keyword. - DeclGroupPtrTy ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc); - - /// The parser has processed a private-module-fragment declaration that begins - /// the definition of the private module fragment of the current module unit. - /// \param ModuleLoc The location of the 'module' keyword. - /// \param PrivateLoc The location of the 'private' keyword. - DeclGroupPtrTy ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc, - SourceLocation PrivateLoc); - - /// The parser has processed a module import declaration. - /// - /// \param StartLoc The location of the first token in the declaration. This - /// could be the location of an '@', 'export', or 'import'. - /// \param ExportLoc The location of the 'export' keyword, if any. - /// \param ImportLoc The location of the 'import' keyword. - /// \param Path The module toplevel name as an access path. - /// \param IsPartition If the name is for a partition. - DeclResult ActOnModuleImport(SourceLocation StartLoc, - SourceLocation ExportLoc, - SourceLocation ImportLoc, ModuleIdPath Path, - bool IsPartition = false); - DeclResult ActOnModuleImport(SourceLocation StartLoc, - SourceLocation ExportLoc, - SourceLocation ImportLoc, Module *M, - ModuleIdPath Path = {}); - - /// The parser has processed a module import translated from a - /// #include or similar preprocessing directive. - void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); - void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod); - - /// The parsed has entered a submodule. - void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod); - /// The parser has left a submodule. - void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod); - - /// Create an implicit import of the given module at the given - /// source location, for error recovery, if possible. - /// - /// This routine is typically used when an entity found by name lookup - /// is actually hidden within a module that we know about but the user - /// has forgotten to import. - void createImplicitModuleImportForErrorRecovery(SourceLocation Loc, - Module *Mod); - - /// Kinds of missing import. Note, the values of these enumerators correspond - /// to %select values in diagnostics. - enum class MissingImportKind { - Declaration, - Definition, - DefaultArgument, - ExplicitSpecialization, - PartialSpecialization - }; - - /// Diagnose that the specified declaration needs to be visible but - /// isn't, and suggest a module import that would resolve the problem. - void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl, - MissingImportKind MIK, bool Recover = true); - void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl, - SourceLocation DeclLoc, ArrayRef Modules, - MissingImportKind MIK, bool Recover); - - Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, - SourceLocation LBraceLoc); - Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl, - SourceLocation RBraceLoc); - - /// We've found a use of a templated declaration that would trigger an - /// implicit instantiation. Check that any relevant explicit specializations - /// and partial specializations are visible/reachable, and diagnose if not. - void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec); - void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec); - - /// Retrieve a suitable printing policy for diagnostics. - PrintingPolicy getPrintingPolicy() const { - return getPrintingPolicy(Context, PP); - } - - /// Retrieve a suitable printing policy for diagnostics. - static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx, - const Preprocessor &PP); - - /// Scope actions. - void ActOnPopScope(SourceLocation Loc, Scope *S); - void ActOnTranslationUnitScope(Scope *S); - - Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, - const ParsedAttributesView &DeclAttrs, - RecordDecl *&AnonRecord); - Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, - const ParsedAttributesView &DeclAttrs, - MultiTemplateParamsArg TemplateParams, - bool IsExplicitInstantiation, - RecordDecl *&AnonRecord); - - Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, - AccessSpecifier AS, - RecordDecl *Record, - const PrintingPolicy &Policy); - - /// Called once it is known whether - /// a tag declaration is an anonymous union or struct. - void ActOnDefinedDeclarationSpecifier(Decl *D); + /// Called once it is known whether + /// a tag declaration is an anonymous union or struct. + void ActOnDefinedDeclarationSpecifier(Decl *D); void DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record); @@ -3479,9 +3307,8 @@ class Sema final { /// what kind of non-tag type this is. NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK); - bool isAcceptableTagRedeclaration(const TagDecl *Previous, - TagTypeKind NewTag, bool isDefinition, - SourceLocation NewTagLoc, + bool isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag, + bool isDefinition, SourceLocation NewTagLoc, const IdentifierInfo *Name); enum TagUseKind { @@ -3513,106 +3340,21 @@ class Sema final { bool IsTypeSpecifier, bool IsTemplateParamOrArg, OffsetOfKind OOK, SkipBodyInfo *SkipBody = nullptr); - DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, - unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, IdentifierInfo *Name, - SourceLocation NameLoc, - const ParsedAttributesView &Attr, - MultiTemplateParamsArg TempParamLists); - - TypeResult ActOnDependentTag(Scope *S, - unsigned TagSpec, - TagUseKind TUK, - const CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation TagLoc, - SourceLocation NameLoc); - - void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, - IdentifierInfo *ClassName, - SmallVectorImpl &Decls); Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth); FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth, - InClassInitStyle InitStyle, - AccessSpecifier AS); - MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD, - SourceLocation DeclStart, Declarator &D, - Expr *BitfieldWidth, - InClassInitStyle InitStyle, - AccessSpecifier AS, - const ParsedAttr &MSPropertyAttr); + InClassInitStyle InitStyle, AccessSpecifier AS); FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, - TypeSourceInfo *TInfo, - RecordDecl *Record, SourceLocation Loc, - bool Mutable, Expr *BitfieldWidth, - InClassInitStyle InitStyle, - SourceLocation TSSL, - AccessSpecifier AS, NamedDecl *PrevDecl, - Declarator *D = nullptr); + TypeSourceInfo *TInfo, RecordDecl *Record, + SourceLocation Loc, bool Mutable, + Expr *BitfieldWidth, InClassInitStyle InitStyle, + SourceLocation TSSL, AccessSpecifier AS, + NamedDecl *PrevDecl, Declarator *D = nullptr); bool CheckNontrivialField(FieldDecl *FD); - void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); - - enum TrivialABIHandling { - /// The triviality of a method unaffected by "trivial_abi". - TAH_IgnoreTrivialABI, - - /// The triviality of a method affected by "trivial_abi". - TAH_ConsiderTrivialABI - }; - - bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, - TrivialABIHandling TAH = TAH_IgnoreTrivialABI, - bool Diagnose = false); - - /// For a defaulted function, the kind of defaulted function that it is. - class DefaultedFunctionKind { - unsigned SpecialMember : 8; - unsigned Comparison : 8; - - public: - DefaultedFunctionKind() - : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) { - } - DefaultedFunctionKind(CXXSpecialMember CSM) - : SpecialMember(CSM), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} - DefaultedFunctionKind(DefaultedComparisonKind Comp) - : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(Comp)) {} - - bool isSpecialMember() const { return SpecialMember != CXXInvalid; } - bool isComparison() const { - return static_cast(Comparison) != DefaultedComparisonKind::None; - } - - explicit operator bool() const { - return isSpecialMember() || isComparison(); - } - - CXXSpecialMember asSpecialMember() const { return static_cast(SpecialMember); } - DefaultedComparisonKind asComparison() const { return static_cast(Comparison); } - - /// Get the index of this function kind for use in diagnostics. - unsigned getDiagnosticIndex() const { - static_assert(CXXInvalid > CXXDestructor, - "invalid should have highest index"); - static_assert((unsigned)DefaultedComparisonKind::None == 0, - "none should be equal to zero"); - return SpecialMember + Comparison; - } - }; - - DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD); - - CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) { - return getDefaultedFunctionKind(MD).asSpecialMember(); - } - DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) { - return getDefaultedFunctionKind(FD).asComparison(); - } void ActOnLastBitfield(SourceLocation DeclStart, SmallVectorImpl &AllIvarDecls); @@ -3634,20 +3376,6 @@ class Sema final { /// in case of a structural mismatch. bool ActOnDuplicateDefinition(Decl *Prev, SkipBodyInfo &SkipBody); - /// Check ODR hashes for C/ObjC when merging types from modules. - /// Differently from C++, actually parse the body and reject in case - /// of a mismatch. - template ::value>> - bool ActOnDuplicateODRHashDefinition(T *Duplicate, T *Previous) { - if (Duplicate->getODRHash() != Previous->getODRHash()) - return false; - - // Make the previous decl visible. - makeMergedDefinitionVisible(Previous); - return true; - } - typedef void *SkippedDefinitionContext; /// Invoked when we enter a tag definition that we're skipping. @@ -3686,8 +3414,7 @@ class Sema final { EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum, EnumConstantDecl *LastEnumConst, - SourceLocation IdLoc, - IdentifierInfo *Id, + SourceLocation IdLoc, IdentifierInfo *Id, Expr *val); bool CheckEnumUnderlyingType(TypeSourceInfo *TI); bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, @@ -3716,34 +3443,15 @@ class Sema final { void EnterDeclaratorContext(Scope *S, DeclContext *DC); void ExitDeclaratorContext(Scope *S); - /// Enter a template parameter scope, after it's been associated with a particular - /// DeclContext. Causes lookup within the scope to chain through enclosing contexts - /// in the correct order. + /// Enter a template parameter scope, after it's been associated with a + /// particular DeclContext. Causes lookup within the scope to chain through + /// enclosing contexts in the correct order. void EnterTemplatedContext(Scope *S, DeclContext *DC); /// Push the parameters of D, which must be a function, into scope. - void ActOnReenterFunctionContext(Scope* S, Decl* D); + void ActOnReenterFunctionContext(Scope *S, Decl *D); void ActOnExitFunctionContext(); - /// If \p AllowLambda is true, treat lambda as function. - DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const; - - /// Returns a pointer to the innermost enclosing function, or nullptr if the - /// current context is not inside a function. If \p AllowLambda is true, - /// this can return the call operator of an enclosing lambda, otherwise - /// lambdas are skipped when looking for an enclosing function. - FunctionDecl *getCurFunctionDecl(bool AllowLambda = false) const; - - /// getCurMethodDecl - If inside of a method body, this returns a pointer to - /// the method decl for the method being parsed. If we're currently - /// in a 'block', this returns the containing context. - ObjCMethodDecl *getCurMethodDecl(); - - /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method - /// or C function we're in, otherwise return null. If we're currently - /// in a 'block', this returns the containing context. - NamedDecl *getCurFunctionOrMethodDecl() const; - /// Add this decl to the scope shadowed decl chains. void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true); @@ -3785,9516 +3493,9111 @@ class Sema final { AMK_OptionalProtocolImplementation }; - /// Describes the kind of priority given to an availability attribute. - /// - /// The sum of priorities deteremines the final priority of the attribute. - /// The final priority determines how the attribute will be merged. - /// An attribute with a lower priority will always remove higher priority - /// attributes for the specified platform when it is being applied. An - /// attribute with a higher priority will not be applied if the declaration - /// already has an availability attribute with a lower priority for the - /// specified platform. The final prirority values are not expected to match - /// the values in this enumeration, but instead should be treated as a plain - /// integer value. This enumeration just names the priority weights that are - /// used to calculate that final vaue. - enum AvailabilityPriority : int { - /// The availability attribute was specified explicitly next to the - /// declaration. - AP_Explicit = 0, + void mergeDeclAttributes(NamedDecl *New, Decl *Old, + AvailabilityMergeKind AMK = AMK_Redeclaration); + void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, + LookupResult &OldDecls); + bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S, + bool MergeTypeWithOld, bool NewDeclIsDefn); + bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, + Scope *S, bool MergeTypeWithOld); + void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old); + void MergeVarDecl(VarDecl *New, LookupResult &Previous); + void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); + bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn); + void notePreviousDefinition(const NamedDecl *Old, SourceLocation New); - /// The availability attribute was applied using '#pragma clang attribute'. - AP_PragmaClangAttribute = 1, + void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, + bool ConsiderLinkage, bool AllowInlineNamespace); - /// The availability attribute for a specific platform was inferred from - /// an availability attribute for another platform. - AP_InferredFromOtherPlatform = 2 - }; + bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old); + bool CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old); + bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old); + bool IsRedefinitionInModule(const NamedDecl *New, const NamedDecl *Old) const; - /// Attribute merging methods. Return true if a new attribute was added. - AvailabilityAttr * - mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI, - IdentifierInfo *Platform, bool Implicit, - VersionTuple Introduced, VersionTuple Deprecated, - VersionTuple Obsoleted, bool IsUnavailable, - StringRef Message, bool IsStrict, StringRef Replacement, - AvailabilityMergeKind AMK, int Priority); - TypeVisibilityAttr * - mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, - TypeVisibilityAttr::VisibilityType Vis); - VisibilityAttr *mergeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, - VisibilityAttr::VisibilityType Vis); - UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI, - StringRef UuidAsWritten, MSGuidDecl *GuidDecl); - DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI); - DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI); - MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D, - const AttributeCommonInfo &CI, - bool BestCase, - MSInheritanceModel Model); - ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI, - StringRef NewUserDiagnostic); - FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, - IdentifierInfo *Format, int FormatIdx, - int FirstArg); - SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, - StringRef Name); - CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI, - StringRef Name); - AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, - const AttributeCommonInfo &CI, - const IdentifierInfo *Ident); - MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI); - SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA, - StringRef Name); - OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, - const AttributeCommonInfo &CI); - InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL); - InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, - const InternalLinkageAttr &AL); - WebAssemblyImportNameAttr *mergeImportNameAttr( - Decl *D, const WebAssemblyImportNameAttr &AL); - WebAssemblyImportModuleAttr *mergeImportModuleAttr( - Decl *D, const WebAssemblyImportModuleAttr &AL); - EnforceTCBAttr *mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL); - EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D, - const EnforceTCBLeafAttr &AL); - BTFDeclTagAttr *mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL); - HLSLNumThreadsAttr *mergeHLSLNumThreadsAttr(Decl *D, - const AttributeCommonInfo &AL, - int X, int Y, int Z); - HLSLShaderAttr *mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLShaderAttr::ShaderType ShaderType); - HLSLParamModifierAttr * - mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, - HLSLParamModifierAttr::Spelling Spelling); - - void mergeDeclAttributes(NamedDecl *New, Decl *Old, - AvailabilityMergeKind AMK = AMK_Redeclaration); - void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, - LookupResult &OldDecls); - bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S, - bool MergeTypeWithOld, bool NewDeclIsDefn); - bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, - Scope *S, bool MergeTypeWithOld); - void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old); - void MergeVarDecl(VarDecl *New, LookupResult &Previous); - void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); - void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); - bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn); - void notePreviousDefinition(const NamedDecl *Old, SourceLocation New); - bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); + bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; - // AssignmentAction - This is used by all the assignment diagnostic functions - // to represent what is actually causing the operation - enum AssignmentAction { - AA_Assigning, - AA_Passing, - AA_Returning, - AA_Converting, - AA_Initializing, - AA_Sending, - AA_Casting, - AA_Passing_CFAudited - }; + /// If it's a file scoped decl that must warn if not used, keep track + /// of it. + void MarkUnusedFileScopedDecl(const DeclaratorDecl *D); - /// C++ Overloading. - enum OverloadKind { - /// This is a legitimate overload: the existing declarations are - /// functions or function templates with different signatures. - Ovl_Overload, + typedef llvm::function_ref + DiagReceiverTy; - /// This is not an overload because the signature exactly matches - /// an existing declaration. - Ovl_Match, + void DiagnoseUnusedNestedTypedefs(const RecordDecl *D); + void DiagnoseUnusedNestedTypedefs(const RecordDecl *D, + DiagReceiverTy DiagReceiver); + void DiagnoseUnusedDecl(const NamedDecl *ND); + void DiagnoseUnusedDecl(const NamedDecl *ND, DiagReceiverTy DiagReceiver); - /// This is not an overload because the lookup results contain a - /// non-function. - Ovl_NonFunction - }; - OverloadKind CheckOverload(Scope *S, - FunctionDecl *New, - const LookupResult &OldDecls, - NamedDecl *&OldDecl, - bool UseMemberUsingDeclRules); - bool IsOverload(FunctionDecl *New, FunctionDecl *Old, - bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true); + /// If VD is set but not otherwise used, diagnose, for a parameter or a + /// variable. + void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver); - // Checks whether MD constitutes an override the base class method BaseMD. - // When checking for overrides, the object object members are ignored. - bool IsOverride(FunctionDecl *MD, FunctionDecl *BaseMD, - bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true); + ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id, + SourceLocation IdLoc, + bool TypoCorrection = false); - // Calculates whether the expression Constraint depends on an enclosing - // template, for the purposes of [temp.friend] p9. - // TemplateDepth is the 'depth' of the friend function, which is used to - // compare whether a declaration reference is referring to a containing - // template, or just the current friend function. A 'lower' TemplateDepth in - // the AST refers to a 'containing' template. As the constraint is - // uninstantiated, this is relative to the 'top' of the TU. - bool - ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, - unsigned TemplateDepth, - const Expr *Constraint); + Scope *getNonFieldDeclScope(Scope *S); - // Calculates whether the friend function depends on an enclosing template for - // the purposes of [temp.friend] p9. - bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD); + FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID, + SourceLocation Loc); + NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S, + bool ForRedeclaration, SourceLocation Loc); - enum class AllowedExplicit { - /// Allow no explicit functions to be used. - None, - /// Allow explicit conversion functions but not explicit constructors. - Conversions, - /// Allow both explicit conversion functions and explicit constructors. - All - }; + /// Get the outermost AttributedType node that sets a calling convention. + /// Valid types should not have multiple attributes with different CCs. + const AttributedType *getCallingConvAttributedType(QualType T) const; - ImplicitConversionSequence - TryImplicitConversion(Expr *From, QualType ToType, - bool SuppressUserConversions, - AllowedExplicit AllowExplicit, - bool InOverloadResolution, - bool CStyle, - bool AllowObjCWritebackConversion); + DeclarationNameInfo GetNameForDeclarator(Declarator &D); + DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name); - bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType); - bool IsFloatingPointPromotion(QualType FromType, QualType ToType); - bool IsComplexPromotion(QualType FromType, QualType ToType); - bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType, - bool InOverloadResolution, - QualType& ConvertedType, bool &IncompatibleObjC); - bool isObjCPointerConversion(QualType FromType, QualType ToType, - QualType& ConvertedType, bool &IncompatibleObjC); - bool isObjCWritebackConversion(QualType FromType, QualType ToType, - QualType &ConvertedType); - bool IsBlockPointerConversion(QualType FromType, QualType ToType, - QualType& ConvertedType); + /// ParsingInitForAutoVars - a set of declarations with auto types for which + /// we are currently parsing the initializer. + llvm::SmallPtrSet ParsingInitForAutoVars; - bool FunctionParamTypesAreEqual(ArrayRef Old, - ArrayRef New, - unsigned *ArgPos = nullptr, - bool Reversed = false); + /// Look for a locally scoped extern "C" declaration by the given name. + NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name); - bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType, - const FunctionProtoType *NewType, - unsigned *ArgPos = nullptr, - bool Reversed = false); + bool inferObjCARCLifetime(ValueDecl *decl); - bool FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction, - const FunctionDecl *NewFunction, - unsigned *ArgPos = nullptr, - bool Reversed = false); + void deduceOpenCLAddressSpace(ValueDecl *decl); - void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, - QualType FromType, QualType ToType); + static bool adjustContextForLocalExternDecl(DeclContext *&DC); - void maybeExtendBlockObject(ExprResult &E); - CastKind PrepareCastToObjCObjectPointer(ExprResult &E); - bool CheckPointerConversion(Expr *From, QualType ToType, - CastKind &Kind, - CXXCastPath& BasePath, - bool IgnoreBaseAccess, - bool Diagnose = true); - bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, - bool InOverloadResolution, - QualType &ConvertedType); - bool CheckMemberPointerConversion(Expr *From, QualType ToType, - CastKind &Kind, - CXXCastPath &BasePath, - bool IgnoreBaseAccess); - bool IsQualificationConversion(QualType FromType, QualType ToType, - bool CStyle, bool &ObjCLifetimeConversion); - bool IsFunctionConversion(QualType FromType, QualType ToType, - QualType &ResultTy); - bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); - bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg); + void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F); - bool CanPerformAggregateInitializationForOverloadResolution( - const InitializedEntity &Entity, InitListExpr *From); + /// Checks if the variant/multiversion functions are compatible. + bool areMultiversionVariantFunctionsCompatible( + const FunctionDecl *OldFD, const FunctionDecl *NewFD, + const PartialDiagnostic &NoProtoDiagID, + const PartialDiagnosticAt &NoteCausedDiagIDAt, + const PartialDiagnosticAt &NoSupportDiagIDAt, + const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, + bool ConstexprSupported, bool CLinkageMayDiffer); - bool IsStringInit(Expr *Init, const ArrayType *AT); + /// type checking declaration initializers (C99 6.7.8) + bool CheckForConstantInitializer(Expr *e, QualType t); - bool CanPerformCopyInitialization(const InitializedEntity &Entity, - ExprResult Init); - ExprResult PerformCopyInitialization(const InitializedEntity &Entity, - SourceLocation EqualLoc, - ExprResult Init, - bool TopLevelOfInitList = false, - bool AllowExplicit = false); - ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj, - FunctionDecl *Fun); - ExprResult PerformImplicitObjectArgumentInitialization( - Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, - CXXMethodDecl *Method); + QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name, + QualType Type, TypeSourceInfo *TSI, + SourceRange Range, bool DirectInit, + Expr *Init); - /// Check that the lifetime of the initializer (and its subobjects) is - /// sufficient for initializing the entity, and perform lifetime extension - /// (when permitted) if not. - void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init); + bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, + Expr *Init); - ExprResult PerformContextuallyConvertToBool(Expr *From); - ExprResult PerformContextuallyConvertToObjCPointer(Expr *From); + sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator); - /// Contexts in which a converted constant expression is required. - enum CCEKind { - CCEK_CaseValue, ///< Expression in a case label. - CCEK_Enumerator, ///< Enumerator value with fixed underlying type. - CCEK_TemplateArg, ///< Value of a non-type template parameter. - CCEK_ArrayBound, ///< Array bound in array declarator or new-expression. - CCEK_ExplicitBool, ///< Condition in an explicit(bool) specifier. - CCEK_Noexcept, ///< Condition in a noexcept(bool) specifier. - CCEK_StaticAssertMessageSize, ///< Call to size() in a static assert - ///< message. - CCEK_StaticAssertMessageData, ///< Call to data() in a static assert - ///< message. - }; + /// The declarator \p D defines a function in the scope \p S which is nested + /// in an `omp begin/end declare variant` scope. In this method we create a + /// declaration for \p D and rename \p D according to the OpenMP context + /// selector of the surrounding scope. Return all base functions in \p Bases. + void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( + Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, + SmallVectorImpl &Bases); - ExprResult BuildConvertedConstantExpression(Expr *From, QualType T, - CCEKind CCE, - NamedDecl *Dest = nullptr); + // Heuristically tells if the function is `get_return_object` member of a + // coroutine promise_type by matching the function name. + static bool CanBeGetReturnObject(const FunctionDecl *FD); + static bool CanBeGetReturnTypeOnAllocFailure(const FunctionDecl *FD); - ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, - llvm::APSInt &Value, CCEKind CCE); - ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, - APValue &Value, CCEKind CCE, - NamedDecl *Dest = nullptr); + NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, + Scope *S); + void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction( + FunctionDecl *FD); + void AddKnownFunctionAttributes(FunctionDecl *FD); - ExprResult - EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, - CCEKind CCE, bool RequireInt, - const APValue &PreNarrowingValue); + /// VerifyBitField - verifies that a bit field expression is an ICE and has + /// the correct width, and that the field type is valid. + /// Returns false on success. + ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, bool IsMsStruct, Expr *BitWidth); - /// Abstract base class used to perform a contextual implicit - /// conversion from an expression to any type passing a filter. - class ContextualImplicitConverter { - public: - bool Suppress; - bool SuppressConversion; + /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag + /// enum. If AllowMask is true, then we also allow the complement of a valid + /// value, to be used as a mask. + bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, + bool AllowMask) const; - ContextualImplicitConverter(bool Suppress = false, - bool SuppressConversion = false) - : Suppress(Suppress), SuppressConversion(SuppressConversion) {} + /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident. + void ActOnPragmaWeakID(IdentifierInfo *WeakName, SourceLocation PragmaLoc, + SourceLocation WeakNameLoc); - /// Determine whether the specified type is a valid destination type - /// for this conversion. - virtual bool match(QualType T) = 0; + /// ActOnPragmaRedefineExtname - Called on well formed + /// \#pragma redefine_extname oldname newname. + void ActOnPragmaRedefineExtname(IdentifierInfo *WeakName, + IdentifierInfo *AliasName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc, + SourceLocation AliasNameLoc); - /// Emits a diagnostic complaining that the expression does not have - /// integral or enumeration type. - virtual SemaDiagnosticBuilder - diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0; + /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident. + void ActOnPragmaWeakAlias(IdentifierInfo *WeakName, IdentifierInfo *AliasName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc, + SourceLocation AliasNameLoc); - /// Emits a diagnostic when the expression has incomplete class type. - virtual SemaDiagnosticBuilder - diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0; + ObjCContainerDecl *getObjCDeclContext() const; - /// Emits a diagnostic when the only matching conversion function - /// is explicit. - virtual SemaDiagnosticBuilder diagnoseExplicitConv( - Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0; + /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs. + enum class FunctionEmissionStatus { + Emitted, + CUDADiscarded, // Discarded due to CUDA/HIP hostness + OMPDiscarded, // Discarded due to OpenMP hostness + TemplateDiscarded, // Discarded due to uninstantiated templates + Unknown, + }; + FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, + bool Final = false); - /// Emits a note for the explicit conversion function. - virtual SemaDiagnosticBuilder - noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; + // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check. + bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee); - /// Emits a diagnostic when there are multiple possible conversion - /// functions. - virtual SemaDiagnosticBuilder - diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0; +private: + /// Function or variable declarations to be checked for whether the deferred + /// diagnostics should be emitted. + llvm::SmallSetVector DeclsToCheckForDeferredDiags; - /// Emits a note for one of the candidate conversions. - virtual SemaDiagnosticBuilder - noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; + /// Map of current shadowing declarations to shadowed declarations. Warn if + /// it looks like the user is trying to modify the shadowing declaration. + llvm::DenseMap ShadowingDecls; - /// Emits a diagnostic when we picked a conversion function - /// (for cases when we are not allowed to pick a conversion function). - virtual SemaDiagnosticBuilder diagnoseConversion( - Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0; + static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); - virtual ~ContextualImplicitConverter() {} - }; + ///@} - class ICEConvertDiagnoser : public ContextualImplicitConverter { - bool AllowScopedEnumerations; + // + // + // ------------------------------------------------------------------------- + // + // - public: - ICEConvertDiagnoser(bool AllowScopedEnumerations, - bool Suppress, bool SuppressConversion) - : ContextualImplicitConverter(Suppress, SuppressConversion), - AllowScopedEnumerations(AllowScopedEnumerations) {} + /// \name Declaration Attribute Handling + /// Implementations are in SemaDeclAttr.cpp + ///@{ - /// Match an integral or (possibly scoped) enumeration type. - bool match(QualType T) override; +public: + /// Describes the kind of priority given to an availability attribute. + /// + /// The sum of priorities deteremines the final priority of the attribute. + /// The final priority determines how the attribute will be merged. + /// An attribute with a lower priority will always remove higher priority + /// attributes for the specified platform when it is being applied. An + /// attribute with a higher priority will not be applied if the declaration + /// already has an availability attribute with a lower priority for the + /// specified platform. The final prirority values are not expected to match + /// the values in this enumeration, but instead should be treated as a plain + /// integer value. This enumeration just names the priority weights that are + /// used to calculate that final vaue. + enum AvailabilityPriority : int { + /// The availability attribute was specified explicitly next to the + /// declaration. + AP_Explicit = 0, - SemaDiagnosticBuilder - diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override { - return diagnoseNotInt(S, Loc, T); - } + /// The availability attribute was applied using '#pragma clang attribute'. + AP_PragmaClangAttribute = 1, - /// Emits a diagnostic complaining that the expression does not have - /// integral or enumeration type. - virtual SemaDiagnosticBuilder - diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0; + /// The availability attribute for a specific platform was inferred from + /// an availability attribute for another platform. + AP_InferredFromOtherPlatform = 2 }; - /// Perform a contextual implicit conversion. - ExprResult PerformContextualImplicitConversion( - SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter); - - - enum ObjCSubscriptKind { - OS_Array, - OS_Dictionary, - OS_Error + /// Describes the reason a calling convention specification was ignored, used + /// for diagnostics. + enum class CallingConventionIgnoredReason { + ForThisTarget = 0, + VariadicFunction, + ConstructorDestructor, + BuiltinFunction }; - ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE); - // Note that LK_String is intentionally after the other literals, as - // this is used for diagnostics logic. - enum ObjCLiteralKind { - LK_Array, - LK_Dictionary, - LK_Numeric, - LK_Boxed, - LK_String, - LK_Block, - LK_None - }; - ObjCLiteralKind CheckLiteralKind(Expr *FromE); + /// WeakTopLevelDecl - Translation-unit scoped declarations generated by + /// \#pragma weak during processing of other Decls. + /// I couldn't figure out a clean way to generate these in-line, so + /// we store them here and handle separately -- which is a hack. + /// It would be best to refactor this. + SmallVector WeakTopLevelDecl; - ExprResult PerformObjectMemberConversion(Expr *From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - NamedDecl *Member); + /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls + SmallVectorImpl &WeakTopLevelDecls() { return WeakTopLevelDecl; } - // Members have to be NamespaceDecl* or TranslationUnitDecl*. - // TODO: make this is a typesafe union. - typedef llvm::SmallSetVector AssociatedNamespaceSet; - typedef llvm::SmallSetVector AssociatedClassSet; + typedef LazyVector + ExtVectorDeclsType; - using ADLCallKind = CallExpr::ADLCallKind; + /// ExtVectorDecls - This is a list all the extended vector types. This allows + /// us to associate a raw vector type with one of the ext_vector type names. + /// This is only necessary for issuing pretty diagnostics. + ExtVectorDeclsType ExtVectorDecls; - void AddOverloadCandidate( - FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef Args, - OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, - bool PartialOverloading = false, bool AllowExplicit = true, - bool AllowExplicitConversion = false, - ADLCallKind IsADLCandidate = ADLCallKind::NotADL, - ConversionSequenceList EarlyConversions = std::nullopt, - OverloadCandidateParamOrder PO = {}, - bool AggregateCandidateDeduction = false); - void AddFunctionCandidates(const UnresolvedSetImpl &Functions, - ArrayRef Args, - OverloadCandidateSet &CandidateSet, - TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, - bool SuppressUserConversions = false, - bool PartialOverloading = false, - bool FirstArgumentIsBase = false); - void AddMethodCandidate(DeclAccessPair FoundDecl, - QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef Args, - OverloadCandidateSet& CandidateSet, - bool SuppressUserConversion = false, - OverloadCandidateParamOrder PO = {}); - void - AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef Args, OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions = false, - bool PartialOverloading = false, - ConversionSequenceList EarlyConversions = std::nullopt, - OverloadCandidateParamOrder PO = {}); - void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, - DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, - TemplateArgumentListInfo *ExplicitTemplateArgs, - QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef Args, - OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions = false, - bool PartialOverloading = false, - OverloadCandidateParamOrder PO = {}); - void AddTemplateOverloadCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, - OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, - bool PartialOverloading = false, bool AllowExplicit = true, - ADLCallKind IsADLCandidate = ADLCallKind::NotADL, - OverloadCandidateParamOrder PO = {}, - bool AggregateCandidateDeduction = false); - bool CheckNonDependentConversions( - FunctionTemplateDecl *FunctionTemplate, ArrayRef ParamTypes, - ArrayRef Args, OverloadCandidateSet &CandidateSet, - ConversionSequenceList &Conversions, bool SuppressUserConversions, - CXXRecordDecl *ActingContext = nullptr, QualType ObjectType = QualType(), - Expr::Classification ObjectClassification = {}, - OverloadCandidateParamOrder PO = {}); - void AddConversionCandidate( - CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, Expr *From, QualType ToType, - OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion = true); - void AddTemplateConversionCandidate( - FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, Expr *From, QualType ToType, - OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion = true); - void AddSurrogateCandidate(CXXConversionDecl *Conversion, - DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, - const FunctionProtoType *Proto, - Expr *Object, ArrayRef Args, - OverloadCandidateSet& CandidateSet); - void AddNonMemberOperatorCandidates( - const UnresolvedSetImpl &Functions, ArrayRef Args, - OverloadCandidateSet &CandidateSet, - TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); - void AddMemberOperatorCandidates(OverloadedOperatorKind Op, - SourceLocation OpLoc, ArrayRef Args, - OverloadCandidateSet &CandidateSet, - OverloadCandidateParamOrder PO = {}); - void AddBuiltinCandidate(QualType *ParamTys, ArrayRef Args, - OverloadCandidateSet& CandidateSet, - bool IsAssignmentOperator = false, - unsigned NumContextualBoolArguments = 0); - void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, - SourceLocation OpLoc, ArrayRef Args, - OverloadCandidateSet& CandidateSet); - void AddArgumentDependentLookupCandidates(DeclarationName Name, - SourceLocation Loc, - ArrayRef Args, - TemplateArgumentListInfo *ExplicitTemplateArgs, - OverloadCandidateSet& CandidateSet, - bool PartialOverloading = false); + bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, + const Expr *E, StringRef &Str, + SourceLocation *ArgLocation = nullptr); + bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum, + StringRef &Str, + SourceLocation *ArgLocation = nullptr); - // Emit as a 'note' the specific overload candidate - void NoteOverloadCandidate( - const NamedDecl *Found, const FunctionDecl *Fn, - OverloadCandidateRewriteKind RewriteKind = OverloadCandidateRewriteKind(), - QualType DestType = QualType(), bool TakingAddress = false); + /// Determine if type T is a valid subject for a nonnull and similar + /// attributes. By default, we look through references (the behavior used by + /// nonnull), but if the second parameter is true, then we treat a reference + /// type as valid. + bool isValidPointerAttrType(QualType T, bool RefOkay = false); - // Emit as a series of 'note's all template and non-templates identified by - // the expression Expr - void NoteAllOverloadCandidates(Expr *E, QualType DestType = QualType(), - bool TakingAddress = false); + /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular + /// declaration. + void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, + Expr *OE); - /// Check the enable_if expressions on the given function. Returns the first - /// failing attribute, or NULL if they were all successful. - EnableIfAttr *CheckEnableIf(FunctionDecl *Function, SourceLocation CallLoc, - ArrayRef Args, - bool MissingImplicitThis = false); + /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular + /// declaration. + void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *ParamExpr); - /// Find the failed Boolean condition within a given Boolean - /// constant expression, and describe it with a string. - std::pair findFailedBooleanCondition(Expr *Cond); - - /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any - /// non-ArgDependent DiagnoseIfAttrs. - /// - /// Argument-dependent diagnose_if attributes should be checked each time a - /// function is used as a direct callee of a function call. - /// - /// Returns true if any errors were emitted. - bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, - const Expr *ThisArg, - ArrayRef Args, - SourceLocation Loc); + bool CheckAttrTarget(const ParsedAttr &CurrAttr); + bool CheckAttrNoArgs(const ParsedAttr &CurrAttr); - /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any - /// ArgDependent DiagnoseIfAttrs. - /// - /// Argument-independent diagnose_if attributes should be checked on every use - /// of a function. - /// - /// Returns true if any errors were emitted. - bool diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, - SourceLocation Loc); + AvailabilityAttr * + mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI, + IdentifierInfo *Platform, bool Implicit, + VersionTuple Introduced, VersionTuple Deprecated, + VersionTuple Obsoleted, bool IsUnavailable, + StringRef Message, bool IsStrict, StringRef Replacement, + AvailabilityMergeKind AMK, int Priority); + TypeVisibilityAttr * + mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, + TypeVisibilityAttr::VisibilityType Vis); + VisibilityAttr *mergeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI, + VisibilityAttr::VisibilityType Vis); + SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef Name); - /// Returns whether the given function's address can be taken or not, - /// optionally emitting a diagnostic if the address can't be taken. - /// - /// Returns false if taking the address of the function is illegal. - bool checkAddressOfFunctionIsAvailable(const FunctionDecl *Function, - bool Complain = false, - SourceLocation Loc = SourceLocation()); + llvm::Error isValidSectionSpecifier(StringRef Str); + bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); + CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef Name); - // [PossiblyAFunctionType] --> [Return] - // NonFunctionType --> NonFunctionType - // R (A) --> R(A) - // R (*)(A) --> R (A) - // R (&)(A) --> R (A) - // R (S::*)(A) --> R (A) - QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType); + bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); + bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, + StringRef &Str, bool &isDefault); + bool checkTargetClonesAttrString( + SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal, + Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault, + SmallVectorImpl> &StringsBuffer); - FunctionDecl * - ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, - QualType TargetType, - bool Complain, - DeclAccessPair &Found, - bool *pHadMultipleCandidates = nullptr); + ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef NewUserDiagnostic); + FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, + IdentifierInfo *Format, int FormatIdx, + int FirstArg); - FunctionDecl * - resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult); + /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. + void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, + bool IsPackExpansion); + void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, TypeSourceInfo *T, + bool IsPackExpansion); - bool resolveAndFixAddressOfSingleOverloadCandidate( - ExprResult &SrcExpr, bool DoFunctionPointerConversion = false); + /// AddAlignValueAttr - Adds an align_value attribute to a particular + /// declaration. + void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E); - FunctionDecl *ResolveSingleFunctionTemplateSpecialization( - OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr, - TemplateSpecCandidateSet *FailedTSC = nullptr); + /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D. + void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef Annot, MutableArrayRef Args); - bool ResolveAndFixSingleFunctionTemplateSpecialization( - ExprResult &SrcExpr, bool DoFunctionPointerConversion = false, - bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(), - QualType DestTypeForComplaining = QualType(), - unsigned DiagIDForComplaining = 0); + bool checkMSInheritanceAttrOnDefinition(CXXRecordDecl *RD, SourceRange Range, + bool BestCase, + MSInheritanceModel SemanticSpelling); - ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, - FunctionDecl *Fn); - ExprResult FixOverloadedFunctionReference(ExprResult, - DeclAccessPair FoundDecl, - FunctionDecl *Fn); + void CheckAlignasUnderalignment(Decl *D); - void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, - ArrayRef Args, - OverloadCandidateSet &CandidateSet, - bool PartialOverloading = false); - void AddOverloadedCallCandidates( - LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef Args, OverloadCandidateSet &CandidateSet); + /// AddModeAttr - Adds a mode attribute to a particular declaration. + void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name, + bool InInstantiation = false); + AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, + const AttributeCommonInfo &CI, + const IdentifierInfo *Ident); + MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI); + SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA, + StringRef Name); + OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, + const AttributeCommonInfo &CI); + InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL); + InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, + const InternalLinkageAttr &AL); - // An enum used to represent the different possible results of building a - // range-based for loop. - enum ForRangeStatus { - FRS_Success, - FRS_NoViableFunction, - FRS_DiagnosticIssued + enum CUDAFunctionTarget { + CFT_Device, + CFT_Global, + CFT_Host, + CFT_HostDevice, + CFT_InvalidTarget }; - ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc, - SourceLocation RangeLoc, - const DeclarationNameInfo &NameInfo, - LookupResult &MemberLookup, - OverloadCandidateSet *CandidateSet, - Expr *Range, ExprResult *CallExpr); + /// Check validaty of calling convention attribute \p attr. If \p FD + /// is not null pointer, use \p FD to determine the CUDA/HIP host/device + /// target. Otherwise, it is specified by \p CFT. + bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC, + const FunctionDecl *FD = nullptr, + CUDAFunctionTarget CFT = CFT_InvalidTarget); - ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn, - UnresolvedLookupExpr *ULE, - SourceLocation LParenLoc, - MultiExprArg Args, - SourceLocation RParenLoc, - Expr *ExecConfig, - bool AllowTypoCorrection=true, - bool CalleesAddressIsTaken=false); + void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, + ParameterABI ABI); + bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value); - bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, - MultiExprArg Args, SourceLocation RParenLoc, - OverloadCandidateSet *CandidateSet, - ExprResult *Result); + /// Create an CUDALaunchBoundsAttr attribute. + CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, + Expr *MaxThreads, + Expr *MinBlocks, + Expr *MaxBlocks); - ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, - NestedNameSpecifierLoc NNSLoc, - DeclarationNameInfo DNI, - const UnresolvedSetImpl &Fns, - bool PerformADL = true); + /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular + /// declaration. + void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks); - ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, - UnaryOperatorKind Opc, - const UnresolvedSetImpl &Fns, - Expr *input, bool RequiresADL = true); + enum class RetainOwnershipKind { NS, CF, OS }; + void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI, + RetainOwnershipKind K, bool IsTemplateInstantiation); - void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet, - OverloadedOperatorKind Op, - const UnresolvedSetImpl &Fns, - ArrayRef Args, bool RequiresADL = true); - ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, - BinaryOperatorKind Opc, - const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS, - bool RequiresADL = true, - bool AllowRewrittenCandidates = true, - FunctionDecl *DefaultedFn = nullptr); - ExprResult BuildSynthesizedThreeWayComparison(SourceLocation OpLoc, - const UnresolvedSetImpl &Fns, - Expr *LHS, Expr *RHS, - FunctionDecl *DefaultedFn); + bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type); - ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, - SourceLocation RLoc, Expr *Base, - MultiExprArg Args); + /// Do a check to make sure \p Name looks like a legal argument for the + /// swift_name attribute applied to decl \p D. Raise a diagnostic if the name + /// is invalid for the given declaration. + /// + /// \p AL is used to provide caret diagnostics in case of a malformed name. + /// + /// \returns true if the name is a valid swift name for \p D, false otherwise. + bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc, + const ParsedAttr &AL, bool IsAsync); - ExprResult BuildCallToMemberFunction(Scope *S, Expr *MemExpr, - SourceLocation LParenLoc, - MultiExprArg Args, - SourceLocation RParenLoc, - Expr *ExecConfig = nullptr, - bool IsExecConfig = false, - bool AllowRecovery = false); - ExprResult - BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc, - MultiExprArg Args, - SourceLocation RParenLoc); + UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI, + StringRef UuidAsWritten, MSGuidDecl *GuidDecl); - ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, - bool *NoArrowOperatorFound = nullptr); + BTFDeclTagAttr *mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL); + HLSLNumThreadsAttr *mergeHLSLNumThreadsAttr(Decl *D, + const AttributeCommonInfo &AL, + int X, int Y, int Z); + HLSLShaderAttr *mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLShaderAttr::ShaderType ShaderType); + HLSLParamModifierAttr * + mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL, + HLSLParamModifierAttr::Spelling Spelling); - /// CheckCallReturnType - Checks that a call expression's return type is - /// complete. Returns true on failure. The location passed in is the location - /// that best represents the call. - bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc, - CallExpr *CE, FunctionDecl *FD); + WebAssemblyImportNameAttr * + mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL); + WebAssemblyImportModuleAttr * + mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL); - /// Helpers for dealing with blocks and functions. - bool CheckParmsForFunctionDef(ArrayRef Parameters, - bool CheckParameterNames); - void CheckCXXDefaultArguments(FunctionDecl *FD); - void CheckExtraCXXDefaultArguments(Declarator &D); - Scope *getNonFieldDeclScope(Scope *S); + /// Create an AMDGPUWavesPerEUAttr attribute. + AMDGPUFlatWorkGroupSizeAttr * + CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, + Expr *Max); - /// \name Name lookup - /// - /// These routines provide name lookup that is used during semantic - /// analysis to resolve the various kinds of names (identifiers, - /// overloaded operator names, constructor names, etc.) into zero or - /// more declarations within a particular scope. The major entry - /// points are LookupName, which performs unqualified name lookup, - /// and LookupQualifiedName, which performs qualified name lookup. - /// - /// All name lookup is performed based on some specific criteria, - /// which specify what names will be visible to name lookup and how - /// far name lookup should work. These criteria are important both - /// for capturing language semantics (certain lookups will ignore - /// certain names, for example) and for performance, since name - /// lookup is often a bottleneck in the compilation of C++. Name - /// lookup criteria is specified via the LookupCriteria enumeration. - /// - /// The results of name lookup can vary based on the kind of name - /// lookup performed, the current language, and the translation - /// unit. In C, for example, name lookup will either return nothing - /// (no entity found) or a single declaration. In C++, name lookup - /// can additionally refer to a set of overloaded functions or - /// result in an ambiguity. All of the possible results of name - /// lookup are captured by the LookupResult class, which provides - /// the ability to distinguish among them. - //@{ + /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size + /// attribute to a particular declaration. + void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *Min, Expr *Max); - /// Describes the kind of name lookup to perform. - enum LookupNameKind { - /// Ordinary name lookup, which finds ordinary names (functions, - /// variables, typedefs, etc.) in C and most kinds of names - /// (functions, variables, members, types, etc.) in C++. - LookupOrdinaryName = 0, - /// Tag name lookup, which finds the names of enums, classes, - /// structs, and unions. - LookupTagName, - /// Label name lookup. - LookupLabel, - /// Member name lookup, which finds the names of - /// class/struct/union members. - LookupMemberName, - /// Look up of an operator name (e.g., operator+) for use with - /// operator overloading. This lookup is similar to ordinary name - /// lookup, but will ignore any declarations that are class members. - LookupOperatorName, - /// Look up a name following ~ in a destructor name. This is an ordinary - /// lookup, but prefers tags to typedefs. - LookupDestructorName, - /// Look up of a name that precedes the '::' scope resolution - /// operator in C++. This lookup completely ignores operator, object, - /// function, and enumerator names (C++ [basic.lookup.qual]p1). - LookupNestedNameSpecifierName, - /// Look up a namespace name within a C++ using directive or - /// namespace alias definition, ignoring non-namespace names (C++ - /// [basic.lookup.udir]p1). - LookupNamespaceName, - /// Look up all declarations in a scope with the given name, - /// including resolved using declarations. This is appropriate - /// for checking redeclarations for a using declaration. - LookupUsingDeclName, - /// Look up an ordinary name that is going to be redeclared as a - /// name with linkage. This lookup ignores any declarations that - /// are outside of the current scope unless they have linkage. See - /// C99 6.2.2p4-5 and C++ [basic.link]p6. - LookupRedeclarationWithLinkage, - /// Look up a friend of a local class. This lookup does not look - /// outside the innermost non-class scope. See C++11 [class.friend]p11. - LookupLocalFriendName, - /// Look up the name of an Objective-C protocol. - LookupObjCProtocolName, - /// Look up implicit 'self' parameter of an objective-c method. - LookupObjCImplicitSelfParam, - /// Look up the name of an OpenMP user-defined reduction operation. - LookupOMPReductionName, - /// Look up the name of an OpenMP user-defined mapper. - LookupOMPMapperName, - /// Look up any declaration with any name. - LookupAnyName - }; + /// Create an AMDGPUWavesPerEUAttr attribute. + AMDGPUWavesPerEUAttr * + CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, + Expr *Max); - /// Specifies whether (or how) name lookup is being performed for a - /// redeclaration (vs. a reference). - enum RedeclarationKind { - /// The lookup is a reference to this name that is not for the - /// purpose of redeclaring the name. - NotForRedeclaration = 0, - /// The lookup results will be used for redeclaration of a name, - /// if an entity by that name already exists and is visible. - ForVisibleRedeclaration, - /// The lookup results will be used for redeclaration of a name - /// with external linkage; non-visible lookup results with external linkage - /// may also be found. - ForExternalRedeclaration - }; + /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a + /// particular declaration. + void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *Min, Expr *Max); - RedeclarationKind forRedeclarationInCurContext() const { - // A declaration with an owning module for linkage can never link against - // anything that is not visible. We don't need to check linkage here; if - // the context has internal linkage, redeclaration lookup won't find things - // from other TUs, and we can't safely compute linkage yet in general. - if (cast(CurContext) - ->getOwningModuleForLinkage(/*IgnoreLinkage*/true)) - return ForVisibleRedeclaration; - return ForExternalRedeclaration; - } + DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI); + DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI); + MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D, + const AttributeCommonInfo &CI, + bool BestCase, + MSInheritanceModel Model); - /// The possible outcomes of name lookup for a literal operator. - enum LiteralOperatorLookupResult { - /// The lookup resulted in an error. - LOLR_Error, - /// The lookup found no match but no diagnostic was issued. - LOLR_ErrorNoDiagnostic, - /// The lookup found a single 'cooked' literal operator, which - /// expects a normal literal to be built and passed to it. - LOLR_Cooked, - /// The lookup found a single 'raw' literal operator, which expects - /// a string literal containing the spelling of the literal token. - LOLR_Raw, - /// The lookup found an overload set of literal operator templates, - /// which expect the characters of the spelling of the literal token to be - /// passed as a non-type template argument pack. - LOLR_Template, - /// The lookup found an overload set of literal operator templates, - /// which expect the character type and characters of the spelling of the - /// string literal token to be passed as template arguments. - LOLR_StringTemplatePack, - }; + bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD); - SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, - CXXSpecialMember SM, - bool ConstArg, - bool VolatileArg, - bool RValueThis, - bool ConstThis, - bool VolatileThis); + EnforceTCBAttr *mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL); + EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D, + const EnforceTCBLeafAttr &AL); - typedef std::function TypoDiagnosticGenerator; - typedef std::function - TypoRecoveryCallback; + // Helper for delayed processing of attributes. + void ProcessDeclAttributeDelayed(Decl *D, + const ParsedAttributesView &AttrList); -private: - bool CppLookupName(LookupResult &R, Scope *S); + // Options for ProcessDeclAttributeList(). + struct ProcessDeclAttributeOptions { + ProcessDeclAttributeOptions() + : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {} - struct TypoExprState { - std::unique_ptr Consumer; - TypoDiagnosticGenerator DiagHandler; - TypoRecoveryCallback RecoveryHandler; - TypoExprState(); - TypoExprState(TypoExprState &&other) noexcept; - TypoExprState &operator=(TypoExprState &&other) noexcept; - }; + ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) { + ProcessDeclAttributeOptions Result = *this; + Result.IncludeCXX11Attributes = Val; + return Result; + } - /// The set of unhandled TypoExprs and their associated state. - llvm::MapVector DelayedTypos; + ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) { + ProcessDeclAttributeOptions Result = *this; + Result.IgnoreTypeAttributes = Val; + return Result; + } - /// Creates a new TypoExpr AST node. - TypoExpr *createDelayedTypo(std::unique_ptr TCC, - TypoDiagnosticGenerator TDG, - TypoRecoveryCallback TRC, SourceLocation TypoLoc); + // Should C++11 attributes be processed? + bool IncludeCXX11Attributes; - // The set of known/encountered (unique, canonicalized) NamespaceDecls. - // - // The boolean value will be true to indicate that the namespace was loaded - // from an AST/PCH file, or false otherwise. - llvm::MapVector KnownNamespaces; + // Should any type attributes encountered be ignored? + // If this option is false, a diagnostic will be emitted for any type + // attributes of a kind that does not "slide" from the declaration to + // the decl-specifier-seq. + bool IgnoreTypeAttributes; + }; - /// Whether we have already loaded known namespaces from an extenal - /// source. - bool LoadedExternalKnownNamespaces; + void ProcessDeclAttributeList(Scope *S, Decl *D, + const ParsedAttributesView &AttrList, + const ProcessDeclAttributeOptions &Options = + ProcessDeclAttributeOptions()); + bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, + const ParsedAttributesView &AttrList); - /// Helper for CorrectTypo and CorrectTypoDelayed used to create and - /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction - /// should be skipped entirely. - std::unique_ptr - makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo, - Sema::LookupNameKind LookupKind, Scope *S, - CXXScopeSpec *SS, - CorrectionCandidateCallback &CCC, - DeclContext *MemberContext, bool EnteringContext, - const ObjCObjectPointerType *OPT, - bool ErrorRecovery); + void checkUnusedDeclAttributes(Declarator &D); -public: - const TypoExprState &getTypoExprState(TypoExpr *TE) const; + NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II, + SourceLocation Loc); + void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W); - /// Clears the state of the given TypoExpr. - void clearDelayedTypo(TypoExpr *TE); + void ProcessPragmaWeak(Scope *S, Decl *D); + // Decl attributes - this routine is the top level dispatcher. + void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); - /// Look up a name, looking for a single declaration. Return - /// null if the results were absent, ambiguous, or overloaded. - /// - /// It is preferable to use the elaborated form and explicitly handle - /// ambiguity and overloaded. - NamedDecl *LookupSingleName(Scope *S, DeclarationName Name, - SourceLocation Loc, - LookupNameKind NameKind, - RedeclarationKind Redecl - = NotForRedeclaration); - bool LookupBuiltin(LookupResult &R); - void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID); - bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false, - bool ForceNoCPlusPlus = false); - bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, - bool InUnqualifiedLookup = false); - bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, - CXXScopeSpec &SS); - bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, - bool AllowBuiltinCreation = false, - bool EnteringContext = false); - ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, - RedeclarationKind Redecl - = NotForRedeclaration); - bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class); + void PopParsingDeclaration(ParsingDeclState state, Decl *decl); - void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, - UnresolvedSetImpl &Functions); + void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); - LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, - SourceLocation GnuLabelLoc = SourceLocation()); + ///@} - DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); - CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class); - CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class, - unsigned Quals); - CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals, - bool RValueThis, unsigned ThisQuals); - CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class, - unsigned Quals); - CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals, - bool RValueThis, unsigned ThisQuals); - CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); + // + // + // ------------------------------------------------------------------------- + // + // - bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id, - bool IsUDSuffix); - LiteralOperatorLookupResult - LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys, - bool AllowRaw, bool AllowTemplate, - bool AllowStringTemplate, bool DiagnoseMissing, - StringLiteral *StringLit = nullptr); - bool isKnownName(StringRef name); + /// \name C++ Declarations + /// Implementations are in SemaDeclCXX.cpp + ///@{ - /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs. - enum class FunctionEmissionStatus { - Emitted, - CUDADiscarded, // Discarded due to CUDA/HIP hostness - OMPDiscarded, // Discarded due to OpenMP hostness - TemplateDiscarded, // Discarded due to uninstantiated templates - Unknown, - }; - FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, - bool Final = false); +public: + void CheckDelegatingCtorCycles(); - // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check. - bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee); + /// Called before parsing a function declarator belonging to a function + /// declaration. + void ActOnStartFunctionDeclarationDeclarator(Declarator &D, + unsigned TemplateParameterDepth); - void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, - ArrayRef Args, ADLResult &Functions); + /// Called after parsing a function declarator belonging to a function + /// declaration. + void ActOnFinishFunctionDeclarationDeclarator(Declarator &D); - void LookupVisibleDecls(Scope *S, LookupNameKind Kind, - VisibleDeclConsumer &Consumer, - bool IncludeGlobalScope = true, - bool LoadExternal = true); - void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, - VisibleDeclConsumer &Consumer, - bool IncludeGlobalScope = true, - bool IncludeDependentBases = false, - bool LoadExternal = true); + // Act on C++ namespaces + Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, + SourceLocation NamespaceLoc, + SourceLocation IdentLoc, IdentifierInfo *Ident, + SourceLocation LBrace, + const ParsedAttributesView &AttrList, + UsingDirectiveDecl *&UsingDecl, bool IsNested); + void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); - enum CorrectTypoKind { - CTK_NonError, // CorrectTypo used in a non error recovery situation. - CTK_ErrorRecovery // CorrectTypo used in normal error recovery. - }; + NamespaceDecl *getStdNamespace() const; + NamespaceDecl *getOrCreateStdNamespace(); - TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, - Sema::LookupNameKind LookupKind, - Scope *S, CXXScopeSpec *SS, - CorrectionCandidateCallback &CCC, - CorrectTypoKind Mode, - DeclContext *MemberContext = nullptr, - bool EnteringContext = false, - const ObjCObjectPointerType *OPT = nullptr, - bool RecordFailure = true); + CXXRecordDecl *getStdBadAlloc() const; + EnumDecl *getStdAlignValT() const; - TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo, - Sema::LookupNameKind LookupKind, Scope *S, - CXXScopeSpec *SS, - CorrectionCandidateCallback &CCC, - TypoDiagnosticGenerator TDG, - TypoRecoveryCallback TRC, CorrectTypoKind Mode, - DeclContext *MemberContext = nullptr, - bool EnteringContext = false, - const ObjCObjectPointerType *OPT = nullptr); + ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl, + const IdentifierInfo *MemberOrBase); - /// Process any TypoExprs in the given Expr and its children, - /// generating diagnostics as appropriate and returning a new Expr if there - /// were typos that were all successfully corrected and ExprError if one or - /// more typos could not be corrected. - /// - /// \param E The Expr to check for TypoExprs. - /// - /// \param InitDecl A VarDecl to avoid because the Expr being corrected is its - /// initializer. + enum class ComparisonCategoryUsage { + /// The '<=>' operator was used in an expression and a builtin operator + /// was selected. + OperatorInExpression, + /// A defaulted 'operator<=>' needed the comparison category. This + /// typically only applies to 'std::strong_ordering', due to the implicit + /// fallback return value. + DefaultedOperator, + }; + + /// Lookup the specified comparison category types in the standard + /// library, an check the VarDecls possibly returned by the operator<=> + /// builtins for that type. /// - /// \param RecoverUncorrectedTypos If true, when typo correction fails, it - /// will rebuild the given Expr with all TypoExprs degraded to RecoveryExprs. + /// \return The type of the comparison category type corresponding to the + /// specified Kind, or a null type if an error occurs + QualType CheckComparisonCategoryType(ComparisonCategoryType Kind, + SourceLocation Loc, + ComparisonCategoryUsage Usage); + + /// Tests whether Ty is an instance of std::initializer_list and, if + /// it is and Element is not NULL, assigns the element type to Element. + bool isStdInitializerList(QualType Ty, QualType *Element); + + /// Looks for the std::initializer_list template and instantiates it + /// with Element, or emits an error if it's not found. /// - /// \param Filter A function applied to a newly rebuilt Expr to determine if - /// it is an acceptable/usable result from a single combination of typo - /// corrections. As long as the filter returns ExprError, different - /// combinations of corrections will be tried until all are exhausted. - ExprResult CorrectDelayedTyposInExpr( - Expr *E, VarDecl *InitDecl = nullptr, - bool RecoverUncorrectedTypos = false, - llvm::function_ref Filter = - [](Expr *E) -> ExprResult { return E; }); + /// \returns The instantiated template, or null on error. + QualType BuildStdInitializerList(QualType Element, SourceLocation Loc); - ExprResult CorrectDelayedTyposInExpr( - ExprResult ER, VarDecl *InitDecl = nullptr, - bool RecoverUncorrectedTypos = false, - llvm::function_ref Filter = - [](Expr *E) -> ExprResult { return E; }) { - return ER.isInvalid() - ? ER - : CorrectDelayedTyposInExpr(ER.get(), InitDecl, - RecoverUncorrectedTypos, Filter); - } + /// Determine whether Ctor is an initializer-list constructor, as + /// defined in [dcl.init.list]p2. + bool isInitListConstructor(const FunctionDecl *Ctor); - void diagnoseTypo(const TypoCorrection &Correction, - const PartialDiagnostic &TypoDiag, - bool ErrorRecovery = true); + Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + const ParsedAttributesView &AttrList); - void diagnoseTypo(const TypoCorrection &Correction, - const PartialDiagnostic &TypoDiag, - const PartialDiagnostic &PrevNote, - bool ErrorRecovery = true); + void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); - void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F); + Decl *ActOnNamespaceAliasDef(Scope *CurScope, SourceLocation NamespaceLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, + CXXScopeSpec &SS, SourceLocation IdentLoc, + IdentifierInfo *Ident); - void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, - ArrayRef Args, - AssociatedNamespaceSet &AssociatedNamespaces, - AssociatedClassSet &AssociatedClasses); + void FilterUsingLookup(Scope *S, LookupResult &lookup); + void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow); + bool CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Target, + const LookupResult &PreviousDecls, + UsingShadowDecl *&PrevShadow); + UsingShadowDecl *BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD, + NamedDecl *Target, + UsingShadowDecl *PrevDecl); - void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, - bool ConsiderLinkage, bool AllowInlineNamespace); + bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc, + bool HasTypenameKeyword, + const CXXScopeSpec &SS, + SourceLocation NameLoc, + const LookupResult &Previous); + bool CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, + const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + SourceLocation NameLoc, + const LookupResult *R = nullptr, + const UsingDecl *UD = nullptr); - bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old); - bool CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old); - bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old); - bool IsRedefinitionInModule(const NamedDecl *New, - const NamedDecl *Old) const; + NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, + bool HasTypenameKeyword, + SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, + SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, + bool IsInstantiation, bool IsUsingIfExists); + NamedDecl *BuildUsingEnumDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, + SourceLocation EnumLoc, + SourceLocation NameLoc, + TypeSourceInfo *EnumType, EnumDecl *ED); + NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, + ArrayRef Expansions); - void DiagnoseAmbiguousLookup(LookupResult &Result); - //@} + bool CheckInheritingConstructorUsingDecl(UsingDecl *UD); - /// Attempts to produce a RecoveryExpr after some AST node cannot be created. - ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, - ArrayRef SubExprs, - QualType T = QualType()); + /// Given a derived-class using shadow declaration for a constructor and the + /// correspnding base class constructor, find or create the implicit + /// synthesized derived class constructor to use for this initialization. + CXXConstructorDecl * + findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor, + ConstructorUsingShadowDecl *DerivedShadow); - ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id, - SourceLocation IdLoc, - bool TypoCorrection = false); - FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID, - SourceLocation Loc); - NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, - Scope *S, bool ForRedeclaration, - SourceLocation Loc); - NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, - Scope *S); - void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction( - FunctionDecl *FD); - void AddKnownFunctionAttributes(FunctionDecl *FD); + Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, + SourceLocation UsingLoc, + SourceLocation TypenameLoc, CXXScopeSpec &SS, + UnqualifiedId &Name, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList); + Decl *ActOnUsingEnumDeclaration(Scope *CurScope, AccessSpecifier AS, + SourceLocation UsingLoc, + SourceLocation EnumLoc, + SourceLocation IdentLoc, IdentifierInfo &II, + CXXScopeSpec *SS = nullptr); + Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, + MultiTemplateParamsArg TemplateParams, + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec); - // More parsing and symbol table subroutines. + /// BuildCXXConstructExpr - Creates a complete call to a constructor, + /// including handling of its default argument expressions. + /// + /// \param ConstructKind - a CXXConstructExpr::ConstructionKind + ExprResult BuildCXXConstructExpr( + SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl, + CXXConstructorDecl *Constructor, MultiExprArg Exprs, + bool HadMultipleCandidates, bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, + CXXConstructionKind ConstructKind, SourceRange ParenRange); - void ProcessPragmaWeak(Scope *S, Decl *D); - // Decl attributes - this routine is the top level dispatcher. - void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); - // Helper for delayed processing of attributes. - void ProcessDeclAttributeDelayed(Decl *D, - const ParsedAttributesView &AttrList); + /// Build a CXXConstructExpr whose constructor has already been resolved if + /// it denotes an inherited constructor. + ExprResult BuildCXXConstructExpr( + SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, + bool HadMultipleCandidates, bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, + CXXConstructionKind ConstructKind, SourceRange ParenRange); - // Options for ProcessDeclAttributeList(). - struct ProcessDeclAttributeOptions { - ProcessDeclAttributeOptions() - : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {} + // FIXME: Can we remove this and have the above BuildCXXConstructExpr check if + // the constructor can be elidable? + ExprResult BuildCXXConstructExpr( + SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl, + CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, + bool HadMultipleCandidates, bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, + CXXConstructionKind ConstructKind, SourceRange ParenRange); - ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) { - ProcessDeclAttributeOptions Result = *this; - Result.IncludeCXX11Attributes = Val; - return Result; + ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr, + SourceLocation InitLoc); + + /// FinalizeVarWithDestructor - Prepare for calling destructor on the + /// constructed variable. + void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); + + /// Helper class that collects exception specifications for + /// implicitly-declared special member functions. + class ImplicitExceptionSpecification { + // Pointer to allow copying + Sema *Self; + // We order exception specifications thus: + // noexcept is the most restrictive, but is only used in C++11. + // throw() comes next. + // Then a throw(collected exceptions) + // Finally no specification, which is expressed as noexcept(false). + // throw(...) is used instead if any called function uses it. + ExceptionSpecificationType ComputedEST; + llvm::SmallPtrSet ExceptionsSeen; + SmallVector Exceptions; + + void ClearExceptions() { + ExceptionsSeen.clear(); + Exceptions.clear(); } - ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) { - ProcessDeclAttributeOptions Result = *this; - Result.IgnoreTypeAttributes = Val; - return Result; + public: + explicit ImplicitExceptionSpecification(Sema &Self) + : Self(&Self), ComputedEST(EST_BasicNoexcept) { + if (!Self.getLangOpts().CPlusPlus11) + ComputedEST = EST_DynamicNone; } - // Should C++11 attributes be processed? - bool IncludeCXX11Attributes; + /// Get the computed exception specification type. + ExceptionSpecificationType getExceptionSpecType() const { + assert(!isComputedNoexcept(ComputedEST) && + "noexcept(expr) should not be a possible result"); + return ComputedEST; + } - // Should any type attributes encountered be ignored? - // If this option is false, a diagnostic will be emitted for any type - // attributes of a kind that does not "slide" from the declaration to - // the decl-specifier-seq. - bool IgnoreTypeAttributes; - }; - - void ProcessDeclAttributeList(Scope *S, Decl *D, - const ParsedAttributesView &AttrList, - const ProcessDeclAttributeOptions &Options = - ProcessDeclAttributeOptions()); - bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const ParsedAttributesView &AttrList); + /// The number of exceptions in the exception specification. + unsigned size() const { return Exceptions.size(); } - void checkUnusedDeclAttributes(Declarator &D); + /// The set of exceptions in the exception specification. + const QualType *data() const { return Exceptions.data(); } - /// Handles semantic checking for features that are common to all attributes, - /// such as checking whether a parameter was properly specified, or the - /// correct number of arguments were passed, etc. Returns true if the - /// attribute has been diagnosed. - bool checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A, - bool SkipArgCountCheck = false); - bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, - bool SkipArgCountCheck = false); + /// Integrate another called method into the collected data. + void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method); - /// Map any API notes provided for this declaration to attributes on the - /// declaration. - /// - /// Triggered by declaration-attribute processing. - void ProcessAPINotes(Decl *D); + /// Integrate an invoked expression into the collected data. + void CalledExpr(Expr *E) { CalledStmt(E); } - /// Determine if type T is a valid subject for a nonnull and similar - /// attributes. By default, we look through references (the behavior used by - /// nonnull), but if the second parameter is true, then we treat a reference - /// type as valid. - bool isValidPointerAttrType(QualType T, bool RefOkay = false); + /// Integrate an invoked statement into the collected data. + void CalledStmt(Stmt *S); - bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value); + /// Overwrite an EPI's exception specification with this + /// computed exception specification. + FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const { + FunctionProtoType::ExceptionSpecInfo ESI; + ESI.Type = getExceptionSpecType(); + if (ESI.Type == EST_Dynamic) { + ESI.Exceptions = Exceptions; + } else if (ESI.Type == EST_None) { + /// C++11 [except.spec]p14: + /// The exception-specification is noexcept(false) if the set of + /// potential exceptions of the special member function contains "any" + ESI.Type = EST_NoexceptFalse; + ESI.NoexceptExpr = + Self->ActOnCXXBoolLiteral(SourceLocation(), tok::kw_false).get(); + } + return ESI; + } + }; - /// Check validaty of calling convention attribute \p attr. If \p FD - /// is not null pointer, use \p FD to determine the CUDA/HIP host/device - /// target. Otherwise, it is specified by \p CFT. - bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC, - const FunctionDecl *FD = nullptr, - CUDAFunctionTarget CFT = CFT_InvalidTarget); - bool CheckAttrTarget(const ParsedAttr &CurrAttr); - bool CheckAttrNoArgs(const ParsedAttr &CurrAttr); - bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, - const Expr *E, StringRef &Str, - SourceLocation *ArgLocation = nullptr); - bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum, - StringRef &Str, - SourceLocation *ArgLocation = nullptr); - llvm::Error isValidSectionSpecifier(StringRef Str); - bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); - bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); - bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, - StringRef &Str, bool &isDefault); - bool checkTargetClonesAttrString( - SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal, - Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault, - SmallVectorImpl> &StringsBuffer); - bool checkMSInheritanceAttrOnDefinition( - CXXRecordDecl *RD, SourceRange Range, bool BestCase, - MSInheritanceModel SemanticSpelling); + /// Evaluate the implicit exception specification for a defaulted + /// special member function. + void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD); - void CheckAlignasUnderalignment(Decl *D); + /// Check the given exception-specification and update the + /// exception specification information with the results. + void checkExceptionSpecification(bool IsTopLevel, + ExceptionSpecificationType EST, + ArrayRef DynamicExceptions, + ArrayRef DynamicExceptionRanges, + Expr *NoexceptExpr, + SmallVectorImpl &Exceptions, + FunctionProtoType::ExceptionSpecInfo &ESI); - bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, - const AttributeCommonInfo &A); - bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, - const AttributeCommonInfo &A); + /// Add an exception-specification to the given member function + /// (or member function template). The exception-specification was parsed + /// after the method itself was declared. + void actOnDelayedExceptionSpecification( + Decl *Method, ExceptionSpecificationType EST, + SourceRange SpecificationRange, ArrayRef DynamicExceptions, + ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr); - bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD); + /// Kinds of C++ special members. + enum CXXSpecialMember { + CXXDefaultConstructor, + CXXCopyConstructor, + CXXMoveConstructor, + CXXCopyAssignment, + CXXMoveAssignment, + CXXDestructor, + CXXInvalid + }; - /// Adjust the calling convention of a method to be the ABI default if it - /// wasn't specified explicitly. This handles method types formed from - /// function type typedefs and typename template arguments. - void adjustMemberFunctionCC(QualType &T, bool HasThisPointer, - bool IsCtorOrDtor, SourceLocation Loc); + class InheritedConstructorInfo; - // Check if there is an explicit attribute, but only look through parens. - // The intent is to look for an attribute on the current declarator, but not - // one that came from a typedef. - bool hasExplicitCallingConv(QualType T); + /// Determine if a special member function should have a deleted + /// definition when it is defaulted. + bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, + InheritedConstructorInfo *ICI = nullptr, + bool Diagnose = false); - /// Get the outermost AttributedType node that sets a calling convention. - /// Valid types should not have multiple attributes with different CCs. - const AttributedType *getCallingConvAttributedType(QualType T) const; + /// Produce notes explaining why a defaulted function was defined as deleted. + void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD); - /// Check whether a nullability type specifier can be added to the given - /// type through some means not written in source (e.g. API notes). + /// Declare the implicit default constructor for the given class. /// - /// \param Type The type to which the nullability specifier will be - /// added. On success, this type will be updated appropriately. + /// \param ClassDecl The class declaration into which the implicit + /// default constructor will be added. /// - /// \param Nullability The nullability specifier to add. + /// \returns The implicitly-declared default constructor. + CXXConstructorDecl * + DeclareImplicitDefaultConstructor(CXXRecordDecl *ClassDecl); + + /// DefineImplicitDefaultConstructor - Checks for feasibility of + /// defining this constructor as the default constructor. + void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor); + + /// Declare the implicit destructor for the given class. /// - /// \param DiagLoc The location to use for diagnostics. + /// \param ClassDecl The class declaration into which the implicit + /// destructor will be added. /// - /// \param AllowArrayTypes Whether to accept nullability specifiers on an - /// array type (e.g., because it will decay to a pointer). + /// \returns The implicitly-declared destructor. + CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl); + + /// DefineImplicitDestructor - Checks for feasibility of + /// defining this destructor as the default destructor. + void DefineImplicitDestructor(SourceLocation CurrentLocation, + CXXDestructorDecl *Destructor); + + /// Build an exception spec for destructors that don't have one. /// - /// \param OverrideExisting Whether to override an existing, locally-specified - /// nullability specifier rather than complaining about the conflict. + /// C++11 says that user-defined destructors with no exception spec get one + /// that looks as if the destructor was implicitly declared. + void AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor); + + /// Define the specified inheriting constructor. + void DefineInheritingConstructor(SourceLocation UseLoc, + CXXConstructorDecl *Constructor); + + /// Declare the implicit copy constructor for the given class. /// - /// \returns true if nullability cannot be applied, false otherwise. - bool CheckImplicitNullabilityTypeSpecifier(QualType &Type, - NullabilityKind Nullability, - SourceLocation DiagLoc, - bool AllowArrayTypes, - bool OverrideExisting); + /// \param ClassDecl The class declaration into which the implicit + /// copy constructor will be added. + /// + /// \returns The implicitly-declared copy constructor. + CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl); - /// Process the attributes before creating an attributed statement. Returns - /// the semantic attributes that have been processed. - void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs, - SmallVectorImpl &OutAttrs); + /// DefineImplicitCopyConstructor - Checks for feasibility of + /// defining this constructor as the copy constructor. + void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor); - void WarnConflictingTypedMethods(ObjCMethodDecl *Method, - ObjCMethodDecl *MethodDecl, - bool IsProtocolMethodDecl); + /// Declare the implicit move constructor for the given class. + /// + /// \param ClassDecl The Class declaration into which the implicit + /// move constructor will be added. + /// + /// \returns The implicitly-declared move constructor, or NULL if it wasn't + /// declared. + CXXConstructorDecl *DeclareImplicitMoveConstructor(CXXRecordDecl *ClassDecl); - void CheckConflictingOverridingMethod(ObjCMethodDecl *Method, - ObjCMethodDecl *Overridden, - bool IsProtocolMethodDecl); + /// DefineImplicitMoveConstructor - Checks for feasibility of + /// defining this constructor as the move constructor. + void DefineImplicitMoveConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor); - /// WarnExactTypedMethods - This routine issues a warning if method - /// implementation declaration matches exactly that of its declaration. - void WarnExactTypedMethods(ObjCMethodDecl *Method, - ObjCMethodDecl *MethodDecl, - bool IsProtocolMethodDecl); + /// Declare the implicit copy assignment operator for the given class. + /// + /// \param ClassDecl The class declaration into which the implicit + /// copy assignment operator will be added. + /// + /// \returns The implicitly-declared copy assignment operator. + CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl); - typedef llvm::SmallPtrSet SelectorSet; + /// Defines an implicitly-declared copy assignment operator. + void DefineImplicitCopyAssignment(SourceLocation CurrentLocation, + CXXMethodDecl *MethodDecl); - /// CheckImplementationIvars - This routine checks if the instance variables - /// listed in the implelementation match those listed in the interface. - void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, - ObjCIvarDecl **Fields, unsigned nIvars, - SourceLocation Loc); + /// Declare the implicit move assignment operator for the given class. + /// + /// \param ClassDecl The Class declaration into which the implicit + /// move assignment operator will be added. + /// + /// \returns The implicitly-declared move assignment operator, or NULL if it + /// wasn't declared. + CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl); - /// ImplMethodsVsClassMethods - This is main routine to warn if any method - /// remains unimplemented in the class or category \@implementation. - void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, - ObjCContainerDecl* IDecl, - bool IncompleteImpl = false); + /// Defines an implicitly-declared move assignment operator. + void DefineImplicitMoveAssignment(SourceLocation CurrentLocation, + CXXMethodDecl *MethodDecl); - /// DiagnoseUnimplementedProperties - This routine warns on those properties - /// which must be implemented by this implementation. - void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, - ObjCContainerDecl *CDecl, - bool SynthesizeProperties); + /// Check a completed declaration of an implicit special member. + void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD); - /// Diagnose any null-resettable synthesized setters. - void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl); + /// Determine whether the given function is an implicitly-deleted + /// special member function. + bool isImplicitlyDeleted(FunctionDecl *FD); - /// DefaultSynthesizeProperties - This routine default synthesizes all - /// properties which must be synthesized in the class's \@implementation. - void DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, - ObjCInterfaceDecl *IDecl, - SourceLocation AtEnd); - void DefaultSynthesizeProperties(Scope *S, Decl *D, SourceLocation AtEnd); + /// Check whether 'this' shows up in the type of a static member + /// function after the (naturally empty) cv-qualifier-seq would be. + /// + /// \returns true if an error occurred. + bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method); - /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is - /// an ivar synthesized for 'Method' and 'Method' is a property accessor - /// declared in class 'IFace'. - bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, - ObjCMethodDecl *Method, ObjCIvarDecl *IV); + /// Whether this' shows up in the exception specification of a static + /// member function. + bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method); - /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which - /// backs the property is not used in the property's accessor. - void DiagnoseUnusedBackingIvarInAccessor(Scope *S, - const ObjCImplementationDecl *ImplD); + /// Check whether 'this' shows up in the attributes of the given + /// static member function. + /// + /// \returns true if an error occurred. + bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method); - /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and - /// it property has a backing ivar, returns this ivar; otherwise, returns NULL. - /// It also returns ivar's property on success. - ObjCIvarDecl *GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, - const ObjCPropertyDecl *&PDecl) const; + bool CheckImmediateEscalatingFunctionDefinition( + FunctionDecl *FD, const sema::FunctionScopeInfo *FSI); - /// Called by ActOnProperty to handle \@property declarations in - /// class extensions. - ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S, - SourceLocation AtLoc, - SourceLocation LParenLoc, - FieldDeclarator &FD, - Selector GetterSel, - SourceLocation GetterNameLoc, - Selector SetterSel, - SourceLocation SetterNameLoc, - const bool isReadWrite, - unsigned &Attributes, - const unsigned AttributesAsWritten, - QualType T, - TypeSourceInfo *TSI, - tok::ObjCKeywordKind MethodImplKind); + void DiagnoseImmediateEscalatingReason(FunctionDecl *FD); - /// Called by ActOnProperty and HandlePropertyInClassExtension to - /// handle creating the ObjcPropertyDecl for a category or \@interface. - ObjCPropertyDecl *CreatePropertyDecl(Scope *S, - ObjCContainerDecl *CDecl, - SourceLocation AtLoc, - SourceLocation LParenLoc, - FieldDeclarator &FD, - Selector GetterSel, - SourceLocation GetterNameLoc, - Selector SetterSel, - SourceLocation SetterNameLoc, - const bool isReadWrite, - const unsigned Attributes, - const unsigned AttributesAsWritten, - QualType T, - TypeSourceInfo *TSI, - tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC = nullptr); + bool CompleteConstructorCall(CXXConstructorDecl *Constructor, + QualType DeclInitType, MultiExprArg ArgsPtr, + SourceLocation Loc, + SmallVectorImpl &ConvertedArgs, + bool AllowExplicit = false, + bool IsListInitialization = false); - /// AtomicPropertySetterGetterRules - This routine enforces the rule (via - /// warning) when atomic property has one but not the other user-declared - /// setter or getter. - void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl, - ObjCInterfaceDecl* IDecl); + /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an + /// initializer for the declaration 'Dcl'. + /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a + /// static data member of class X, names should be looked up in the scope of + /// class X. + void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl); - void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D); + /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an + /// initializer for the declaration 'Dcl'. + void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); - void DiagnoseMissingDesignatedInitOverrides( - const ObjCImplementationDecl *ImplD, - const ObjCInterfaceDecl *IFD); + /// Define the "body" of the conversion from a lambda object to a + /// function pointer. + /// + /// This routine doesn't actually define a sensible body; rather, it fills + /// in the initialization expression needed to copy the lambda object into + /// the block, and IR generation actually generates the real body of the + /// block pointer conversion. + void + DefineImplicitLambdaToFunctionPointerConversion(SourceLocation CurrentLoc, + CXXConversionDecl *Conv); - void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); + /// Define the "body" of the conversion from a lambda object to a + /// block pointer. + /// + /// This routine doesn't actually define a sensible body; rather, it fills + /// in the initialization expression needed to copy the lambda object into + /// the block, and IR generation actually generates the real body of the + /// block pointer conversion. + void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc, + CXXConversionDecl *Conv); - enum MethodMatchStrategy { - MMS_loose, - MMS_strict - }; + Decl *ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, + Expr *LangStr, SourceLocation LBraceLoc); + Decl *ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec, + SourceLocation RBraceLoc); - /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns - /// true, or false, accordingly. - bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, - const ObjCMethodDecl *PrevMethod, - MethodMatchStrategy strategy = MMS_strict); + //===--------------------------------------------------------------------===// + // C++ Classes + // + CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS); + bool isCurrentClassName(const IdentifierInfo &II, Scope *S, + const CXXScopeSpec *SS = nullptr); + bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); - /// MatchAllMethodDeclarations - Check methods declaraed in interface or - /// or protocol against those declared in their implementations. - void MatchAllMethodDeclarations(const SelectorSet &InsMap, - const SelectorSet &ClsMap, - SelectorSet &InsMapSeen, - SelectorSet &ClsMapSeen, - ObjCImplDecl* IMPDecl, - ObjCContainerDecl* IDecl, - bool &IncompleteImpl, - bool ImmediateClass, - bool WarnCategoryMethodImpl=false); + bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, + SourceLocation ColonLoc, + const ParsedAttributesView &Attrs); - /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in - /// category matches with those implemented in its primary class and - /// warns each time an exact match is found. - void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); + NamedDecl * + ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + Expr *BitfieldWidth, const VirtSpecifiers &VS, + InClassInitStyle InitStyle); - /// Add the given method to the list of globally-known methods. - void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); + void ActOnStartCXXInClassMemberInitializer(); + void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl, + SourceLocation EqualLoc, + Expr *Init); - /// Returns default addr space for method qualifiers. - LangAS getDefaultCXXMethodAddrSpace() const; + MemInitResult + ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, + SourceLocation LParenLoc, ArrayRef Args, + SourceLocation RParenLoc, SourceLocation EllipsisLoc); -private: - /// AddMethodToGlobalPool - Add an instance or factory method to the global - /// pool. See descriptoin of AddInstanceMethodToGlobalPool. - void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance); + MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, + Expr *InitList, SourceLocation EllipsisLoc); - /// LookupMethodInGlobalPool - Returns the instance or factory method and - /// optionally warns if there are multiple signatures. - ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R, - bool receiverIdOrClass, - bool instance); + MemInitResult BuildMemInitializer(Decl *ConstructorD, Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + const DeclSpec &DS, SourceLocation IdLoc, + Expr *Init, SourceLocation EllipsisLoc); -public: - /// - Returns instance or factory methods in global method pool for - /// given selector. It checks the desired kind first, if none is found, and - /// parameter checkTheOther is set, it then checks the other kind. If no such - /// method or only one method is found, function returns false; otherwise, it - /// returns true. - bool - CollectMultipleMethodsInGlobalPool(Selector Sel, - SmallVectorImpl& Methods, - bool InstanceFirst, bool CheckTheOther, - const ObjCObjectType *TypeBound = nullptr); + MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr *Init, + SourceLocation IdLoc); - bool - AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, - SourceRange R, bool receiverIdOrClass, - SmallVectorImpl& Methods); + MemInitResult BuildBaseInitializer(QualType BaseType, + TypeSourceInfo *BaseTInfo, Expr *Init, + CXXRecordDecl *ClassDecl, + SourceLocation EllipsisLoc); - void - DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods, - Selector Sel, SourceRange R, - bool receiverIdOrClass); + MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, + CXXRecordDecl *ClassDecl); -private: - /// - Returns a selector which best matches given argument list or - /// nullptr if none could be found - ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args, - bool IsInstance, - SmallVectorImpl& Methods); + bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, + CXXCtorInitializer *Initializer); + bool SetCtorInitializers( + CXXConstructorDecl *Constructor, bool AnyErrors, + ArrayRef Initializers = std::nullopt); - /// Record the typo correction failure and return an empty correction. - TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc, - bool RecordFailure = true) { - if (RecordFailure) - TypoCorrectionFailures[Typo].insert(TypoLoc); - return TypoCorrection(); - } + void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); -public: - /// AddInstanceMethodToGlobalPool - All instance methods in a translation - /// unit are added to a global pool. This allows us to efficiently associate - /// a selector with a method declaraation for purposes of typechecking - /// messages sent to "id" (where the class of the object is unknown). - void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) { - AddMethodToGlobalPool(Method, impl, /*instance*/true); - } + /// MarkBaseAndMemberDestructorsReferenced - Given a record decl, + /// mark all the non-trivial destructors of its members and bases as + /// referenced. + void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc, + CXXRecordDecl *Record); - /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. - void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) { - AddMethodToGlobalPool(Method, impl, /*instance*/false); - } + /// Mark destructors of virtual bases of this class referenced. In the Itanium + /// C++ ABI, this is done when emitting a destructor for any non-abstract + /// class. In the Microsoft C++ ABI, this is done any time a class's + /// destructor is referenced. + void MarkVirtualBaseDestructorsReferenced( + SourceLocation Location, CXXRecordDecl *ClassDecl, + llvm::SmallPtrSetImpl *DirectVirtualBases = nullptr); - /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global - /// pool. - void AddAnyMethodToGlobalPool(Decl *D); + /// Do semantic checks to allow the complete destructor variant to be emitted + /// when the destructor is defined in another translation unit. In the Itanium + /// C++ ABI, destructor variants are emitted together. In the MS C++ ABI, they + /// can be emitted in separate TUs. To emit the complete variant, run a subset + /// of the checks performed when emitting a regular destructor. + void CheckCompleteDestructorVariant(SourceLocation CurrentLocation, + CXXDestructorDecl *Dtor); - /// LookupInstanceMethodInGlobalPool - Returns the method and warns if - /// there are multiple signatures. - ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, - bool receiverIdOrClass=false) { - return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, - /*instance*/true); - } + /// The list of classes whose vtables have been used within + /// this translation unit, and the source locations at which the + /// first use occurred. + typedef std::pair VTableUse; - /// LookupFactoryMethodInGlobalPool - Returns the method and warns if - /// there are multiple signatures. - ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R, - bool receiverIdOrClass=false) { - return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, - /*instance*/false); - } + /// The list of vtables that are required but have not yet been + /// materialized. + SmallVector VTableUses; - const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel, - QualType ObjectType=QualType()); - /// LookupImplementedMethodInGlobalPool - Returns the method which has an - /// implementation. - ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); + /// The set of classes whose vtables have been used within + /// this translation unit, and a bit that will be true if the vtable is + /// required to be emitted (otherwise, it should be emitted only if needed + /// by code generation). + llvm::DenseMap VTablesUsed; - /// CollectIvarsToConstructOrDestruct - Collect those ivars which require - /// initialization. - void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, - SmallVectorImpl &Ivars); + /// Load any externally-stored vtable uses. + void LoadExternalVTableUses(); - //===--------------------------------------------------------------------===// - // Statement Parsing Callbacks: SemaStmt.cpp. -public: - class FullExprArg { - public: - FullExprArg() : E(nullptr) { } - FullExprArg(Sema &actions) : E(nullptr) { } + /// Note that the vtable for the given class was used at the + /// given location. + void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, + bool DefinitionRequired = false); - ExprResult release() { - return E; - } + /// Mark the exception specifications of all virtual member functions + /// in the given class as needed. + void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, + const CXXRecordDecl *RD); - Expr *get() const { return E; } + /// MarkVirtualMembersReferenced - Will mark all members of the given + /// CXXRecordDecl referenced. + void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD, + bool ConstexprOnly = false); - Expr *operator->() { - return E; - } + /// Define all of the vtables that have been used in this + /// translation unit and reference any virtual members used by those + /// vtables. + /// + /// \returns true if any work was done, false otherwise. + bool DefineUsedVTables(); - private: - // FIXME: No need to make the entire Sema class a friend when it's just - // Sema::MakeFullExpr that needs access to the constructor below. - friend class Sema; + void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); - explicit FullExprArg(Expr *expr) : E(expr) {} + void ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, + ArrayRef MemInits, + bool AnyErrors); - Expr *E; - }; + /// Check class-level dllimport/dllexport attribute. The caller must + /// ensure that referenceDLLExportedClassMethods is called some point later + /// when all outer classes of Class are complete. + void checkClassLevelDLLAttribute(CXXRecordDecl *Class); + void checkClassLevelCodeSegAttribute(CXXRecordDecl *Class); - FullExprArg MakeFullExpr(Expr *Arg) { - return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); - } - FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { - return FullExprArg( - ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get()); - } - FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { - ExprResult FE = - ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), - /*DiscardedValue*/ true); - return FullExprArg(FE.get()); - } + void referenceDLLExportedClassMethods(); - StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true); - StmtResult ActOnExprStmtError(); + void propagateDLLAttrToBaseClassTemplate( + CXXRecordDecl *Class, Attr *ClassAttr, + ClassTemplateSpecializationDecl *BaseTemplateSpec, + SourceLocation BaseLoc); - StmtResult ActOnNullStmt(SourceLocation SemiLoc, - bool HasLeadingEmptyMacro = false); + void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record); - void ActOnStartOfCompoundStmt(bool IsStmtExpr); - void ActOnAfterCompoundStatementLeadingPragmas(); - void ActOnFinishOfCompoundStmt(); - StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, - ArrayRef Elts, bool isStmtExpr); + /// Check that the C++ class annoated with "trivial_abi" satisfies all the + /// conditions that are needed for the attribute to have an effect. + void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD); - /// A RAII object to enter scope of a compound statement. - class CompoundScopeRAII { - public: - CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) { - S.ActOnStartOfCompoundStmt(IsStmtExpr); - } + void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc, + Decl *TagDecl, SourceLocation LBrac, + SourceLocation RBrac, + const ParsedAttributesView &AttrList); + void ActOnFinishCXXMemberDecls(); + void ActOnFinishCXXNonNestedClass(); - ~CompoundScopeRAII() { - S.ActOnFinishOfCompoundStmt(); - } + void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param); + unsigned ActOnReenterTemplateScope(Decl *Template, + llvm::function_ref EnterScope); + void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); + void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); + void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); + void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record); + void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method); + void ActOnFinishDelayedMemberInitializers(Decl *Record); - private: - Sema &S; - }; + bool EvaluateStaticAssertMessageAsString(Expr *Message, std::string &Result, + ASTContext &Ctx, + bool ErrorOnInvalidMessage); + Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, + Expr *AssertExpr, Expr *AssertMessageExpr, + SourceLocation RParenLoc); + Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, + Expr *AssertExpr, Expr *AssertMessageExpr, + SourceLocation RParenLoc, bool Failed); + void DiagnoseStaticAssertDetails(const Expr *E); - /// An RAII helper that pops function a function scope on exit. - struct FunctionScopeRAII { - Sema &S; - bool Active; - FunctionScopeRAII(Sema &S) : S(S), Active(true) {} - ~FunctionScopeRAII() { - if (Active) - S.PopFunctionScopeInfo(); - } - void disable() { Active = false; } - }; + Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, + MultiTemplateParamsArg TemplateParams); + NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParams); - StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, - SourceLocation StartLoc, - SourceLocation EndLoc); - void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); - StmtResult ActOnForEachLValueExpr(Expr *E); - ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val); - StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS, - SourceLocation DotDotDotLoc, ExprResult RHS, - SourceLocation ColonLoc); - void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt); + QualType CheckConstructorDeclarator(Declarator &D, QualType R, + StorageClass &SC); + void CheckConstructor(CXXConstructorDecl *Constructor); + QualType CheckDestructorDeclarator(Declarator &D, QualType R, + StorageClass &SC); + bool CheckDestructor(CXXDestructorDecl *Destructor); + void CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass &SC); + Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); + bool CheckDeductionGuideDeclarator(Declarator &D, QualType &R, + StorageClass &SC); - StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, - SourceLocation ColonLoc, - Stmt *SubStmt, Scope *CurScope); - StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, - SourceLocation ColonLoc, Stmt *SubStmt); + void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD); - StmtResult BuildAttributedStmt(SourceLocation AttrsLoc, - ArrayRef Attrs, Stmt *SubStmt); - StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList, - Stmt *SubStmt); + bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, + CXXSpecialMember CSM, + SourceLocation DefaultLoc); + void CheckDelayedMemberExceptionSpecs(); - class ConditionResult; + /// Kinds of defaulted comparison operator functions. + enum class DefaultedComparisonKind : unsigned char { + /// This is not a defaultable comparison operator. + None, + /// This is an operator== that should be implemented as a series of + /// subobject comparisons. + Equal, + /// This is an operator<=> that should be implemented as a series of + /// subobject comparisons. + ThreeWay, + /// This is an operator!= that should be implemented as a rewrite in terms + /// of a == comparison. + NotEqual, + /// This is an <, <=, >, or >= that should be implemented as a rewrite in + /// terms of a <=> comparison. + Relational, + }; - StmtResult ActOnIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind, - SourceLocation LParenLoc, Stmt *InitStmt, - ConditionResult Cond, SourceLocation RParenLoc, - Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal); - StmtResult BuildIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind, - SourceLocation LParenLoc, Stmt *InitStmt, - ConditionResult Cond, SourceLocation RParenLoc, - Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal); - StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, - SourceLocation LParenLoc, Stmt *InitStmt, - ConditionResult Cond, - SourceLocation RParenLoc); - StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, - Stmt *Switch, Stmt *Body); - StmtResult ActOnWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc, - ConditionResult Cond, SourceLocation RParenLoc, - Stmt *Body); - StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, - SourceLocation WhileLoc, SourceLocation CondLParen, - Expr *Cond, SourceLocation CondRParen); + bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD, + DefaultedComparisonKind DCK); + void DeclareImplicitEqualityComparison(CXXRecordDecl *RD, + FunctionDecl *Spaceship); + void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD, + DefaultedComparisonKind DCK); - StmtResult ActOnForStmt(SourceLocation ForLoc, - SourceLocation LParenLoc, - Stmt *First, - ConditionResult Second, - FullExprArg Third, - SourceLocation RParenLoc, - Stmt *Body); - ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc, - Expr *collection); - StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, - Stmt *First, Expr *collection, - SourceLocation RParenLoc); - StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body); + void CheckExplicitObjectMemberFunction(Declarator &D, DeclarationName Name, + QualType R, bool IsLambda, + DeclContext *DC = nullptr); + void CheckExplicitObjectMemberFunction(DeclContext *DC, Declarator &D, + DeclarationName Name, QualType R); + void CheckExplicitObjectLambda(Declarator &D); - enum BuildForRangeKind { - /// Initial building of a for-range statement. - BFRK_Build, - /// Instantiation or recovery rebuild of a for-range statement. Don't - /// attempt any typo-correction. - BFRK_Rebuild, - /// Determining whether a for-range statement could be built. Avoid any - /// unnecessary or irreversible actions. - BFRK_Check - }; + //===--------------------------------------------------------------------===// + // C++ Derived Classes + // - StmtResult ActOnCXXForRangeStmt( - Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, - Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection, - SourceLocation RParenLoc, BuildForRangeKind Kind, - ArrayRef LifetimeExtendTemps = {}); - StmtResult BuildCXXForRangeStmt( - SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, - SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, - Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, - BuildForRangeKind Kind, - ArrayRef LifetimeExtendTemps = {}); - StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body); + /// ActOnBaseSpecifier - Parsed a base specifier + CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class, + SourceRange SpecifierRange, bool Virtual, + AccessSpecifier Access, + TypeSourceInfo *TInfo, + SourceLocation EllipsisLoc); - StmtResult ActOnGotoStmt(SourceLocation GotoLoc, - SourceLocation LabelLoc, - LabelDecl *TheDecl); - StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, - SourceLocation StarLoc, - Expr *DestExp); - StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope); - StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope); + BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, + const ParsedAttributesView &Attrs, bool Virtual, + AccessSpecifier Access, ParsedType basetype, + SourceLocation BaseLoc, + SourceLocation EllipsisLoc); - void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, - CapturedRegionKind Kind, unsigned NumParams); - typedef std::pair CapturedParamNameType; - void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, - CapturedRegionKind Kind, - ArrayRef Params, - unsigned OpenMPCaptureLevel = 0); - StmtResult ActOnCapturedRegionEnd(Stmt *S); - void ActOnCapturedRegionError(); - RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD, - SourceLocation Loc, - unsigned NumParams); + bool AttachBaseSpecifiers(CXXRecordDecl *Class, + MutableArrayRef Bases); + void ActOnBaseSpecifiers(Decl *ClassDecl, + MutableArrayRef Bases); - struct NamedReturnInfo { - const VarDecl *Candidate; + bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base); + bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, + CXXBasePaths &Paths); - enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable }; - Status S; + // FIXME: I don't like this name. + void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath); - bool isMoveEligible() const { return S != None; }; - bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; } - }; - enum class SimplerImplicitMoveMode { ForceOff, Normal, ForceOn }; - NamedReturnInfo getNamedReturnInfo( - Expr *&E, SimplerImplicitMoveMode Mode = SimplerImplicitMoveMode::Normal); - NamedReturnInfo getNamedReturnInfo(const VarDecl *VD); - const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info, - QualType ReturnType); + bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, + SourceLocation Loc, SourceRange Range, + CXXCastPath *BasePath = nullptr, + bool IgnoreAccess = false); + bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, + unsigned InaccessibleBaseID, + unsigned AmbiguousBaseConvID, + SourceLocation Loc, SourceRange Range, + DeclarationName Name, CXXCastPath *BasePath, + bool IgnoreAccess = false); - ExprResult - PerformMoveOrCopyInitialization(const InitializedEntity &Entity, - const NamedReturnInfo &NRInfo, Expr *Value, - bool SupressSimplerImplicitMoves = false); + std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths); - StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, - Scope *CurScope); - StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, - bool AllowRecovery = false); - StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, - NamedReturnInfo &NRInfo, - bool SupressSimplerImplicitMoves); + bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New, + const CXXMethodDecl *Old); - StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, - bool IsVolatile, unsigned NumOutputs, - unsigned NumInputs, IdentifierInfo **Names, - MultiExprArg Constraints, MultiExprArg Exprs, - Expr *AsmString, MultiExprArg Clobbers, - unsigned NumLabels, - SourceLocation RParenLoc); + /// CheckOverridingFunctionReturnType - Checks whether the return types are + /// covariant, according to C++ [class.virtual]p5. + bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New, + const CXXMethodDecl *Old); - void FillInlineAsmIdentifierInfo(Expr *Res, - llvm::InlineAsmIdentifierInfo &Info); - ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - UnqualifiedId &Id, - bool IsUnevaluatedContext); - bool LookupInlineAsmField(StringRef Base, StringRef Member, - unsigned &Offset, SourceLocation AsmLoc); - ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, - SourceLocation AsmLoc); - StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, - ArrayRef AsmToks, - StringRef AsmString, - unsigned NumOutputs, unsigned NumInputs, - ArrayRef Constraints, - ArrayRef Clobbers, - ArrayRef Exprs, - SourceLocation EndLoc); - LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName, - SourceLocation Location, - bool AlwaysCreate); + // Check that the overriding method has no explicit object parameter. + bool CheckExplicitObjectOverride(CXXMethodDecl *New, + const CXXMethodDecl *Old); - VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, - bool Invalid = false); + bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange); - Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D); + /// CheckOverrideControl - Check C++11 override control semantics. + void CheckOverrideControl(NamedDecl *D); - StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, - Decl *Parm, Stmt *Body); + /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was + /// not used in the declaration of an overriding method. + void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent); - StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body); + /// CheckForFunctionMarkedFinal - Checks whether a virtual member function + /// overrides a virtual member function marked 'final', according to + /// C++11 [class.virtual]p4. + bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, + const CXXMethodDecl *Old); - StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, - MultiStmtArg Catch, Stmt *Finally); + enum AbstractDiagSelID { + AbstractNone = -1, + AbstractReturnType, + AbstractParamType, + AbstractVariableType, + AbstractFieldType, + AbstractIvarType, + AbstractSynthesizedIvarType, + AbstractArrayType + }; - StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw); - StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, - Scope *CurScope); - ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, - Expr *operand); - StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, - Expr *SynchExpr, - Stmt *SynchBody); + struct TypeDiagnoser; - StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body); + bool isAbstractType(SourceLocation Loc, QualType T); + bool RequireNonAbstractType(SourceLocation Loc, QualType T, + TypeDiagnoser &Diagnoser); + template + bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, + const Ts &...Args) { + BoundTypeDiagnoser Diagnoser(DiagID, Args...); + return RequireNonAbstractType(Loc, T, Diagnoser); + } - VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, - SourceLocation StartLoc, - SourceLocation IdLoc, - IdentifierInfo *Id); + void DiagnoseAbstractType(const CXXRecordDecl *RD); - Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D); + //===--------------------------------------------------------------------===// + // C++ Overloaded Operators [C++ 13.5] + // - StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, - Decl *ExDecl, Stmt *HandlerBlock); - StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, - ArrayRef Handlers); + bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl); - StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ? - SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler); - StmtResult ActOnSEHExceptBlock(SourceLocation Loc, - Expr *FilterExpr, - Stmt *Block); - void ActOnStartSEHFinallyBlock(); - void ActOnAbortSEHFinallyBlock(); - StmtResult ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block); - StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope); + bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl); - void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); + /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression + /// found in an explicit(bool) specifier. + ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E); - bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; + /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier. + /// Returns true if the explicit specifier is now resolved. + bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec); - /// If it's a file scoped decl that must warn if not used, keep track - /// of it. - void MarkUnusedFileScopedDecl(const DeclaratorDecl *D); + DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); - typedef llvm::function_ref - DiagReceiverTy; + // Emitting members of dllexported classes is delayed until the class + // (including field initializers) is fully parsed. + SmallVector DelayedDllExportClasses; + SmallVector DelayedDllExportMemberFunctions; - /// DiagnoseUnusedExprResult - If the statement passed in is an expression - /// whose result is unused, warn. - void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID); - void DiagnoseUnusedNestedTypedefs(const RecordDecl *D); - void DiagnoseUnusedNestedTypedefs(const RecordDecl *D, - DiagReceiverTy DiagReceiver); - void DiagnoseUnusedDecl(const NamedDecl *ND); - void DiagnoseUnusedDecl(const NamedDecl *ND, DiagReceiverTy DiagReceiver); + void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); + bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); - /// If VD is set but not otherwise used, diagnose, for a parameter or a - /// variable. - void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver); + /// Helpers for dealing with blocks and functions. + void CheckCXXDefaultArguments(FunctionDecl *FD); + void CheckExtraCXXDefaultArguments(Declarator &D); - /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null - /// statement as a \p Body, and it is located on the same line. - /// - /// This helps prevent bugs due to typos, such as: - /// if (condition); - /// do_stuff(); - void DiagnoseEmptyStmtBody(SourceLocation StmtLoc, - const Stmt *Body, - unsigned DiagID); + CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) { + return getDefaultedFunctionKind(MD).asSpecialMember(); + } - /// Warn if a for/while loop statement \p S, which is followed by - /// \p PossibleBody, has a suspicious null statement as a body. - void DiagnoseEmptyLoopBody(const Stmt *S, - const Stmt *PossibleBody); + VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id); - /// Warn if a value is moved to itself. - void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, - SourceLocation OpLoc); + Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D); - /// Returns a field in a CXXRecordDecl that has the same name as the decl \p - /// SelfAssigned when inside a CXXMethodDecl. - const FieldDecl * - getSelfAssignmentClassMemberCandidate(const ValueDecl *SelfAssigned); + void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); - /// Warn if we're implicitly casting from a _Nullable pointer type to a - /// _Nonnull one. - void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, - SourceLocation Loc); + DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, + unsigned TagSpec, SourceLocation TagLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TempParamLists); - /// Warn when implicitly casting 0 to nullptr. - void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E); + MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD, + SourceLocation DeclStart, Declarator &D, + Expr *BitfieldWidth, + InClassInitStyle InitStyle, + AccessSpecifier AS, + const ParsedAttr &MSPropertyAttr); - ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { - return DelayedDiagnostics.push(pool); - } - void PopParsingDeclaration(ParsingDeclState state, Decl *decl); + void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); - typedef ProcessingContextState ParsingClassState; - ParsingClassState PushParsingClass() { - ParsingClassDepth++; - return DelayedDiagnostics.pushUndelayed(); - } - void PopParsingClass(ParsingClassState state) { - ParsingClassDepth--; - DelayedDiagnostics.popUndelayed(state); - } + enum TrivialABIHandling { + /// The triviality of a method unaffected by "trivial_abi". + TAH_IgnoreTrivialABI, - void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); + /// The triviality of a method affected by "trivial_abi". + TAH_ConsiderTrivialABI + }; - void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef Locs, - const ObjCInterfaceDecl *UnknownObjCClass, - bool ObjCPropertyAccess, - bool AvoidPartialAvailabilityChecks = false, - ObjCInterfaceDecl *ClassReceiver = nullptr); + bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, + TrivialABIHandling TAH = TAH_IgnoreTrivialABI, + bool Diagnose = false); - bool makeUnavailableInSystemHeader(SourceLocation loc, - UnavailableAttr::ImplicitReason reason); + /// For a defaulted function, the kind of defaulted function that it is. + class DefaultedFunctionKind { + unsigned SpecialMember : 8; + unsigned Comparison : 8; - /// Issue any -Wunguarded-availability warnings in \c FD - void DiagnoseUnguardedAvailabilityViolations(Decl *FD); + public: + DefaultedFunctionKind() + : SpecialMember(CXXInvalid), + Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} + DefaultedFunctionKind(CXXSpecialMember CSM) + : SpecialMember(CSM), + Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {} + DefaultedFunctionKind(DefaultedComparisonKind Comp) + : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(Comp)) {} - void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); + bool isSpecialMember() const { return SpecialMember != CXXInvalid; } + bool isComparison() const { + return static_cast(Comparison) != + DefaultedComparisonKind::None; + } - //===--------------------------------------------------------------------===// - // Expression Parsing Callbacks: SemaExpr.cpp. + explicit operator bool() const { + return isSpecialMember() || isComparison(); + } - bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid); - // A version of DiagnoseUseOfDecl that should be used if overload resolution - // has been used to find this declaration, which means we don't have to bother - // checking the trailing requires clause. - bool DiagnoseUseOfOverloadedDecl(NamedDecl *D, SourceLocation Loc) { - return DiagnoseUseOfDecl( - D, Loc, /*UnknownObjCClass=*/nullptr, /*ObjCPropertyAccess=*/false, - /*AvoidPartialAvailabilityChecks=*/false, /*ClassReceiver=*/nullptr, - /*SkipTrailingRequiresClause=*/true); - } + CXXSpecialMember asSpecialMember() const { + return static_cast(SpecialMember); + } + DefaultedComparisonKind asComparison() const { + return static_cast(Comparison); + } - bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, - const ObjCInterfaceDecl *UnknownObjCClass = nullptr, - bool ObjCPropertyAccess = false, - bool AvoidPartialAvailabilityChecks = false, - ObjCInterfaceDecl *ClassReciever = nullptr, - bool SkipTrailingRequiresClause = false); - void NoteDeletedFunction(FunctionDecl *FD); - void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD); - bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, - ObjCMethodDecl *Getter, - SourceLocation Loc); - void DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc, - ArrayRef Args); + /// Get the index of this function kind for use in diagnostics. + unsigned getDiagnosticIndex() const { + static_assert(CXXInvalid > CXXDestructor, + "invalid should have highest index"); + static_assert((unsigned)DefaultedComparisonKind::None == 0, + "none should be equal to zero"); + return SpecialMember + Comparison; + } + }; - void PushExpressionEvaluationContext( - ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, - ExpressionEvaluationContextRecord::ExpressionKind Type = - ExpressionEvaluationContextRecord::EK_Other); - enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; - void PushExpressionEvaluationContext( - ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, - ExpressionEvaluationContextRecord::ExpressionKind Type = - ExpressionEvaluationContextRecord::EK_Other); - void PopExpressionEvaluationContext(); + DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD); - void DiscardCleanupsInEvaluationContext(); - - ExprResult TransformToPotentiallyEvaluated(Expr *E); - TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo); - ExprResult HandleExprEvaluationContextForTypeof(Expr *E); + /// Handle a C++11 empty-declaration and attribute-declaration. + Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList, + SourceLocation SemiLoc); - ExprResult CheckUnevaluatedOperand(Expr *E); - void CheckUnusedVolatileAssignment(Expr *E); + enum class CheckConstexprKind { + /// Diagnose issues that are non-constant or that are extensions. + Diagnose, + /// Identify whether this function satisfies the formal rules for constexpr + /// functions in the current lanugage mode (with no extensions). + CheckValid + }; - ExprResult ActOnConstantExpression(ExprResult Res); + bool CheckConstexprFunctionDefinition(const FunctionDecl *FD, + CheckConstexprKind Kind); - // Functions for marking a declaration referenced. These functions also - // contain the relevant logic for marking if a reference to a function or - // variable is an odr-use (in the C++11 sense). There are separate variants - // for expressions referring to a decl; these exist because odr-use marking - // needs to be delayed for some constant variables when we build one of the - // named expressions. - // - // MightBeOdrUse indicates whether the use could possibly be an odr-use, and - // should usually be true. This only needs to be set to false if the lack of - // odr-use cannot be determined from the current context (for instance, - // because the name denotes a virtual function and was written without an - // explicit nested-name-specifier). - void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse); - void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, - bool MightBeOdrUse = true); - void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); - void MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base = nullptr); - void MarkMemberReferenced(MemberExpr *E); - void MarkFunctionParmPackReferenced(FunctionParmPackExpr *E); - void MarkCaptureUsedInEnclosingContext(ValueDecl *Capture, SourceLocation Loc, - unsigned CapturingScopeIndex); + void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD); + void + FindHiddenVirtualMethods(CXXMethodDecl *MD, + SmallVectorImpl &OverloadedMethods); + void + NoteHiddenVirtualMethods(CXXMethodDecl *MD, + SmallVectorImpl &OverloadedMethods); + void ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, + Expr *defarg); + void ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc, + SourceLocation ArgLoc); + void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc, + Expr *DefaultArg); + ExprResult ConvertParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, + SourceLocation EqualLoc); + void SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, + SourceLocation EqualLoc); - ExprResult CheckLValueToRValueConversionOperand(Expr *E); - void CleanupVarDeclMarking(); + void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc); + void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); + void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc); - enum TryCaptureKind { - TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef - }; + void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind); + void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D); + ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr); + ExprResult ActOnRequiresClause(ExprResult ConstraintExpr); - /// Try to capture the given variable. - /// - /// \param Var The variable to capture. - /// - /// \param Loc The location at which the capture occurs. - /// - /// \param Kind The kind of capture, which may be implicit (for either a - /// block or a lambda), or explicit by-value or by-reference (for a lambda). - /// - /// \param EllipsisLoc The location of the ellipsis, if one is provided in - /// an explicit lambda capture. - /// - /// \param BuildAndDiagnose Whether we are actually supposed to add the - /// captures or diagnose errors. If false, this routine merely check whether - /// the capture can occur without performing the capture itself or complaining - /// if the variable cannot be captured. - /// - /// \param CaptureType Will be set to the type of the field used to capture - /// this variable in the innermost block or lambda. Only valid when the - /// variable can be captured. - /// - /// \param DeclRefType Will be set to the type of a reference to the capture - /// from within the current scope. Only valid when the variable can be - /// captured. - /// - /// \param FunctionScopeIndexToStopAt If non-null, it points to the index - /// of the FunctionScopeInfo stack beyond which we do not attempt to capture. - /// This is useful when enclosing lambdas must speculatively capture - /// variables that may or may not be used in certain specializations of - /// a nested generic lambda. - /// - /// \returns true if an error occurred (i.e., the variable cannot be - /// captured) and false if the capture succeeded. - bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, - TryCaptureKind Kind, SourceLocation EllipsisLoc, - bool BuildAndDiagnose, QualType &CaptureType, - QualType &DeclRefType, - const unsigned *const FunctionScopeIndexToStopAt); + NamedDecl * + ActOnDecompositionDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists); + void DiagPlaceholderVariableDefinition(SourceLocation Loc); + bool DiagRedefinedPlaceholderFieldDecl(SourceLocation Loc, + RecordDecl *ClassDecl, + const IdentifierInfo *Name); - /// Try to capture the given variable. - bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, - TryCaptureKind Kind = TryCapture_Implicit, - SourceLocation EllipsisLoc = SourceLocation()); + void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD); - /// Checks if the variable must be captured. - bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc); + /// Stack containing information needed when in C++2a an 'auto' is encountered + /// in a function declaration parameter type specifier in order to invent a + /// corresponding template parameter in the enclosing abbreviated function + /// template. This information is also present in LambdaScopeInfo, stored in + /// the FunctionScopes stack. + SmallVector InventedParameterInfos; - /// Given a variable, determine the type that a reference to that - /// variable will have in the given scope. - QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc); + /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. + std::unique_ptr FieldCollector; - /// Mark all of the declarations referenced within a particular AST node as - /// referenced. Used when template instantiation instantiates a non-dependent - /// type -- entities referenced by the type are now referenced. - void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); - void MarkDeclarationsReferencedInExpr( - Expr *E, bool SkipLocalVariables = false, - ArrayRef StopAt = std::nullopt); + typedef llvm::SmallSetVector NamedDeclSetType; + /// Set containing all declared private fields that are not used. + NamedDeclSetType UnusedPrivateFields; - /// Try to recover by turning the given expression into a - /// call. Returns true if recovery was attempted or an error was - /// emitted; this may also leave the ExprResult invalid. - bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, - bool ForceComplain = false, - bool (*IsPlausibleResult)(QualType) = nullptr); + typedef llvm::SmallPtrSet RecordDeclSetTy; - /// Figure out if an expression could be turned into a call. - bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, - UnresolvedSetImpl &NonTemplateOverloads); + /// PureVirtualClassDiagSet - a set of class declarations which we have + /// emitted a list of pure virtual functions. Used to prevent emitting the + /// same list more than once. + std::unique_ptr PureVirtualClassDiagSet; - /// Try to convert an expression \p E to type \p Ty. Returns the result of the - /// conversion. - ExprResult tryConvertExprToType(Expr *E, QualType Ty); + typedef LazyVector + DelegatingCtorDeclsType; - /// Conditionally issue a diagnostic based on the statements's reachability - /// analysis. - /// - /// \param Stmts If Stmts is non-empty, delay reporting the diagnostic until - /// the function body is parsed, and then do a basic reachability analysis to - /// determine if the statement is reachable. If it is unreachable, the - /// diagnostic will not be emitted. - bool DiagIfReachable(SourceLocation Loc, ArrayRef Stmts, - const PartialDiagnostic &PD); + /// All the delegating constructors seen so far in the file, used for + /// cycle detection at the end of the TU. + DelegatingCtorDeclsType DelegatingCtorDecls; - /// Conditionally issue a diagnostic based on the current - /// evaluation context. - /// - /// \param Statement If Statement is non-null, delay reporting the - /// diagnostic until the function body is parsed, and then do a basic - /// reachability analysis to determine if the statement is reachable. - /// If it is unreachable, the diagnostic will not be emitted. - bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, - const PartialDiagnostic &PD); - /// Similar, but diagnostic is only produced if all the specified statements - /// are reachable. - bool DiagRuntimeBehavior(SourceLocation Loc, ArrayRef Stmts, - const PartialDiagnostic &PD); + /// The C++ "std" namespace, where the standard library resides. + LazyDeclPtr StdNamespace; - // Primary Expressions. - SourceRange getExprRange(Expr *E) const; + /// The C++ "std::initializer_list" template, which is defined in + /// \. + ClassTemplateDecl *StdInitializerList; - ExprResult ActOnIdExpression( - Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = nullptr, - bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr); + // Contains the locations of the beginning of unparsed default + // argument locations. + llvm::DenseMap UnparsedDefaultArgLocs; - void DecomposeUnqualifiedId(const UnqualifiedId &Id, - TemplateArgumentListInfo &Buffer, - DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *&TemplateArgs); + /// UndefinedInternals - all the used, undefined objects which require a + /// definition in this translation unit. + llvm::MapVector UndefinedButUsed; - bool DiagnoseDependentMemberLookup(const LookupResult &R); + typedef llvm::PointerIntPair + SpecialMemberDecl; - bool - DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - CorrectionCandidateCallback &CCC, - TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, - ArrayRef Args = std::nullopt, - DeclContext *LookupCtx = nullptr, - TypoExpr **Out = nullptr); + /// The C++ special members which we are currently in the process of + /// declaring. If this process recursively triggers the declaration of the + /// same special member, we should act as if it is not yet declared. + llvm::SmallPtrSet SpecialMembersBeingDeclared; - DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, - IdentifierInfo *II); - ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV); + void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD); - ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, - IdentifierInfo *II, - bool AllowBuiltinCreation=false); + void ActOnDefaultCtorInitializers(Decl *CDtorDecl); - ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - bool isAddressOfOperand, - const TemplateArgumentListInfo *TemplateArgs); + typedef ProcessingContextState ParsingClassState; + ParsingClassState PushParsingClass() { + ParsingClassDepth++; + return DelayedDiagnostics.pushUndelayed(); + } + void PopParsingClass(ParsingClassState state) { + ParsingClassDepth--; + DelayedDiagnostics.popUndelayed(state); + } - /// If \p D cannot be odr-used in the current expression evaluation context, - /// return a reason explaining why. Otherwise, return NOUR_None. - NonOdrUseReason getNonOdrUseReasonInCurrentContext(ValueDecl *D); +private: + void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem, + QualType ResultTy, + ArrayRef Args); - DeclRefExpr *BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, - SourceLocation Loc, - const CXXScopeSpec *SS = nullptr); - DeclRefExpr * - BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, - const DeclarationNameInfo &NameInfo, - const CXXScopeSpec *SS = nullptr, - NamedDecl *FoundD = nullptr, - SourceLocation TemplateKWLoc = SourceLocation(), - const TemplateArgumentListInfo *TemplateArgs = nullptr); - DeclRefExpr * - BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, - const DeclarationNameInfo &NameInfo, - NestedNameSpecifierLoc NNS, - NamedDecl *FoundD = nullptr, - SourceLocation TemplateKWLoc = SourceLocation(), - const TemplateArgumentListInfo *TemplateArgs = nullptr); + // A cache representing if we've fully checked the various comparison category + // types stored in ASTContext. The bit-index corresponds to the integer value + // of a ComparisonCategoryType enumerator. + llvm::SmallBitVector FullyCheckedComparisonCategories; - ExprResult - BuildAnonymousStructUnionMemberReference( - const CXXScopeSpec &SS, - SourceLocation nameLoc, - IndirectFieldDecl *indirectField, - DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none), - Expr *baseObjectExpr = nullptr, - SourceLocation opLoc = SourceLocation()); + ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, + CXXScopeSpec &SS, + ParsedType TemplateTypeTy, + IdentifierInfo *MemberOrBase); - ExprResult BuildPossibleImplicitMemberExpr( - const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, const Scope *S, - UnresolvedLookupExpr *AsULE = nullptr); - ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, - bool IsDefiniteInstance, - const Scope *S); - bool UseArgumentDependentLookup(const CXXScopeSpec &SS, - const LookupResult &R, - bool HasTrailingLParen); + /// Check if there is a field shadowing. + void CheckShadowInheritedFields(const SourceLocation &Loc, + DeclarationName FieldName, + const CXXRecordDecl *RD, + bool DeclIsField = true); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand, const Scope *S, - TypeSourceInfo **RecoveryTSI = nullptr); + ///@} - ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); + // + // + // ------------------------------------------------------------------------- + // + // - ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, - LookupResult &R, - bool NeedsADL, - bool AcceptInvalidDecl = false); - ExprResult BuildDeclarationNameExpr( - const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, - NamedDecl *FoundD = nullptr, - const TemplateArgumentListInfo *TemplateArgs = nullptr, - bool AcceptInvalidDecl = false); + /// \name C++ Exception Specifications + /// Implementations are in SemaExceptionSpec.cpp + ///@{ - ExprResult BuildLiteralOperatorCall(LookupResult &R, - DeclarationNameInfo &SuffixInfo, - ArrayRef Args, - SourceLocation LitEndLoc, - TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); +public: + /// All the overriding functions seen during a class definition + /// that had their exception spec checks delayed, plus the overridden + /// function. + SmallVector, 2> + DelayedOverridingExceptionSpecChecks; - // ExpandFunctionLocalPredefinedMacros - Returns a new vector of Tokens, - // where Tokens representing function local predefined macros (such as - // __FUNCTION__) are replaced (expanded) with string-literal Tokens. - std::vector ExpandFunctionLocalPredefinedMacros(ArrayRef Toks); + /// All the function redeclarations seen during a class definition that had + /// their exception spec checks delayed, plus the prior declaration they + /// should be checked against. Except during error recovery, the new decl + /// should always be a friend declaration, as that's the only valid way to + /// redeclare a special member before its class is complete. + SmallVector, 2> + DelayedEquivalentExceptionSpecChecks; - ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK); - ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); - ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val); + /// Determine if we're in a case where we need to (incorrectly) eagerly + /// parse an exception specification to work around a libstdc++ bug. + bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D); - ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc, - SourceLocation LParen, - SourceLocation RParen, - TypeSourceInfo *TSI); - ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc, - SourceLocation LParen, - SourceLocation RParen, - ParsedType ParsedTy); + /// Check the given noexcept-specifier, convert its expression, and compute + /// the appropriate ExceptionSpecificationType. + ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr, + ExceptionSpecificationType &EST); - bool CheckLoopHintExpr(Expr *E, SourceLocation Loc); + CanThrowResult canThrow(const Stmt *E); + /// Determine whether the callee of a particular function call can throw. + /// E, D and Loc are all optional. + static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, + SourceLocation Loc = SourceLocation()); + const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, + const FunctionProtoType *FPT); + void UpdateExceptionSpec(FunctionDecl *FD, + const FunctionProtoType::ExceptionSpecInfo &ESI); + bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range); + bool CheckDistantExceptionSpec(QualType T); + bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); + bool CheckEquivalentExceptionSpec(const FunctionProtoType *Old, + SourceLocation OldLoc, + const FunctionProtoType *New, + SourceLocation NewLoc); + bool CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, + const PartialDiagnostic &NoteID, + const FunctionProtoType *Old, + SourceLocation OldLoc, + const FunctionProtoType *New, + SourceLocation NewLoc); + bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); + bool CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, + const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, + const FunctionProtoType *Superset, bool SkipSupersetFirstParameter, + SourceLocation SuperLoc, const FunctionProtoType *Subset, + bool SkipSubsetFirstParameter, SourceLocation SubLoc); + bool CheckParamExceptionSpec( + const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, + const FunctionProtoType *Target, bool SkipTargetFirstParameter, + SourceLocation TargetLoc, const FunctionProtoType *Source, + bool SkipSourceFirstParameter, SourceLocation SourceLoc); - ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr); - ExprResult ActOnCharacterConstant(const Token &Tok, - Scope *UDLScope = nullptr); - ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E); - ExprResult ActOnParenListExpr(SourceLocation L, - SourceLocation R, - MultiExprArg Val); + bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); - /// ActOnStringLiteral - The specified tokens were lexed as pasted string - /// fragments (e.g. "foo" "bar" L"baz"). - ExprResult ActOnStringLiteral(ArrayRef StringToks, - Scope *UDLScope = nullptr); + /// CheckOverridingFunctionExceptionSpec - Checks whether the exception + /// spec is a subset of base spec. + bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, + const CXXMethodDecl *Old); - ExprResult ActOnUnevaluatedStringLiteral(ArrayRef StringToks); + ///@} - /// ControllingExprOrType is either an opaque pointer coming out of a - /// ParsedType or an Expr *. FIXME: it'd be better to split this interface - /// into two so we don't take a void *, but that's awkward because one of - /// the operands is either a ParsedType or an Expr *, which doesn't lend - /// itself to generic code very well. - ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc, - SourceLocation DefaultLoc, - SourceLocation RParenLoc, - bool PredicateIsExpr, - void *ControllingExprOrType, - ArrayRef ArgTypes, - ArrayRef ArgExprs); - /// ControllingExprOrType is either a TypeSourceInfo * or an Expr *. FIXME: - /// it'd be better to split this interface into two so we don't take a - /// void *, but see the FIXME on ActOnGenericSelectionExpr as to why that - /// isn't a trivial change. - ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc, - SourceLocation DefaultLoc, - SourceLocation RParenLoc, - bool PredicateIsExpr, - void *ControllingExprOrType, - ArrayRef Types, - ArrayRef Exprs); + // + // + // ------------------------------------------------------------------------- + // + // - // Binary/Unary Operators. 'Tok' is the token for the operator. - ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, - Expr *InputExpr, bool IsAfterAmp = false); - ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, - Expr *Input, bool IsAfterAmp = false); - ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, - Expr *Input, bool IsAfterAmp = false); + /// \name Expressions + /// Implementations are in SemaExpr.cpp + ///@{ - bool isQualifiedMemberAccess(Expr *E); - bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc, - const Expr *Op, - const CXXMethodDecl *MD); +public: + /// Describes how the expressions currently being parsed are + /// evaluated at run-time, if at all. + enum class ExpressionEvaluationContext { + /// The current expression and its subexpressions occur within an + /// unevaluated operand (C++11 [expr]p7), such as the subexpression of + /// \c sizeof, where the type of the expression may be significant but + /// no code will be generated to evaluate the value of the expression at + /// run time. + Unevaluated, - QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc); + /// The current expression occurs within a braced-init-list within + /// an unevaluated operand. This is mostly like a regular unevaluated + /// context, except that we still instantiate constexpr functions that are + /// referenced here so that we can perform narrowing checks correctly. + UnevaluatedList, - bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N); + /// The current expression occurs within a discarded statement. + /// This behaves largely similarly to an unevaluated operand in preventing + /// definitions from being required, but not in other ways. + DiscardedStatement, - bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty, - SourceLocation OpLoc, SourceRange R); - bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo, - SourceLocation OpLoc, SourceRange R); + /// The current expression occurs within an unevaluated + /// operand that unconditionally permits abstract references to + /// fields, such as a SIZE operator in MS-style inline assembly. + UnevaluatedAbstract, - ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, - SourceLocation OpLoc, - UnaryExprOrTypeTrait ExprKind, - SourceRange R); - ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, - UnaryExprOrTypeTrait ExprKind); - ExprResult - ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, - UnaryExprOrTypeTrait ExprKind, - bool IsType, void *TyOrEx, - SourceRange ArgRange); + /// The current context is "potentially evaluated" in C++11 terms, + /// but the expression is evaluated at compile-time (like the values of + /// cases in a switch statement). + ConstantEvaluated, - ExprResult CheckPlaceholderExpr(Expr *E); - bool CheckVecStepExpr(Expr *E); + /// In addition of being constant evaluated, the current expression + /// occurs in an immediate function context - either a consteval function + /// or a consteval if statement. + ImmediateFunctionContext, - bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind); - bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc, - SourceRange ExprRange, - UnaryExprOrTypeTrait ExprKind, - StringRef KWName); - ExprResult ActOnSizeofParameterPackExpr(Scope *S, - SourceLocation OpLoc, - IdentifierInfo &Name, - SourceLocation NameLoc, - SourceLocation RParenLoc); + /// The current expression is potentially evaluated at run time, + /// which means that code may be generated to evaluate the value of the + /// expression at run time. + PotentiallyEvaluated, - ExprResult ActOnPackIndexingExpr(Scope *S, Expr *PackExpression, - SourceLocation EllipsisLoc, - SourceLocation LSquareLoc, Expr *IndexExpr, - SourceLocation RSquareLoc); + /// The current expression is potentially evaluated, but any + /// declarations referenced inside that expression are only used if + /// in fact the current expression is used. + /// + /// This value is used when parsing default function arguments, for which + /// we would like to provide diagnostics (e.g., passing non-POD arguments + /// through varargs) but do not want to mark declarations as "referenced" + /// until the default argument is used. + PotentiallyEvaluatedIfUsed + }; - ExprResult BuildPackIndexingExpr(Expr *PackExpression, - SourceLocation EllipsisLoc, Expr *IndexExpr, - SourceLocation RSquareLoc, - ArrayRef ExpandedExprs = {}, - bool EmptyPack = false); + /// Store a set of either DeclRefExprs or MemberExprs that contain a reference + /// to a variable (constant) that may or may not be odr-used in this Expr, and + /// we won't know until all lvalue-to-rvalue and discarded value conversions + /// have been applied to all subexpressions of the enclosing full expression. + /// This is cleared at the end of each full expression. + using MaybeODRUseExprSet = llvm::SmallSetVector; + MaybeODRUseExprSet MaybeODRUseExprs; - ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, - tok::TokenKind Kind, Expr *Input); + using ImmediateInvocationCandidate = llvm::PointerIntPair; - ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, - MultiExprArg ArgExprs, - SourceLocation RLoc); - ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, - Expr *Idx, SourceLocation RLoc); + /// Data structure used to record current or nested + /// expression evaluation contexts. + struct ExpressionEvaluationContextRecord { + /// The expression evaluation context. + ExpressionEvaluationContext Context; - ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, - Expr *ColumnIdx, - SourceLocation RBLoc); + /// Whether the enclosing context needed a cleanup. + CleanupInfo ParentCleanup; - ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, - Expr *LowerBound, - SourceLocation ColonLocFirst, - SourceLocation ColonLocSecond, - Expr *Length, Expr *Stride, - SourceLocation RBLoc); - ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, - SourceLocation RParenLoc, - ArrayRef Dims, - ArrayRef Brackets); + /// The number of active cleanup objects when we entered + /// this expression evaluation context. + unsigned NumCleanupObjects; - /// Data structure for iterator expression. - struct OMPIteratorData { - IdentifierInfo *DeclIdent = nullptr; - SourceLocation DeclIdentLoc; - ParsedType Type; - OMPIteratorExpr::IteratorRange Range; - SourceLocation AssignLoc; - SourceLocation ColonLoc; - SourceLocation SecColonLoc; - }; + /// The number of typos encountered during this expression evaluation + /// context (i.e. the number of TypoExprs created). + unsigned NumTypos; - ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, - SourceLocation LLoc, SourceLocation RLoc, - ArrayRef Data); + MaybeODRUseExprSet SavedMaybeODRUseExprs; - // This struct is for use by ActOnMemberAccess to allow - // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after - // changing the access operator from a '.' to a '->' (to see if that is the - // change needed to fix an error about an unknown member, e.g. when the class - // defines a custom operator->). - struct ActOnMemberAccessExtraArgs { - Scope *S; - UnqualifiedId &Id; - Decl *ObjCImpDecl; - }; + /// The lambdas that are present within this context, if it + /// is indeed an unevaluated context. + SmallVector Lambdas; - ExprResult BuildMemberReferenceExpr( - Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, - CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs, - const Scope *S, - ActOnMemberAccessExtraArgs *ExtraArgs = nullptr); + /// The declaration that provides context for lambda expressions + /// and block literals if the normal declaration context does not + /// suffice, e.g., in a default function argument. + Decl *ManglingContextDecl; - ExprResult - BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, - bool IsArrow, const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierInScope, LookupResult &R, - const TemplateArgumentListInfo *TemplateArgs, - const Scope *S, - bool SuppressQualifierCheck = false, - ActOnMemberAccessExtraArgs *ExtraArgs = nullptr); + /// If we are processing a decltype type, a set of call expressions + /// for which we have deferred checking the completeness of the return type. + SmallVector DelayedDecltypeCalls; - ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, - SourceLocation OpLoc, - const CXXScopeSpec &SS, FieldDecl *Field, - DeclAccessPair FoundDecl, - const DeclarationNameInfo &MemberNameInfo); + /// If we are processing a decltype type, a set of temporary binding + /// expressions for which we have deferred checking the destructor. + SmallVector DelayedDecltypeBinds; - ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow); + llvm::SmallPtrSet PossibleDerefs; - bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, - const CXXScopeSpec &SS, - const LookupResult &R); + /// Expressions appearing as the LHS of a volatile assignment in this + /// context. We produce a warning for these when popping the context if + /// they are not discarded-value expressions nor unevaluated operands. + SmallVector VolatileAssignmentLHSs; - ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType, - bool IsArrow, SourceLocation OpLoc, - const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierInScope, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); + /// Set of candidates for starting an immediate invocation. + llvm::SmallVector + ImmediateInvocationCandidates; - ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - UnqualifiedId &Member, - Decl *ObjCImpDecl); + /// Set of DeclRefExprs referencing a consteval function when used in a + /// context not already known to be immediately invoked. + llvm::SmallPtrSet ReferenceToConsteval; - MemberExpr * - BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, - const CXXScopeSpec *SS, SourceLocation TemplateKWLoc, - ValueDecl *Member, DeclAccessPair FoundDecl, - bool HadMultipleCandidates, - const DeclarationNameInfo &MemberNameInfo, QualType Ty, - ExprValueKind VK, ExprObjectKind OK, - const TemplateArgumentListInfo *TemplateArgs = nullptr); - MemberExpr * - BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, - NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, - ValueDecl *Member, DeclAccessPair FoundDecl, - bool HadMultipleCandidates, - const DeclarationNameInfo &MemberNameInfo, QualType Ty, - ExprValueKind VK, ExprObjectKind OK, - const TemplateArgumentListInfo *TemplateArgs = nullptr); + /// P2718R0 - Lifetime extension in range-based for loops. + /// MaterializeTemporaryExprs in for-range-init expressions which need to + /// extend lifetime. Add MaterializeTemporaryExpr* if the value of + /// InLifetimeExtendingContext is true. + SmallVector ForRangeLifetimeExtendTemps; - void ActOnDefaultCtorInitializers(Decl *CDtorDecl); - bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, - FunctionDecl *FDecl, - const FunctionProtoType *Proto, - ArrayRef Args, - SourceLocation RParenLoc, - bool ExecConfig = false); - void CheckStaticArrayArgument(SourceLocation CallLoc, - ParmVarDecl *Param, - const Expr *ArgExpr); + /// \brief Describes whether we are in an expression constext which we have + /// to handle differently. + enum ExpressionKind { + EK_Decltype, + EK_TemplateArgument, + EK_Other + } ExprContext; - /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. - /// This provides the location of the left/right parens and a list of comma - /// locations. - ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, - MultiExprArg ArgExprs, SourceLocation RParenLoc, - Expr *ExecConfig = nullptr); - ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, - MultiExprArg ArgExprs, SourceLocation RParenLoc, - Expr *ExecConfig = nullptr, - bool IsExecConfig = false, - bool AllowRecovery = false); - Expr *BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, - MultiExprArg CallArgs); - enum class AtomicArgumentOrder { API, AST }; - ExprResult - BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, - SourceLocation RParenLoc, MultiExprArg Args, - AtomicExpr::AtomicOp Op, - AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API); - ExprResult - BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, - ArrayRef Arg, SourceLocation RParenLoc, - Expr *Config = nullptr, bool IsExecConfig = false, - ADLCallKind UsesADL = ADLCallKind::NotADL); + // A context can be nested in both a discarded statement context and + // an immediate function context, so they need to be tracked independently. + bool InDiscardedStatement; + bool InImmediateFunctionContext; + bool InImmediateEscalatingFunctionContext; - ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, - MultiExprArg ExecConfig, - SourceLocation GGGLoc); + bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false; - ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, - Declarator &D, ParsedType &Ty, - SourceLocation RParenLoc, Expr *CastExpr); - ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, - TypeSourceInfo *Ty, - SourceLocation RParenLoc, - Expr *Op); - CastKind PrepareScalarCast(ExprResult &src, QualType destType); + // We are in a constant context, but we also allow + // non constant expressions, for example for array bounds (which may be + // VLAs). + bool InConditionallyConstantEvaluateContext = false; - /// Build an altivec or OpenCL literal. - ExprResult BuildVectorLiteral(SourceLocation LParenLoc, - SourceLocation RParenLoc, Expr *E, - TypeSourceInfo *TInfo); + /// Whether we are currently in a context in which all temporaries must be + /// lifetime-extended, even if they're not bound to a reference (for + /// example, in a for-range initializer). + bool InLifetimeExtendingContext = false; - ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME); + /// Whether we are currently in a context in which all temporaries must be + /// materialized. + /// + /// [class.temporary]/p2: + /// The materialization of a temporary object is generally delayed as long + /// as possible in order to avoid creating unnecessary temporary objects. + /// + /// Temporary objects are materialized: + /// (2.1) when binding a reference to a prvalue ([dcl.init.ref], + /// [expr.type.conv], [expr.dynamic.cast], [expr.static.cast], + /// [expr.const.cast], [expr.cast]), + /// + /// (2.2) when performing member access on a class prvalue ([expr.ref], + /// [expr.mptr.oper]), + /// + /// (2.3) when performing an array-to-pointer conversion or subscripting + /// on an array prvalue ([conv.array], [expr.sub]), + /// + /// (2.4) when initializing an object of type + /// std​::​initializer_list from a braced-init-list + /// ([dcl.init.list]), + /// + /// (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof]) + /// + /// (2.6) when a prvalue that has type other than cv void appears as a + /// discarded-value expression ([expr.context]). + bool InMaterializeTemporaryObjectContext = false; - ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, - ParsedType Ty, - SourceLocation RParenLoc, - Expr *InitExpr); + // When evaluating immediate functions in the initializer of a default + // argument or default member initializer, this is the declaration whose + // default initializer is being evaluated and the location of the call + // or constructor definition. + struct InitializationContext { + InitializationContext(SourceLocation Loc, ValueDecl *Decl, + DeclContext *Context) + : Loc(Loc), Decl(Decl), Context(Context) { + assert(Decl && Context && "invalid initialization context"); + } - ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc, - TypeSourceInfo *TInfo, - SourceLocation RParenLoc, - Expr *LiteralExpr); + SourceLocation Loc; + ValueDecl *Decl = nullptr; + DeclContext *Context = nullptr; + }; + std::optional DelayedDefaultInitializationContext; - ExprResult ActOnInitList(SourceLocation LBraceLoc, - MultiExprArg InitArgList, - SourceLocation RBraceLoc); + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, + unsigned NumCleanupObjects, + CleanupInfo ParentCleanup, + Decl *ManglingContextDecl, + ExpressionKind ExprContext) + : Context(Context), ParentCleanup(ParentCleanup), + NumCleanupObjects(NumCleanupObjects), NumTypos(0), + ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext), + InDiscardedStatement(false), InImmediateFunctionContext(false), + InImmediateEscalatingFunctionContext(false) {} - ExprResult BuildInitList(SourceLocation LBraceLoc, - MultiExprArg InitArgList, - SourceLocation RBraceLoc); + bool isUnevaluated() const { + return Context == ExpressionEvaluationContext::Unevaluated || + Context == ExpressionEvaluationContext::UnevaluatedAbstract || + Context == ExpressionEvaluationContext::UnevaluatedList; + } - ExprResult ActOnDesignatedInitializer(Designation &Desig, - SourceLocation EqualOrColonLoc, - bool GNUSyntax, - ExprResult Init); + bool isConstantEvaluated() const { + return Context == ExpressionEvaluationContext::ConstantEvaluated || + Context == ExpressionEvaluationContext::ImmediateFunctionContext; + } -private: - static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind); + bool isImmediateFunctionContext() const { + return Context == ExpressionEvaluationContext::ImmediateFunctionContext || + (Context == ExpressionEvaluationContext::DiscardedStatement && + InImmediateFunctionContext) || + // C++23 [expr.const]p14: + // An expression or conversion is in an immediate function + // context if it is potentially evaluated and either: + // * its innermost enclosing non-block scope is a function + // parameter scope of an immediate function, or + // * its enclosing statement is enclosed by the compound- + // statement of a consteval if statement. + (Context == ExpressionEvaluationContext::PotentiallyEvaluated && + InImmediateFunctionContext); + } -public: - ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, - tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr); - ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, - BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); - ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, - Expr *LHSExpr, Expr *RHSExpr); - void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, - UnresolvedSetImpl &Functions); + bool isDiscardedStatementContext() const { + return Context == ExpressionEvaluationContext::DiscardedStatement || + (Context == + ExpressionEvaluationContext::ImmediateFunctionContext && + InDiscardedStatement); + } + }; - void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc); + const ExpressionEvaluationContextRecord ¤tEvaluationContext() const { + assert(!ExprEvalContexts.empty() && + "Must be in an expression evaluation context"); + return ExprEvalContexts.back(); + }; - /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null - /// in the case of a the GNU conditional expr extension. - ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, - SourceLocation ColonLoc, - Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr); + /// Increment when we find a reference; decrement when we find an ignored + /// assignment. Ultimately the value is 0 if every reference is an ignored + /// assignment. + llvm::DenseMap RefsMinusAssignments; - /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". - ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, - LabelDecl *TheDecl); + /// Used to control the generation of ExprWithCleanups. + CleanupInfo Cleanup; - void ActOnStartStmtExpr(); - ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt, - SourceLocation RPLoc); - ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, - SourceLocation RPLoc, unsigned TemplateDepth); - // Handle the final expression in a statement expression. - ExprResult ActOnStmtExprResult(ExprResult E); - void ActOnStmtExprError(); + /// ExprCleanupObjects - This is the stack of objects requiring + /// cleanup that are created by the current full expression. + SmallVector ExprCleanupObjects; - // __builtin_offsetof(type, identifier(.identifier|[expr])*) - struct OffsetOfComponent { - SourceLocation LocStart, LocEnd; - bool isBrackets; // true if [expr], false if .ident - union { - IdentifierInfo *IdentInfo; - Expr *E; - } U; + // AssignmentAction - This is used by all the assignment diagnostic functions + // to represent what is actually causing the operation + enum AssignmentAction { + AA_Assigning, + AA_Passing, + AA_Returning, + AA_Converting, + AA_Initializing, + AA_Sending, + AA_Casting, + AA_Passing_CFAudited }; - /// __builtin_offsetof(type, a.b[123][456].c) - ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, - TypeSourceInfo *TInfo, - ArrayRef Components, - SourceLocation RParenLoc); - ExprResult ActOnBuiltinOffsetOf(Scope *S, - SourceLocation BuiltinLoc, - SourceLocation TypeLoc, - ParsedType ParsedArgTy, - ArrayRef Components, - SourceLocation RParenLoc); + bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid); + // A version of DiagnoseUseOfDecl that should be used if overload resolution + // has been used to find this declaration, which means we don't have to bother + // checking the trailing requires clause. + bool DiagnoseUseOfOverloadedDecl(NamedDecl *D, SourceLocation Loc) { + return DiagnoseUseOfDecl( + D, Loc, /*UnknownObjCClass=*/nullptr, /*ObjCPropertyAccess=*/false, + /*AvoidPartialAvailabilityChecks=*/false, /*ClassReceiver=*/nullptr, + /*SkipTrailingRequiresClause=*/true); + } - // __builtin_choose_expr(constExpr, expr1, expr2) - ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, - Expr *CondExpr, Expr *LHSExpr, - Expr *RHSExpr, SourceLocation RPLoc); + bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, + const ObjCInterfaceDecl *UnknownObjCClass = nullptr, + bool ObjCPropertyAccess = false, + bool AvoidPartialAvailabilityChecks = false, + ObjCInterfaceDecl *ClassReciever = nullptr, + bool SkipTrailingRequiresClause = false); + void NoteDeletedFunction(FunctionDecl *FD); - // __builtin_va_arg(expr, type) - ExprResult ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty, - SourceLocation RPLoc); - ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E, - TypeSourceInfo *TInfo, SourceLocation RPLoc); + void DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc, + ArrayRef Args); - // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(), - // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location() - ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind, - SourceLocation BuiltinLoc, - SourceLocation RPLoc); + void PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, + ExpressionEvaluationContextRecord::ExpressionKind Type = + ExpressionEvaluationContextRecord::EK_Other); + enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; + void PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, + ExpressionEvaluationContextRecord::ExpressionKind Type = + ExpressionEvaluationContextRecord::EK_Other); + void PopExpressionEvaluationContext(); - // Build a potentially resolved SourceLocExpr. - ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy, - SourceLocation BuiltinLoc, SourceLocation RPLoc, - DeclContext *ParentContext); + void DiscardCleanupsInEvaluationContext(); - // __null - ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc); + ExprResult TransformToPotentiallyEvaluated(Expr *E); + TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo); + ExprResult HandleExprEvaluationContextForTypeof(Expr *E); - bool CheckCaseExpression(Expr *E); + void CheckUnusedVolatileAssignment(Expr *E); - /// Describes the result of an "if-exists" condition check. - enum IfExistsResult { - /// The symbol exists. - IER_Exists, + ExprResult ActOnConstantExpression(ExprResult Res); - /// The symbol does not exist. - IER_DoesNotExist, + // Functions for marking a declaration referenced. These functions also + // contain the relevant logic for marking if a reference to a function or + // variable is an odr-use (in the C++11 sense). There are separate variants + // for expressions referring to a decl; these exist because odr-use marking + // needs to be delayed for some constant variables when we build one of the + // named expressions. + // + // MightBeOdrUse indicates whether the use could possibly be an odr-use, and + // should usually be true. This only needs to be set to false if the lack of + // odr-use cannot be determined from the current context (for instance, + // because the name denotes a virtual function and was written without an + // explicit nested-name-specifier). + void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse); + void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, + bool MightBeOdrUse = true); + void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); + void MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base = nullptr); + void MarkMemberReferenced(MemberExpr *E); + void MarkFunctionParmPackReferenced(FunctionParmPackExpr *E); + void MarkCaptureUsedInEnclosingContext(ValueDecl *Capture, SourceLocation Loc, + unsigned CapturingScopeIndex); - /// The name is a dependent name, so the results will differ - /// from one instantiation to the next. - IER_Dependent, + ExprResult CheckLValueToRValueConversionOperand(Expr *E); + void CleanupVarDeclMarking(); - /// An error occurred. - IER_Error + enum TryCaptureKind { + TryCapture_Implicit, + TryCapture_ExplicitByVal, + TryCapture_ExplicitByRef }; - IfExistsResult - CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS, - const DeclarationNameInfo &TargetNameInfo); + /// Try to capture the given variable. + /// + /// \param Var The variable to capture. + /// + /// \param Loc The location at which the capture occurs. + /// + /// \param Kind The kind of capture, which may be implicit (for either a + /// block or a lambda), or explicit by-value or by-reference (for a lambda). + /// + /// \param EllipsisLoc The location of the ellipsis, if one is provided in + /// an explicit lambda capture. + /// + /// \param BuildAndDiagnose Whether we are actually supposed to add the + /// captures or diagnose errors. If false, this routine merely check whether + /// the capture can occur without performing the capture itself or complaining + /// if the variable cannot be captured. + /// + /// \param CaptureType Will be set to the type of the field used to capture + /// this variable in the innermost block or lambda. Only valid when the + /// variable can be captured. + /// + /// \param DeclRefType Will be set to the type of a reference to the capture + /// from within the current scope. Only valid when the variable can be + /// captured. + /// + /// \param FunctionScopeIndexToStopAt If non-null, it points to the index + /// of the FunctionScopeInfo stack beyond which we do not attempt to capture. + /// This is useful when enclosing lambdas must speculatively capture + /// variables that may or may not be used in certain specializations of + /// a nested generic lambda. + /// + /// \returns true if an error occurred (i.e., the variable cannot be + /// captured) and false if the capture succeeded. + bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, + TryCaptureKind Kind, SourceLocation EllipsisLoc, + bool BuildAndDiagnose, QualType &CaptureType, + QualType &DeclRefType, + const unsigned *const FunctionScopeIndexToStopAt); - IfExistsResult - CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, - bool IsIfExists, CXXScopeSpec &SS, - UnqualifiedId &Name); + /// Try to capture the given variable. + bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, + TryCaptureKind Kind = TryCapture_Implicit, + SourceLocation EllipsisLoc = SourceLocation()); - StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc, - bool IsIfExists, - NestedNameSpecifierLoc QualifierLoc, - DeclarationNameInfo NameInfo, - Stmt *Nested); - StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, - bool IsIfExists, - CXXScopeSpec &SS, UnqualifiedId &Name, - Stmt *Nested); + /// Checks if the variable must be captured. + bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc); - //===------------------------- "Block" Extension ------------------------===// + /// Given a variable, determine the type that a reference to that + /// variable will have in the given scope. + QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc); - /// ActOnBlockStart - This callback is invoked when a block literal is - /// started. - void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope); + /// Mark all of the declarations referenced within a particular AST node as + /// referenced. Used when template instantiation instantiates a non-dependent + /// type -- entities referenced by the type are now referenced. + void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); + void MarkDeclarationsReferencedInExpr( + Expr *E, bool SkipLocalVariables = false, + ArrayRef StopAt = std::nullopt); - /// ActOnBlockArguments - This callback allows processing of block arguments. - /// If there are no arguments, this is still invoked. - void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, - Scope *CurScope); + /// Try to convert an expression \p E to type \p Ty. Returns the result of the + /// conversion. + ExprResult tryConvertExprToType(Expr *E, QualType Ty); - /// ActOnBlockError - If there is an error parsing a block, this callback - /// is invoked to pop the information about the block from the action impl. - void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope); + /// Conditionally issue a diagnostic based on the statements's reachability + /// analysis. + /// + /// \param Stmts If Stmts is non-empty, delay reporting the diagnostic until + /// the function body is parsed, and then do a basic reachability analysis to + /// determine if the statement is reachable. If it is unreachable, the + /// diagnostic will not be emitted. + bool DiagIfReachable(SourceLocation Loc, ArrayRef Stmts, + const PartialDiagnostic &PD); - /// ActOnBlockStmtExpr - This is called when the body of a block statement - /// literal was successfully completed. ^(int x){...} - ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body, - Scope *CurScope); + /// Conditionally issue a diagnostic based on the current + /// evaluation context. + /// + /// \param Statement If Statement is non-null, delay reporting the + /// diagnostic until the function body is parsed, and then do a basic + /// reachability analysis to determine if the statement is reachable. + /// If it is unreachable, the diagnostic will not be emitted. + bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement, + const PartialDiagnostic &PD); + /// Similar, but diagnostic is only produced if all the specified statements + /// are reachable. + bool DiagRuntimeBehavior(SourceLocation Loc, ArrayRef Stmts, + const PartialDiagnostic &PD); - //===---------------------------- Clang Extensions ----------------------===// + // Primary Expressions. + SourceRange getExprRange(Expr *E) const; - /// __builtin_convertvector(...) - ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, - SourceLocation BuiltinLoc, - SourceLocation RParenLoc); + ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &Id, + bool HasTrailingLParen, bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC = nullptr, + bool IsInlineAsmIdentifier = false, + Token *KeywordReplacement = nullptr); - //===---------------------------- OpenCL Features -----------------------===// + void DecomposeUnqualifiedId(const UnqualifiedId &Id, + TemplateArgumentListInfo &Buffer, + DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *&TemplateArgs); - /// __builtin_astype(...) - ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, - SourceLocation BuiltinLoc, - SourceLocation RParenLoc); - ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy, - SourceLocation BuiltinLoc, - SourceLocation RParenLoc); + bool DiagnoseDependentMemberLookup(const LookupResult &R); - //===---------------------------- HLSL Features -------------------------===// - Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, - SourceLocation KwLoc, IdentifierInfo *Ident, - SourceLocation IdentLoc, SourceLocation LBrace); - void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace); + bool + DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectionCandidateCallback &CCC, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, + ArrayRef Args = std::nullopt, + DeclContext *LookupCtx = nullptr, + TypoExpr **Out = nullptr); - //===---------------------------- C++ Features --------------------------===// + DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II); + ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV); - // Act on C++ namespaces - Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, - SourceLocation NamespaceLoc, - SourceLocation IdentLoc, IdentifierInfo *Ident, - SourceLocation LBrace, - const ParsedAttributesView &AttrList, - UsingDirectiveDecl *&UsingDecl, bool IsNested); - void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); + ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, + IdentifierInfo *II, + bool AllowBuiltinCreation = false); - NamespaceDecl *getStdNamespace() const; - NamespaceDecl *getOrCreateStdNamespace(); + /// If \p D cannot be odr-used in the current expression evaluation context, + /// return a reason explaining why. Otherwise, return NOUR_None. + NonOdrUseReason getNonOdrUseReasonInCurrentContext(ValueDecl *D); - CXXRecordDecl *getStdBadAlloc() const; - EnumDecl *getStdAlignValT() const; + DeclRefExpr *BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + SourceLocation Loc, + const CXXScopeSpec *SS = nullptr); + DeclRefExpr * + BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + const DeclarationNameInfo &NameInfo, + const CXXScopeSpec *SS = nullptr, + NamedDecl *FoundD = nullptr, + SourceLocation TemplateKWLoc = SourceLocation(), + const TemplateArgumentListInfo *TemplateArgs = nullptr); + DeclRefExpr * + BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + const DeclarationNameInfo &NameInfo, + NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr, + SourceLocation TemplateKWLoc = SourceLocation(), + const TemplateArgumentListInfo *TemplateArgs = nullptr); - ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl, - const IdentifierInfo *MemberOrBase); + bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, + bool HasTrailingLParen); -private: - // A cache representing if we've fully checked the various comparison category - // types stored in ASTContext. The bit-index corresponds to the integer value - // of a ComparisonCategoryType enumerator. - llvm::SmallBitVector FullyCheckedComparisonCategories; + ExprResult + BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + bool IsAddressOfOperand, const Scope *S, + TypeSourceInfo **RecoveryTSI = nullptr); - ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, - CXXScopeSpec &SS, - ParsedType TemplateTypeTy, - IdentifierInfo *MemberOrBase); + ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, + bool NeedsADL, + bool AcceptInvalidDecl = false); + ExprResult BuildDeclarationNameExpr( + const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, + NamedDecl *FoundD = nullptr, + const TemplateArgumentListInfo *TemplateArgs = nullptr, + bool AcceptInvalidDecl = false); -public: - enum class ComparisonCategoryUsage { - /// The '<=>' operator was used in an expression and a builtin operator - /// was selected. - OperatorInExpression, - /// A defaulted 'operator<=>' needed the comparison category. This - /// typically only applies to 'std::strong_ordering', due to the implicit - /// fallback return value. - DefaultedOperator, - }; + // ExpandFunctionLocalPredefinedMacros - Returns a new vector of Tokens, + // where Tokens representing function local predefined macros (such as + // __FUNCTION__) are replaced (expanded) with string-literal Tokens. + std::vector ExpandFunctionLocalPredefinedMacros(ArrayRef Toks); - /// Lookup the specified comparison category types in the standard - /// library, an check the VarDecls possibly returned by the operator<=> - /// builtins for that type. - /// - /// \return The type of the comparison category type corresponding to the - /// specified Kind, or a null type if an error occurs - QualType CheckComparisonCategoryType(ComparisonCategoryType Kind, - SourceLocation Loc, - ComparisonCategoryUsage Usage); + ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK); + ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); + ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val); - /// Tests whether Ty is an instance of std::initializer_list and, if - /// it is and Element is not NULL, assigns the element type to Element. - bool isStdInitializerList(QualType Ty, QualType *Element); + ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc, + SourceLocation LParen, + SourceLocation RParen, + TypeSourceInfo *TSI); + ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc, + SourceLocation LParen, + SourceLocation RParen, + ParsedType ParsedTy); - /// Looks for the std::initializer_list template and instantiates it - /// with Element, or emits an error if it's not found. - /// - /// \returns The instantiated template, or null on error. - QualType BuildStdInitializerList(QualType Element, SourceLocation Loc); + bool CheckLoopHintExpr(Expr *E, SourceLocation Loc); - /// Determine whether Ctor is an initializer-list constructor, as - /// defined in [dcl.init.list]p2. - bool isInitListConstructor(const FunctionDecl *Ctor); + ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr); + ExprResult ActOnCharacterConstant(const Token &Tok, + Scope *UDLScope = nullptr); + ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E); + ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, + MultiExprArg Val); - Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, - SourceLocation NamespcLoc, CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - const ParsedAttributesView &AttrList); + /// ActOnStringLiteral - The specified tokens were lexed as pasted string + /// fragments (e.g. "foo" "bar" L"baz"). + ExprResult ActOnStringLiteral(ArrayRef StringToks, + Scope *UDLScope = nullptr); - void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); + ExprResult ActOnUnevaluatedStringLiteral(ArrayRef StringToks); - Decl *ActOnNamespaceAliasDef(Scope *CurScope, - SourceLocation NamespaceLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *Ident); + /// ControllingExprOrType is either an opaque pointer coming out of a + /// ParsedType or an Expr *. FIXME: it'd be better to split this interface + /// into two so we don't take a void *, but that's awkward because one of + /// the operands is either a ParsedType or an Expr *, which doesn't lend + /// itself to generic code very well. + ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool PredicateIsExpr, + void *ControllingExprOrType, + ArrayRef ArgTypes, + ArrayRef ArgExprs); + /// ControllingExprOrType is either a TypeSourceInfo * or an Expr *. FIXME: + /// it'd be better to split this interface into two so we don't take a + /// void *, but see the FIXME on ActOnGenericSelectionExpr as to why that + /// isn't a trivial change. + ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool PredicateIsExpr, + void *ControllingExprOrType, + ArrayRef Types, + ArrayRef Exprs); - void FilterUsingLookup(Scope *S, LookupResult &lookup); - void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow); - bool CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Target, - const LookupResult &PreviousDecls, - UsingShadowDecl *&PrevShadow); - UsingShadowDecl *BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD, - NamedDecl *Target, - UsingShadowDecl *PrevDecl); + // Binary/Unary Operators. 'Tok' is the token for the operator. + ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, + Expr *InputExpr, bool IsAfterAmp = false); + ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, + Expr *Input, bool IsAfterAmp = false); + ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, + Expr *Input, bool IsAfterAmp = false); - bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc, - bool HasTypenameKeyword, - const CXXScopeSpec &SS, - SourceLocation NameLoc, - const LookupResult &Previous); - bool CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, - const CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - SourceLocation NameLoc, - const LookupResult *R = nullptr, - const UsingDecl *UD = nullptr); + bool isQualifiedMemberAccess(Expr *E); + bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc, + const Expr *Op, + const CXXMethodDecl *MD); - NamedDecl *BuildUsingDeclaration( - Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, - bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, - const ParsedAttributesView &AttrList, bool IsInstantiation, - bool IsUsingIfExists); - NamedDecl *BuildUsingEnumDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - SourceLocation EnumLoc, - SourceLocation NameLoc, - TypeSourceInfo *EnumType, EnumDecl *ED); - NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, - ArrayRef Expansions); + QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc); - bool CheckInheritingConstructorUsingDecl(UsingDecl *UD); + bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty, + SourceLocation OpLoc, SourceRange R); + bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo, + SourceLocation OpLoc, SourceRange R); - /// Given a derived-class using shadow declaration for a constructor and the - /// correspnding base class constructor, find or create the implicit - /// synthesized derived class constructor to use for this initialization. - CXXConstructorDecl * - findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor, - ConstructorUsingShadowDecl *DerivedShadow); + ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R); + ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind); + ExprResult ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + bool IsType, void *TyOrEx, + SourceRange ArgRange); - Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, - SourceLocation UsingLoc, - SourceLocation TypenameLoc, CXXScopeSpec &SS, - UnqualifiedId &Name, SourceLocation EllipsisLoc, - const ParsedAttributesView &AttrList); - Decl *ActOnUsingEnumDeclaration(Scope *CurScope, AccessSpecifier AS, - SourceLocation UsingLoc, - SourceLocation EnumLoc, - SourceLocation IdentLoc, IdentifierInfo &II, - CXXScopeSpec *SS = nullptr); - Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, - MultiTemplateParamsArg TemplateParams, - SourceLocation UsingLoc, UnqualifiedId &Name, - const ParsedAttributesView &AttrList, - TypeResult Type, Decl *DeclFromDeclSpec); + ExprResult CheckPlaceholderExpr(Expr *E); + bool CheckVecStepExpr(Expr *E); - /// BuildCXXConstructExpr - Creates a complete call to a constructor, - /// including handling of its default argument expressions. - /// - /// \param ConstructKind - a CXXConstructExpr::ConstructionKind - ExprResult BuildCXXConstructExpr( - SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl, - CXXConstructorDecl *Constructor, MultiExprArg Exprs, - bool HadMultipleCandidates, bool IsListInitialization, - bool IsStdInitListInitialization, bool RequiresZeroInit, - CXXConstructionKind ConstructKind, SourceRange ParenRange); + bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind); + bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc, + SourceRange ExprRange, + UnaryExprOrTypeTrait ExprKind, + StringRef KWName); - /// Build a CXXConstructExpr whose constructor has already been resolved if - /// it denotes an inherited constructor. - ExprResult BuildCXXConstructExpr( - SourceLocation ConstructLoc, QualType DeclInitType, - CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, - bool HadMultipleCandidates, bool IsListInitialization, - bool IsStdInitListInitialization, bool RequiresZeroInit, - CXXConstructionKind ConstructKind, SourceRange ParenRange); + ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Kind, Expr *Input); - // FIXME: Can we remove this and have the above BuildCXXConstructExpr check if - // the constructor can be elidable? - ExprResult BuildCXXConstructExpr( - SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl, - CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, - bool HadMultipleCandidates, bool IsListInitialization, - bool IsStdInitListInitialization, bool RequiresZeroInit, - CXXConstructionKind ConstructKind, SourceRange ParenRange); + ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, + MultiExprArg ArgExprs, + SourceLocation RLoc); + ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc); - ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr, - SourceLocation InitLoc); + ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx, + Expr *ColumnIdx, + SourceLocation RBLoc); - ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field); + ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, + Expr *LowerBound, + SourceLocation ColonLocFirst, + SourceLocation ColonLocSecond, + Expr *Length, Expr *Stride, + SourceLocation RBLoc); + ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, + SourceLocation RParenLoc, + ArrayRef Dims, + ArrayRef Brackets); + /// Data structure for iterator expression. + struct OMPIteratorData { + IdentifierInfo *DeclIdent = nullptr; + SourceLocation DeclIdentLoc; + ParsedType Type; + OMPIteratorExpr::IteratorRange Range; + SourceLocation AssignLoc; + SourceLocation ColonLoc; + SourceLocation SecColonLoc; + }; - /// Instantiate or parse a C++ default argument expression as necessary. - /// Return true on error. - bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, - ParmVarDecl *Param, Expr *Init = nullptr, - bool SkipImmediateInvocations = true); + ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, + SourceLocation LLoc, SourceLocation RLoc, + ArrayRef Data); - /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating - /// the default expr if needed. - ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, - ParmVarDecl *Param, Expr *Init = nullptr); + bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl, + const FunctionProtoType *Proto, + ArrayRef Args, SourceLocation RParenLoc, + bool ExecConfig = false); + void CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param, + const Expr *ArgExpr); - /// FinalizeVarWithDestructor - Prepare for calling destructor on the - /// constructed variable. - void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. + /// This provides the location of the left/right parens and a list of comma + /// locations. + ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, + MultiExprArg ArgExprs, SourceLocation RParenLoc, + Expr *ExecConfig = nullptr); + ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, + MultiExprArg ArgExprs, SourceLocation RParenLoc, + Expr *ExecConfig = nullptr, + bool IsExecConfig = false, + bool AllowRecovery = false); + Expr *BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, + MultiExprArg CallArgs); - /// Helper class that collects exception specifications for - /// implicitly-declared special member functions. - class ImplicitExceptionSpecification { - // Pointer to allow copying - Sema *Self; - // We order exception specifications thus: - // noexcept is the most restrictive, but is only used in C++11. - // throw() comes next. - // Then a throw(collected exceptions) - // Finally no specification, which is expressed as noexcept(false). - // throw(...) is used instead if any called function uses it. - ExceptionSpecificationType ComputedEST; - llvm::SmallPtrSet ExceptionsSeen; - SmallVector Exceptions; + using ADLCallKind = CallExpr::ADLCallKind; - void ClearExceptions() { - ExceptionsSeen.clear(); - Exceptions.clear(); - } + ExprResult + BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, + ArrayRef Arg, SourceLocation RParenLoc, + Expr *Config = nullptr, bool IsExecConfig = false, + ADLCallKind UsesADL = ADLCallKind::NotADL); - public: - explicit ImplicitExceptionSpecification(Sema &Self) - : Self(&Self), ComputedEST(EST_BasicNoexcept) { - if (!Self.getLangOpts().CPlusPlus11) - ComputedEST = EST_DynamicNone; - } + ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, Declarator &D, + ParsedType &Ty, SourceLocation RParenLoc, + Expr *CastExpr); - /// Get the computed exception specification type. - ExceptionSpecificationType getExceptionSpecType() const { - assert(!isComputedNoexcept(ComputedEST) && - "noexcept(expr) should not be a possible result"); - return ComputedEST; - } + CastKind PrepareScalarCast(ExprResult &src, QualType destType); - /// The number of exceptions in the exception specification. - unsigned size() const { return Exceptions.size(); } + /// Build an altivec or OpenCL literal. + ExprResult BuildVectorLiteral(SourceLocation LParenLoc, + SourceLocation RParenLoc, Expr *E, + TypeSourceInfo *TInfo); - /// The set of exceptions in the exception specification. - const QualType *data() const { return Exceptions.data(); } + ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME); - /// Integrate another called method into the collected data. - void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method); + ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty, + SourceLocation RParenLoc, Expr *InitExpr); - /// Integrate an invoked expression into the collected data. - void CalledExpr(Expr *E) { CalledStmt(E); } + ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc, + TypeSourceInfo *TInfo, + SourceLocation RParenLoc, + Expr *LiteralExpr); - /// Integrate an invoked statement into the collected data. - void CalledStmt(Stmt *S); + ExprResult ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, + SourceLocation RBraceLoc); - /// Overwrite an EPI's exception specification with this - /// computed exception specification. - FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const { - FunctionProtoType::ExceptionSpecInfo ESI; - ESI.Type = getExceptionSpecType(); - if (ESI.Type == EST_Dynamic) { - ESI.Exceptions = Exceptions; - } else if (ESI.Type == EST_None) { - /// C++11 [except.spec]p14: - /// The exception-specification is noexcept(false) if the set of - /// potential exceptions of the special member function contains "any" - ESI.Type = EST_NoexceptFalse; - ESI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), - tok::kw_false).get(); - } - return ESI; - } - }; + ExprResult BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, + SourceLocation RBraceLoc); - /// Evaluate the implicit exception specification for a defaulted - /// special member function. - void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD); + ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, + Expr *LHSExpr, Expr *RHSExpr); + ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, + Expr *LHSExpr, Expr *RHSExpr); + ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, + Expr *LHSExpr, Expr *RHSExpr); + void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, + UnresolvedSetImpl &Functions); - /// Check the given noexcept-specifier, convert its expression, and compute - /// the appropriate ExceptionSpecificationType. - ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr, - ExceptionSpecificationType &EST); + void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc); - /// Check the given exception-specification and update the - /// exception specification information with the results. - void checkExceptionSpecification(bool IsTopLevel, - ExceptionSpecificationType EST, - ArrayRef DynamicExceptions, - ArrayRef DynamicExceptionRanges, - Expr *NoexceptExpr, - SmallVectorImpl &Exceptions, - FunctionProtoType::ExceptionSpecInfo &ESI); + /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null + /// in the case of a the GNU conditional expr extension. + ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, + SourceLocation ColonLoc, Expr *CondExpr, + Expr *LHSExpr, Expr *RHSExpr); - /// Determine if we're in a case where we need to (incorrectly) eagerly - /// parse an exception specification to work around a libstdc++ bug. - bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D); + /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". + ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, + LabelDecl *TheDecl); - /// Add an exception-specification to the given member function - /// (or member function template). The exception-specification was parsed - /// after the method itself was declared. - void actOnDelayedExceptionSpecification(Decl *Method, - ExceptionSpecificationType EST, - SourceRange SpecificationRange, - ArrayRef DynamicExceptions, - ArrayRef DynamicExceptionRanges, - Expr *NoexceptExpr); + void ActOnStartStmtExpr(); + ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt, + SourceLocation RPLoc); + ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, + SourceLocation RPLoc, unsigned TemplateDepth); + // Handle the final expression in a statement expression. + ExprResult ActOnStmtExprResult(ExprResult E); + void ActOnStmtExprError(); - class InheritedConstructorInfo; + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + struct OffsetOfComponent { + SourceLocation LocStart, LocEnd; + bool isBrackets; // true if [expr], false if .ident + union { + IdentifierInfo *IdentInfo; + Expr *E; + } U; + }; - /// Determine if a special member function should have a deleted - /// definition when it is defaulted. - bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, - InheritedConstructorInfo *ICI = nullptr, - bool Diagnose = false); + /// __builtin_offsetof(type, a.b[123][456].c) + ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, + TypeSourceInfo *TInfo, + ArrayRef Components, + SourceLocation RParenLoc); + ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc, + SourceLocation TypeLoc, + ParsedType ParsedArgTy, + ArrayRef Components, + SourceLocation RParenLoc); - /// Produce notes explaining why a defaulted function was defined as deleted. - void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD); + // __builtin_choose_expr(constExpr, expr1, expr2) + ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, Expr *CondExpr, + Expr *LHSExpr, Expr *RHSExpr, + SourceLocation RPLoc); - /// Declare the implicit default constructor for the given class. - /// - /// \param ClassDecl The class declaration into which the implicit - /// default constructor will be added. - /// - /// \returns The implicitly-declared default constructor. - CXXConstructorDecl *DeclareImplicitDefaultConstructor( - CXXRecordDecl *ClassDecl); + // __builtin_va_arg(expr, type) + ExprResult ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty, + SourceLocation RPLoc); + ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E, + TypeSourceInfo *TInfo, SourceLocation RPLoc); - /// DefineImplicitDefaultConstructor - Checks for feasibility of - /// defining this constructor as the default constructor. - void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, - CXXConstructorDecl *Constructor); + // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(), + // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location() + ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind, + SourceLocation BuiltinLoc, + SourceLocation RPLoc); - /// Declare the implicit destructor for the given class. - /// - /// \param ClassDecl The class declaration into which the implicit - /// destructor will be added. - /// - /// \returns The implicitly-declared destructor. - CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl); + // Build a potentially resolved SourceLocExpr. + ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy, + SourceLocation BuiltinLoc, SourceLocation RPLoc, + DeclContext *ParentContext); - /// DefineImplicitDestructor - Checks for feasibility of - /// defining this destructor as the default destructor. - void DefineImplicitDestructor(SourceLocation CurrentLocation, - CXXDestructorDecl *Destructor); + // __null + ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc); - /// Build an exception spec for destructors that don't have one. - /// - /// C++11 says that user-defined destructors with no exception spec get one - /// that looks as if the destructor was implicitly declared. - void AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor); + bool CheckCaseExpression(Expr *E); - /// Define the specified inheriting constructor. - void DefineInheritingConstructor(SourceLocation UseLoc, - CXXConstructorDecl *Constructor); + //===------------------------- "Block" Extension ------------------------===// - /// Declare the implicit copy constructor for the given class. - /// - /// \param ClassDecl The class declaration into which the implicit - /// copy constructor will be added. - /// - /// \returns The implicitly-declared copy constructor. - CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl); + /// ActOnBlockStart - This callback is invoked when a block literal is + /// started. + void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope); - /// DefineImplicitCopyConstructor - Checks for feasibility of - /// defining this constructor as the copy constructor. - void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, - CXXConstructorDecl *Constructor); + /// ActOnBlockArguments - This callback allows processing of block arguments. + /// If there are no arguments, this is still invoked. + void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, + Scope *CurScope); - /// Declare the implicit move constructor for the given class. - /// - /// \param ClassDecl The Class declaration into which the implicit - /// move constructor will be added. - /// - /// \returns The implicitly-declared move constructor, or NULL if it wasn't - /// declared. - CXXConstructorDecl *DeclareImplicitMoveConstructor(CXXRecordDecl *ClassDecl); + /// ActOnBlockError - If there is an error parsing a block, this callback + /// is invoked to pop the information about the block from the action impl. + void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope); - /// DefineImplicitMoveConstructor - Checks for feasibility of - /// defining this constructor as the move constructor. - void DefineImplicitMoveConstructor(SourceLocation CurrentLocation, - CXXConstructorDecl *Constructor); + /// ActOnBlockStmtExpr - This is called when the body of a block statement + /// literal was successfully completed. ^(int x){...} + ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body, + Scope *CurScope); - /// Declare the implicit copy assignment operator for the given class. - /// - /// \param ClassDecl The class declaration into which the implicit - /// copy assignment operator will be added. - /// - /// \returns The implicitly-declared copy assignment operator. - CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl); + //===---------------------------- Clang Extensions ----------------------===// - /// Defines an implicitly-declared copy assignment operator. - void DefineImplicitCopyAssignment(SourceLocation CurrentLocation, - CXXMethodDecl *MethodDecl); + /// __builtin_convertvector(...) + ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc); - /// Declare the implicit move assignment operator for the given class. - /// - /// \param ClassDecl The Class declaration into which the implicit - /// move assignment operator will be added. - /// - /// \returns The implicitly-declared move assignment operator, or NULL if it - /// wasn't declared. - CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl); + //===---------------------------- OpenCL Features -----------------------===// - /// Defines an implicitly-declared move assignment operator. - void DefineImplicitMoveAssignment(SourceLocation CurrentLocation, - CXXMethodDecl *MethodDecl); + /// __builtin_astype(...) + ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc); + ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc); - /// Force the declaration of any implicitly-declared members of this - /// class. - void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class); + /// Attempts to produce a RecoveryExpr after some AST node cannot be created. + ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, + ArrayRef SubExprs, + QualType T = QualType()); - /// Check a completed declaration of an implicit special member. - void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD); + // Note that LK_String is intentionally after the other literals, as + // this is used for diagnostics logic. + enum ObjCLiteralKind { + LK_Array, + LK_Dictionary, + LK_Numeric, + LK_Boxed, + LK_String, + LK_Block, + LK_None + }; + ObjCLiteralKind CheckLiteralKind(Expr *FromE); - /// Determine whether the given function is an implicitly-deleted - /// special member function. - bool isImplicitlyDeleted(FunctionDecl *FD); + ExprResult PerformObjectMemberConversion(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + NamedDecl *Member); - /// Check whether 'this' shows up in the type of a static member - /// function after the (naturally empty) cv-qualifier-seq would be. - /// - /// \returns true if an error occurred. - bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method); + /// CheckCallReturnType - Checks that a call expression's return type is + /// complete. Returns true on failure. The location passed in is the location + /// that best represents the call. + bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc, + CallExpr *CE, FunctionDecl *FD); - /// Whether this' shows up in the exception specification of a static - /// member function. - bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method); + /// Emit a warning for all pending noderef expressions that we recorded. + void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec); - /// Check whether 'this' shows up in the attributes of the given - /// static member function. - /// - /// \returns true if an error occurred. - bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method); + ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field); - /// MaybeBindToTemporary - If the passed in expression has a record type with - /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise - /// it simply returns the passed in expression. - ExprResult MaybeBindToTemporary(Expr *E); + /// Instantiate or parse a C++ default argument expression as necessary. + /// Return true on error. + bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, + ParmVarDecl *Param, Expr *Init = nullptr, + bool SkipImmediateInvocations = true); + + /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating + /// the default expr if needed. + ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, + ParmVarDecl *Param, Expr *Init = nullptr); /// Wrap the expression in a ConstantExpr if it is a potential immediate /// invocation. ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl); - bool CheckImmediateEscalatingFunctionDefinition( - FunctionDecl *FD, const sema::FunctionScopeInfo *FSI); - void MarkExpressionAsImmediateEscalating(Expr *E); - void DiagnoseImmediateEscalatingReason(FunctionDecl *FD); + bool IsInvalidSMECallConversion(QualType FromType, QualType ToType); - bool CompleteConstructorCall(CXXConstructorDecl *Constructor, - QualType DeclInitType, MultiExprArg ArgsPtr, - SourceLocation Loc, - SmallVectorImpl &ConvertedArgs, - bool AllowExplicit = false, - bool IsListInitialization = false); + const DeclContext *getCurObjCLexicalContext() const { + const DeclContext *DC = getCurLexicalContext(); + // A category implicitly has the attribute of the interface. + if (const ObjCCategoryDecl *CatD = dyn_cast(DC)) + DC = CatD->getClassInterface(); + return DC; + } - ParsedType getInheritingConstructorName(CXXScopeSpec &SS, - SourceLocation NameLoc, - IdentifierInfo &Name); + /// Abstract base class used for diagnosing integer constant + /// expression violations. + class VerifyICEDiagnoser { + public: + bool Suppress; - ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS, - bool EnteringContext); - ParsedType getDestructorName(IdentifierInfo &II, SourceLocation NameLoc, - Scope *S, CXXScopeSpec &SS, - ParsedType ObjectType, bool EnteringContext); + VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) {} - ParsedType getDestructorTypeForDecltype(const DeclSpec &DS, - ParsedType ObjectType); + virtual SemaDiagnosticBuilder + diagnoseNotICEType(Sema &S, SourceLocation Loc, QualType T); + virtual SemaDiagnosticBuilder diagnoseNotICE(Sema &S, + SourceLocation Loc) = 0; + virtual SemaDiagnosticBuilder diagnoseFold(Sema &S, SourceLocation Loc); + virtual ~VerifyICEDiagnoser() {} + }; - // Checks that reinterpret casts don't have undefined behavior. - void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, - bool IsDereference, SourceRange Range); + enum AllowFoldKind { + NoFold, + AllowFold, + }; - // Checks that the vector type should be initialized from a scalar - // by splatting the value rather than populating a single element. - // This is the case for AltiVecVector types as well as with - // AltiVecPixel and AltiVecBool when -faltivec-src-compat=xl is specified. - bool ShouldSplatAltivecScalarInCast(const VectorType *VecTy); + /// VerifyIntegerConstantExpression - Verifies that an expression is an ICE, + /// and reports the appropriate diagnostics. Returns false on success. + /// Can optionally return the value of the expression. + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + VerifyICEDiagnoser &Diagnoser, + AllowFoldKind CanFold = NoFold); + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + unsigned DiagID, + AllowFoldKind CanFold = NoFold); + ExprResult VerifyIntegerConstantExpression(Expr *E, + llvm::APSInt *Result = nullptr, + AllowFoldKind CanFold = NoFold); + ExprResult VerifyIntegerConstantExpression(Expr *E, + AllowFoldKind CanFold = NoFold) { + return VerifyIntegerConstantExpression(E, nullptr, CanFold); + } - // Checks if the -faltivec-src-compat=gcc option is specified. - // If so, AltiVecVector, AltiVecBool and AltiVecPixel types are - // treated the same way as they are when trying to initialize - // these vectors on gcc (an error is emitted). - bool CheckAltivecInitFromScalar(SourceRange R, QualType VecTy, - QualType SrcTy); + /// DiagnoseAssignmentAsCondition - Given that an expression is + /// being used as a boolean condition, warn if it's an assignment. + void DiagnoseAssignmentAsCondition(Expr *E); - /// ActOnCXXNamedCast - Parse - /// {dynamic,static,reinterpret,const,addrspace}_cast's. - ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, - tok::TokenKind Kind, - SourceLocation LAngleBracketLoc, - Declarator &D, - SourceLocation RAngleBracketLoc, - SourceLocation LParenLoc, - Expr *E, - SourceLocation RParenLoc); + /// Redundant parentheses over an equality comparison can indicate + /// that the user intended an assignment used as condition. + void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE); - ExprResult BuildCXXNamedCast(SourceLocation OpLoc, - tok::TokenKind Kind, - TypeSourceInfo *Ty, - Expr *E, - SourceRange AngleBrackets, - SourceRange Parens); + class FullExprArg { + public: + FullExprArg() : E(nullptr) {} + FullExprArg(Sema &actions) : E(nullptr) {} - ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl, - ExprResult Operand, - SourceLocation RParenLoc); + ExprResult release() { return E; } - ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI, - Expr *Operand, SourceLocation RParenLoc); + Expr *get() const { return E; } - ExprResult BuildCXXTypeId(QualType TypeInfoType, - SourceLocation TypeidLoc, - TypeSourceInfo *Operand, - SourceLocation RParenLoc); - ExprResult BuildCXXTypeId(QualType TypeInfoType, - SourceLocation TypeidLoc, - Expr *Operand, - SourceLocation RParenLoc); + Expr *operator->() { return E; } - /// ActOnCXXTypeid - Parse typeid( something ). - ExprResult ActOnCXXTypeid(SourceLocation OpLoc, - SourceLocation LParenLoc, bool isType, - void *TyOrExpr, - SourceLocation RParenLoc); + private: + // FIXME: No need to make the entire Sema class a friend when it's just + // Sema::MakeFullExpr that needs access to the constructor below. + friend class Sema; - ExprResult BuildCXXUuidof(QualType TypeInfoType, - SourceLocation TypeidLoc, - TypeSourceInfo *Operand, - SourceLocation RParenLoc); - ExprResult BuildCXXUuidof(QualType TypeInfoType, - SourceLocation TypeidLoc, - Expr *Operand, - SourceLocation RParenLoc); + explicit FullExprArg(Expr *expr) : E(expr) {} - /// ActOnCXXUuidof - Parse __uuidof( something ). - ExprResult ActOnCXXUuidof(SourceLocation OpLoc, - SourceLocation LParenLoc, bool isType, - void *TyOrExpr, - SourceLocation RParenLoc); + Expr *E; + }; - /// Handle a C++1z fold-expression: ( expr op ... op expr ). - ExprResult ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS, - tok::TokenKind Operator, - SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc); - ExprResult BuildCXXFoldExpr(UnresolvedLookupExpr *Callee, - SourceLocation LParenLoc, Expr *LHS, - BinaryOperatorKind Operator, - SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc, - std::optional NumExpansions); - ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, - BinaryOperatorKind Operator); - - //// ActOnCXXThis - Parse 'this' pointer. - ExprResult ActOnCXXThis(SourceLocation loc); - - /// Build a CXXThisExpr and mark it referenced in the current context. - Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); - void MarkThisReferenced(CXXThisExpr *This); - - /// Try to retrieve the type of the 'this' pointer. - /// - /// \returns The type of 'this', if possible. Otherwise, returns a NULL type. - QualType getCurrentThisType(); + FullExprArg MakeFullExpr(Expr *Arg) { + return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); + } + FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { + return FullExprArg( + ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get()); + } + FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { + ExprResult FE = + ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), + /*DiscardedValue*/ true); + return FullExprArg(FE.get()); + } - /// When non-NULL, the C++ 'this' expression is allowed despite the - /// current context not being a non-static member function. In such cases, - /// this provides the type used for 'this'. - QualType CXXThisTypeOverride; + class ConditionResult { + Decl *ConditionVar; + FullExprArg Condition; + bool Invalid; + std::optional KnownValue; - /// RAII object used to temporarily allow the C++ 'this' expression - /// to be used, with the given qualifiers on the current class type. - class CXXThisScopeRAII { - Sema &S; - QualType OldCXXThisTypeOverride; - bool Enabled; + friend class Sema; + ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition, + bool IsConstexpr) + : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) { + if (IsConstexpr && Condition.get()) { + if (std::optional Val = + Condition.get()->getIntegerConstantExpr(S.Context)) { + KnownValue = !!(*Val); + } + } + } + explicit ConditionResult(bool Invalid) + : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid), + KnownValue(std::nullopt) {} public: - /// Introduce a new scope where 'this' may be allowed (when enabled), - /// using the given declaration (which is either a class template or a - /// class) along with the given qualifiers. - /// along with the qualifiers placed on '*this'. - CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals, - bool Enabled = true); - - ~CXXThisScopeRAII(); + ConditionResult() : ConditionResult(false) {} + bool isInvalid() const { return Invalid; } + std::pair get() const { + return std::make_pair(cast_or_null(ConditionVar), + Condition.get()); + } + std::optional getKnownValue() const { return KnownValue; } }; + static ConditionResult ConditionError() { return ConditionResult(true); } - /// Make sure the value of 'this' is actually available in the current - /// context, if it is a potentially evaluated context. - /// - /// \param Loc The location at which the capture of 'this' occurs. - /// - /// \param Explicit Whether 'this' is explicitly captured in a lambda - /// capture list. + /// CheckBooleanCondition - Diagnose problems involving the use of + /// the given expression as a boolean condition (e.g. in an if + /// statement). Also performs the standard function and array + /// decays, possibly changing the input variable. /// - /// \param FunctionScopeIndexToStopAt If non-null, it points to the index - /// of the FunctionScopeInfo stack beyond which we do not attempt to capture. - /// This is useful when enclosing lambdas must speculatively capture - /// 'this' that may or may not be used in certain specializations of - /// a nested generic lambda (depending on whether the name resolves to - /// a non-static member function or a static function). - /// \return returns 'true' if failed, 'false' if success. - bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false, - bool BuildAndDiagnose = true, - const unsigned *const FunctionScopeIndexToStopAt = nullptr, - bool ByCopy = false); + /// \param Loc - A location associated with the condition, e.g. the + /// 'if' keyword. + /// \return true iff there were any errors + ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, + bool IsConstexpr = false); - /// Determine whether the given type is the type of *this that is used - /// outside of the body of a member function for a type that is currently - /// being defined. - bool isThisOutsideMemberFunctionBody(QualType BaseType); + enum class ConditionKind { + Boolean, ///< A boolean condition, from 'if', 'while', 'for', or 'do'. + ConstexprIf, ///< A constant boolean condition from 'if constexpr'. + Switch ///< An integral condition for a 'switch' statement. + }; - /// ActOnCXXBoolLiteral - Parse {true,false} literals. - ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); + ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr, + ConditionKind CK, bool MissingOK = false); + QualType CheckConditionalOperands( // C99 6.5.15 + ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, + ExprObjectKind &OK, SourceLocation QuestionLoc); - /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. - ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); + QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc); - ExprResult - ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs, - SourceLocation AtLoc, SourceLocation RParen); + bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, + SourceLocation QuestionLoc); - /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. - ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc); + /// type checking for vector binary operators. + QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, bool IsCompAssign, + bool AllowBothBool, bool AllowBoolConversion, + bool AllowBoolOperation, bool ReportInvalid); + QualType GetSignedVectorType(QualType V); + QualType GetSignedSizelessVectorType(QualType V); + QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + BinaryOperatorKind Opc); + QualType CheckSizelessVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + BinaryOperatorKind Opc); + QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc); - //// ActOnCXXThrow - Parse throw expressions. - ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr); - ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, - bool IsThrownVarInScope); - bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E); + /// Context in which we're performing a usual arithmetic conversion. + enum ArithConvKind { + /// An arithmetic operation. + ACK_Arithmetic, + /// A bitwise operation. + ACK_BitwiseOp, + /// A comparison. + ACK_Comparison, + /// A conditional (?:) operator. + ACK_Conditional, + /// A compound assignment expression. + ACK_CompAssign, + }; - /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. - /// Can be interpreted either as function-style casting ("int(x)") - /// or class type construction ("ClassType(x,y,z)") - /// or creation of a value-initialized type ("int()"). - ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep, - SourceLocation LParenOrBraceLoc, - MultiExprArg Exprs, - SourceLocation RParenOrBraceLoc, - bool ListInitialization); + // type checking for sizeless vector binary operators. + QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, bool IsCompAssign, + ArithConvKind OperationKind); - ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type, - SourceLocation LParenLoc, - MultiExprArg Exprs, - SourceLocation RParenLoc, - bool ListInitialization); + /// Type checking for matrix binary operators. + QualType CheckMatrixElementwiseOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, + bool IsCompAssign); + QualType CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, bool IsCompAssign); - /// ActOnCXXNew - Parsed a C++ 'new' expression. - ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, - SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, - SourceRange TypeIdParens, Declarator &D, - Expr *Initializer); - ExprResult - BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, - MultiExprArg PlacementArgs, SourceLocation PlacementRParen, - SourceRange TypeIdParens, QualType AllocType, - TypeSourceInfo *AllocTypeInfo, std::optional ArraySize, - SourceRange DirectInitRange, Expr *Initializer); + bool isValidSveBitcast(QualType srcType, QualType destType); + bool isValidRVVBitcast(QualType srcType, QualType destType); - /// Determine whether \p FD is an aligned allocation or deallocation - /// function that is unavailable. - bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const; + bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy); - /// Produce diagnostics if \p FD is an aligned allocation or deallocation - /// function that is unavailable. - void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, - SourceLocation Loc); + bool areVectorTypesSameSize(QualType srcType, QualType destType); + bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType); + bool isLaxVectorConversion(QualType srcType, QualType destType); + bool anyAltivecTypes(QualType srcType, QualType destType); - bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, - SourceRange R); + // type checking C++ declaration initializers (C++ [dcl.init]). - /// The scope in which to find allocation functions. - enum AllocationFunctionScope { - /// Only look for allocation functions in the global scope. - AFS_Global, - /// Only look for allocation functions in the scope of the - /// allocated class. - AFS_Class, - /// Look for allocation functions in both the global scope - /// and in the scope of the allocated class. - AFS_Both - }; + ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, + Expr *CastExpr, CastKind &CastKind, + ExprValueKind &VK, CXXCastPath &Path); - /// Finds the overloads of operator new and delete that are appropriate - /// for the allocation. - bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, - AllocationFunctionScope NewScope, - AllocationFunctionScope DeleteScope, - QualType AllocType, bool IsArray, - bool &PassAlignment, MultiExprArg PlaceArgs, - FunctionDecl *&OperatorNew, - FunctionDecl *&OperatorDelete, - bool Diagnose = true); - void DeclareGlobalNewDelete(); - void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, - ArrayRef Params); + /// Force an expression with unknown-type to an expression of the + /// given type. + ExprResult forceUnknownAnyToType(Expr *E, QualType ToType); - bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, - DeclarationName Name, FunctionDecl *&Operator, - bool Diagnose = true, bool WantSize = false, - bool WantAligned = false); - FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc, - bool CanProvideSize, - bool Overaligned, - DeclarationName Name); - FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc, - CXXRecordDecl *RD); + /// Type-check an expression that's being passed to an + /// __unknown_anytype parameter. + ExprResult checkUnknownAnyArg(SourceLocation callLoc, Expr *result, + QualType ¶mType); - /// ActOnCXXDelete - Parsed a C++ 'delete' expression - ExprResult ActOnCXXDelete(SourceLocation StartLoc, - bool UseGlobal, bool ArrayForm, - Expr *Operand); - void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, - bool IsDelete, bool CallCanBeVirtual, - bool WarnOnNonAbstractTypes, - SourceLocation DtorLoc); - - ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen, - Expr *Operand, SourceLocation RParen); - ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, - SourceLocation RParen); + // CheckMatrixCast - Check type constraints for matrix casts. + // We allow casting between matrixes of the same dimensions i.e. when they + // have the same number of rows and column. Returns true if the cast is + // invalid. + bool CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy, + CastKind &Kind); - /// Parsed one of the type trait support pseudo-functions. - ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, - ArrayRef Args, - SourceLocation RParenLoc); - ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, - ArrayRef Args, - SourceLocation RParenLoc); + // CheckVectorCast - check type constraints for vectors. + // Since vectors are an extension, there are no C standard reference for this. + // We allow casting between vectors and integer datatypes of the same size. + // returns true if the cast is invalid + bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, + CastKind &Kind); - /// ActOnArrayTypeTrait - Parsed one of the binary type trait support - /// pseudo-functions. - ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, - SourceLocation KWLoc, - ParsedType LhsTy, - Expr *DimExpr, - SourceLocation RParen); + /// Prepare `SplattedExpr` for a vector splat operation, adding + /// implicit casts if necessary. + ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr); - ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, - SourceLocation KWLoc, - TypeSourceInfo *TSInfo, - Expr *DimExpr, - SourceLocation RParen); + // CheckExtVectorCast - check type constraints for extended vectors. + // Since vectors are an extension, there are no C standard reference for this. + // We allow casting between vectors and integer datatypes of the same size, + // or vectors and the element type of that vector. + // returns the cast expr + ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr, + CastKind &Kind); - /// ActOnExpressionTrait - Parsed one of the unary type trait support - /// pseudo-functions. - ExprResult ActOnExpressionTrait(ExpressionTrait OET, - SourceLocation KWLoc, - Expr *Queried, - SourceLocation RParen); + QualType PreferredConditionType(ConditionKind K) const { + return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy; + } - ExprResult BuildExpressionTrait(ExpressionTrait OET, - SourceLocation KWLoc, - Expr *Queried, - SourceLocation RParen); + // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts + // functions and arrays to their respective pointers (C99 6.3.2.1). + ExprResult UsualUnaryConversions(Expr *E); - ExprResult ActOnStartCXXMemberReference(Scope *S, - Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - ParsedType &ObjectType, - bool &MayBePseudoDestructor); + /// CallExprUnaryConversions - a special case of an unary conversion + /// performed on a function designator of a call expression. + ExprResult CallExprUnaryConversions(Expr *E); - ExprResult BuildPseudoDestructorExpr(Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - TypeSourceInfo *ScopeType, - SourceLocation CCLoc, - SourceLocation TildeLoc, - PseudoDestructorTypeStorage DestroyedType); + // DefaultFunctionArrayConversion - converts functions and arrays + // to their respective pointers (C99 6.3.2.1). + ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true); - ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - CXXScopeSpec &SS, - UnqualifiedId &FirstTypeName, - SourceLocation CCLoc, - SourceLocation TildeLoc, - UnqualifiedId &SecondTypeName); + // DefaultFunctionArrayLvalueConversion - converts functions and + // arrays to their respective pointers and performs the + // lvalue-to-rvalue conversion. + ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, + bool Diagnose = true); - ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation TildeLoc, - const DeclSpec& DS); + // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on + // the operand. This function is a no-op if the operand has a function type + // or an array type. + ExprResult DefaultLvalueConversion(Expr *E); - /// MaybeCreateExprWithCleanups - If the current full-expression - /// requires any cleanups, surround it with a ExprWithCleanups node. - /// Otherwise, just returns the passed-in expression. - Expr *MaybeCreateExprWithCleanups(Expr *SubExpr); - Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt); - ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr); + // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that + // do not have a prototype. Integer promotions are performed on each + // argument, and arguments that have type float are promoted to double. + ExprResult DefaultArgumentPromotion(Expr *E); - MaterializeTemporaryExpr * - CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference); + VariadicCallType getVariadicCallType(FunctionDecl *FDecl, + const FunctionProtoType *Proto, + Expr *Fn); - ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) { - return ActOnFinishFullExpr( - Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue); - } - ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, - bool DiscardedValue, bool IsConstexpr = false, - bool IsTemplateArgument = false); - StmtResult ActOnFinishFullStmt(Stmt *Stmt); + // Used for determining in which context a type is allowed to be passed to a + // vararg function. + enum VarArgKind { + VAK_Valid, + VAK_ValidInCXX11, + VAK_Undefined, + VAK_MSVCUndefined, + VAK_Invalid + }; - // Marks SS invalid if it represents an incomplete type. - bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC); - // Complete an enum decl, maybe without a scope spec. - bool RequireCompleteEnumDecl(EnumDecl *D, SourceLocation L, - CXXScopeSpec *SS = nullptr); + // Determines which VarArgKind fits an expression. + VarArgKind isValidVarArgType(const QualType &Ty); - DeclContext *computeDeclContext(QualType T); - DeclContext *computeDeclContext(const CXXScopeSpec &SS, - bool EnteringContext = false); - bool isDependentScopeSpecifier(const CXXScopeSpec &SS); - CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); + /// Check to see if the given expression is a valid argument to a variadic + /// function, issuing a diagnostic if not. + void checkVariadicArgument(const Expr *E, VariadicCallType CT); - /// The parser has parsed a global nested-name-specifier '::'. - /// - /// \param CCLoc The location of the '::'. - /// - /// \param SS The nested-name-specifier, which will be updated in-place - /// to reflect the parsed nested-name-specifier. - /// - /// \returns true if an error occurred, false otherwise. - bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS); + /// GatherArgumentsForCall - Collector argument expressions for various + /// form of call prototypes. + bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstParam, ArrayRef Args, + SmallVectorImpl &AllArgs, + VariadicCallType CallType = VariadicDoesNotApply, + bool AllowExplicit = false, + bool IsListInitialization = false); - /// The parser has parsed a '__super' nested-name-specifier. - /// - /// \param SuperLoc The location of the '__super' keyword. - /// - /// \param ColonColonLoc The location of the '::'. - /// - /// \param SS The nested-name-specifier, which will be updated in-place - /// to reflect the parsed nested-name-specifier. - /// - /// \returns true if an error occurred, false otherwise. - bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc, - SourceLocation ColonColonLoc, CXXScopeSpec &SS); + // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but + // will create a runtime trap if the resulting type is not a POD type. + ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, + FunctionDecl *FDecl); - bool isAcceptableNestedNameSpecifier(const NamedDecl *SD, - bool *CanCorrect = nullptr); - NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); + // UsualArithmeticConversions - performs the UsualUnaryConversions on it's + // operands and then handles various conversions that are common to binary + // operators (C99 6.3.1.8). If both operands aren't arithmetic, this + // routine returns the first non-arithmetic type found. The client is + // responsible for emitting appropriate error diagnostics. + QualType UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc, ArithConvKind ACK); - /// Keeps information about an identifier in a nested-name-spec. - /// - struct NestedNameSpecInfo { - /// The type of the object, if we're parsing nested-name-specifier in - /// a member access expression. - ParsedType ObjectType; + /// AssignConvertType - All of the 'assignment' semantic checks return this + /// enum to indicate whether the assignment was allowed. These checks are + /// done for simple assignments, as well as initialization, return from + /// function, argument passing, etc. The query is phrased in terms of a + /// source and destination type. + enum AssignConvertType { + /// Compatible - the types are compatible according to the standard. + Compatible, - /// The identifier preceding the '::'. - IdentifierInfo *Identifier; + /// PointerToInt - The assignment converts a pointer to an int, which we + /// accept as an extension. + PointerToInt, - /// The location of the identifier. - SourceLocation IdentifierLoc; + /// IntToPointer - The assignment converts an int to a pointer, which we + /// accept as an extension. + IntToPointer, - /// The location of the '::'. - SourceLocation CCLoc; + /// FunctionVoidPointer - The assignment is between a function pointer and + /// void*, which the standard doesn't allow, but we accept as an extension. + FunctionVoidPointer, - /// Creates info object for the most typical case. - NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc, - SourceLocation ColonColonLoc, ParsedType ObjectType = ParsedType()) - : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc), - CCLoc(ColonColonLoc) { - } + /// IncompatiblePointer - The assignment is between two pointers types that + /// are not compatible, but we accept them as an extension. + IncompatiblePointer, - NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc, - SourceLocation ColonColonLoc, QualType ObjectType) - : ObjectType(ParsedType::make(ObjectType)), Identifier(II), - IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) { - } - }; + /// IncompatibleFunctionPointer - The assignment is between two function + /// pointers types that are not compatible, but we accept them as an + /// extension. + IncompatibleFunctionPointer, - bool BuildCXXNestedNameSpecifier(Scope *S, - NestedNameSpecInfo &IdInfo, - bool EnteringContext, - CXXScopeSpec &SS, - NamedDecl *ScopeLookupResult, - bool ErrorRecoveryLookup, - bool *IsCorrectedToColon = nullptr, - bool OnlyNamespace = false); + /// IncompatibleFunctionPointerStrict - The assignment is between two + /// function pointer types that are not identical, but are compatible, + /// unless compiled with -fsanitize=cfi, in which case the type mismatch + /// may trip an indirect call runtime check. + IncompatibleFunctionPointerStrict, - /// The parser has parsed a nested-name-specifier 'identifier::'. - /// - /// \param S The scope in which this nested-name-specifier occurs. - /// - /// \param IdInfo Parser information about an identifier in the - /// nested-name-spec. - /// - /// \param EnteringContext Whether we're entering the context nominated by - /// this nested-name-specifier. - /// - /// \param SS The nested-name-specifier, which is both an input - /// parameter (the nested-name-specifier before this type) and an - /// output parameter (containing the full nested-name-specifier, - /// including this new type). - /// - /// \param IsCorrectedToColon If not null, suggestions to replace '::' -> ':' - /// are allowed. The bool value pointed by this parameter is set to 'true' - /// if the identifier is treated as if it was followed by ':', not '::'. - /// - /// \param OnlyNamespace If true, only considers namespaces in lookup. - /// - /// \returns true if an error occurred, false otherwise. - bool ActOnCXXNestedNameSpecifier(Scope *S, - NestedNameSpecInfo &IdInfo, - bool EnteringContext, - CXXScopeSpec &SS, - bool *IsCorrectedToColon = nullptr, - bool OnlyNamespace = false); + /// IncompatiblePointerSign - The assignment is between two pointers types + /// which point to integers which have a different sign, but are otherwise + /// identical. This is a subset of the above, but broken out because it's by + /// far the most common case of incompatible pointers. + IncompatiblePointerSign, - ExprResult ActOnDecltypeExpression(Expr *E); - - bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, - const DeclSpec &DS, - SourceLocation ColonColonLoc); + /// CompatiblePointerDiscardsQualifiers - The assignment discards + /// c/v/r qualifiers, which we accept as an extension. + CompatiblePointerDiscardsQualifiers, - bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS, - const DeclSpec &DS, - SourceLocation ColonColonLoc, - QualType Type); + /// IncompatiblePointerDiscardsQualifiers - The assignment + /// discards qualifiers that we don't permit to be discarded, + /// like address spaces. + IncompatiblePointerDiscardsQualifiers, - bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, - NestedNameSpecInfo &IdInfo, - bool EnteringContext); + /// IncompatibleNestedPointerAddressSpaceMismatch - The assignment + /// changes address spaces in nested pointer types which is not allowed. + /// For instance, converting __private int ** to __generic int ** is + /// illegal even though __private could be converted to __generic. + IncompatibleNestedPointerAddressSpaceMismatch, - bool IsInvalidSMECallConversion(QualType FromType, QualType ToType); + /// IncompatibleNestedPointerQualifiers - The assignment is between two + /// nested pointer types, and the qualifiers other than the first two + /// levels differ e.g. char ** -> const char **, but we accept them as an + /// extension. + IncompatibleNestedPointerQualifiers, - /// The parser has parsed a nested-name-specifier - /// 'template[opt] template-name < template-args >::'. - /// - /// \param S The scope in which this nested-name-specifier occurs. - /// - /// \param SS The nested-name-specifier, which is both an input - /// parameter (the nested-name-specifier before this type) and an - /// output parameter (containing the full nested-name-specifier, - /// including this new type). - /// - /// \param TemplateKWLoc the location of the 'template' keyword, if any. - /// \param TemplateName the template name. - /// \param TemplateNameLoc The location of the template name. - /// \param LAngleLoc The location of the opening angle bracket ('<'). - /// \param TemplateArgs The template arguments. - /// \param RAngleLoc The location of the closing angle bracket ('>'). - /// \param CCLoc The location of the '::'. - /// - /// \param EnteringContext Whether we're entering the context of the - /// nested-name-specifier. - /// - /// - /// \returns true if an error occurred, false otherwise. - bool ActOnCXXNestedNameSpecifier(Scope *S, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - TemplateTy TemplateName, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, - SourceLocation CCLoc, - bool EnteringContext); + /// IncompatibleVectors - The assignment is between two vector types that + /// have the same size, which we accept as an extension. + IncompatibleVectors, - /// Given a C++ nested-name-specifier, produce an annotation value - /// that the parser can use later to reconstruct the given - /// nested-name-specifier. - /// - /// \param SS A nested-name-specifier. - /// - /// \returns A pointer containing all of the information in the - /// nested-name-specifier \p SS. - void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS); + /// IntToBlockPointer - The assignment converts an int to a block + /// pointer. We disallow this. + IntToBlockPointer, - /// Given an annotation pointer for a nested-name-specifier, restore - /// the nested-name-specifier structure. - /// - /// \param Annotation The annotation pointer, produced by - /// \c SaveNestedNameSpecifierAnnotation(). - /// - /// \param AnnotationRange The source range corresponding to the annotation. - /// - /// \param SS The nested-name-specifier that will be updated with the contents - /// of the annotation pointer. - void RestoreNestedNameSpecifierAnnotation(void *Annotation, - SourceRange AnnotationRange, - CXXScopeSpec &SS); + /// IncompatibleBlockPointer - The assignment is between two block + /// pointers types that are not compatible. + IncompatibleBlockPointer, - bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS); + /// IncompatibleObjCQualifiedId - The assignment is between a qualified + /// id type and something else (that is incompatible with it). For example, + /// "id " = "Foo *", where "Foo *" doesn't implement the XXX protocol. + IncompatibleObjCQualifiedId, - /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global - /// scope or nested-name-specifier) is parsed, part of a declarator-id. - /// After this method is called, according to [C++ 3.4.3p3], names should be - /// looked up in the declarator-id's scope, until the declarator is parsed and - /// ActOnCXXExitDeclaratorScope is called. - /// The 'SS' should be a non-empty valid CXXScopeSpec. - bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS); + /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an + /// object with __weak qualifier. + IncompatibleObjCWeakRef, - /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously - /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same - /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. - /// Used to indicate that names should revert to being looked up in the - /// defining scope. - void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS); + /// Incompatible - We reject this conversion outright, it is invalid to + /// represent it in the AST. + Incompatible + }; - /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an - /// initializer for the declaration 'Dcl'. - /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a - /// static data member of class X, names should be looked up in the scope of - /// class X. - void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl); + /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the + /// assignment conversion type specified by ConvTy. This returns true if the + /// conversion was invalid or false if the conversion was accepted. + bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc, + QualType DstType, QualType SrcType, + Expr *SrcExpr, AssignmentAction Action, + bool *Complained = nullptr); - /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an - /// initializer for the declaration 'Dcl'. - void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); + /// CheckAssignmentConstraints - Perform type checking for assignment, + /// argument passing, variable initialization, and function return values. + /// C99 6.5.16. + AssignConvertType CheckAssignmentConstraints(SourceLocation Loc, + QualType LHSType, + QualType RHSType); - /// Create a new lambda closure type. - CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, - TypeSourceInfo *Info, - unsigned LambdaDependencyKind, - LambdaCaptureDefault CaptureDefault); + /// Check assignment constraints and optionally prepare for a conversion of + /// the RHS to the LHS type. The conversion is prepared for if ConvertRHS + /// is true. + AssignConvertType CheckAssignmentConstraints(QualType LHSType, + ExprResult &RHS, CastKind &Kind, + bool ConvertRHS = true); - /// Number lambda for linkage purposes if necessary. - void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method, - std::optional - NumberingOverride = std::nullopt); + /// Check assignment constraints for an assignment of RHS to LHSType. + /// + /// \param LHSType The destination type for the assignment. + /// \param RHS The source expression for the assignment. + /// \param Diagnose If \c true, diagnostics may be produced when checking + /// for assignability. If a diagnostic is produced, \p RHS will be + /// set to ExprError(). Note that this function may still return + /// without producing a diagnostic, even for an invalid assignment. + /// \param DiagnoseCFAudited If \c true, the target is a function parameter + /// in an audited Core Foundation API and does not need to be checked + /// for ARC retain issues. + /// \param ConvertRHS If \c true, \p RHS will be updated to model the + /// conversions necessary to perform the assignment. If \c false, + /// \p Diagnose must also be \c false. + AssignConvertType CheckSingleAssignmentConstraints( + QualType LHSType, ExprResult &RHS, bool Diagnose = true, + bool DiagnoseCFAudited = false, bool ConvertRHS = true); - /// Endow the lambda scope info with the relevant properties. - void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator, - SourceRange IntroducerRange, - LambdaCaptureDefault CaptureDefault, - SourceLocation CaptureDefaultLoc, bool ExplicitParams, - bool Mutable); + // If the lhs type is a transparent union, check whether we + // can initialize the transparent union with the given expression. + AssignConvertType CheckTransparentUnionArgumentConstraints(QualType ArgType, + ExprResult &RHS); - CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange, - CXXRecordDecl *Class); + /// the following "Check" methods will return a valid/converted QualType + /// or a null QualType (indicating an error diagnostic was issued). - void AddTemplateParametersToLambdaCallOperator( - CXXMethodDecl *CallOperator, CXXRecordDecl *Class, - TemplateParameterList *TemplateParams); + /// type checking binary operators (subroutines of CreateBuiltinBinOp). + QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS); + QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS); - void CompleteLambdaCallOperator( - CXXMethodDecl *Method, SourceLocation LambdaLoc, - SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause, - TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind, - StorageClass SC, ArrayRef Params, - bool HasExplicitResultType); + QualType CheckMultiplyDivideOperands( // C99 6.5.5 + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign, + bool IsDivide); + QualType CheckRemainderOperands( // C99 6.5.5 + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + bool IsCompAssign = false); + QualType CheckAdditionOperands( // C99 6.5.6 + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + BinaryOperatorKind Opc, QualType *CompLHSTy = nullptr); + QualType CheckSubtractionOperands( // C99 6.5.6 + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + QualType *CompLHSTy = nullptr); + QualType CheckShiftOperands( // C99 6.5.7 + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + BinaryOperatorKind Opc, bool IsCompAssign = false); + void CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE); + QualType CheckCompareOperands( // C99 6.5.8/9 + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + BinaryOperatorKind Opc); + QualType CheckBitwiseOperands( // C99 6.5.[10...12] + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + BinaryOperatorKind Opc); + QualType CheckLogicalOperands( // C99 6.5.[13,14] + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + BinaryOperatorKind Opc); + // CheckAssignmentOperands is used for both simple and compound assignment. + // For simple assignment, pass both expressions and a null converted type. + // For compound assignment, pass both expressions and the converted type. + QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] + Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType, + BinaryOperatorKind Opc); - void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method); + bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr, + bool Diagnose = true); - /// Perform initialization analysis of the init-capture and perform - /// any implicit conversions such as an lvalue-to-rvalue conversion if - /// not being used to initialize a reference. - ParsedType actOnLambdaInitCaptureInitialization( - SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc, - IdentifierInfo *Id, LambdaCaptureInitKind InitKind, Expr *&Init) { - return ParsedType::make(buildLambdaInitCaptureInitialization( - Loc, ByRef, EllipsisLoc, std::nullopt, Id, - InitKind != LambdaCaptureInitKind::CopyInit, Init)); + /// To be used for checking whether the arguments being passed to + /// function exceeds the number of parameters expected for it. + static bool TooManyArguments(size_t NumParams, size_t NumArgs, + bool PartialOverloading = false) { + // We check whether we're just after a comma in code-completion. + if (NumArgs > 0 && PartialOverloading) + return NumArgs + 1 > NumParams; // If so, we view as an extra argument. + return NumArgs > NumParams; } - QualType buildLambdaInitCaptureInitialization( - SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc, - std::optional NumExpansions, IdentifierInfo *Id, - bool DirectInit, Expr *&Init); - /// Create a dummy variable within the declcontext of the lambda's - /// call operator, for name lookup purposes for a lambda init capture. - /// - /// CodeGen handles emission of lambda captures, ignoring these dummy - /// variables appropriately. - VarDecl *createLambdaInitCaptureVarDecl( - SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc, - IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx); + /// Whether the AST is currently being rebuilt to correct immediate + /// invocations. Immediate invocation candidates and references to consteval + /// functions aren't tracked when this is set. + bool RebuildingImmediateInvocation = false; - /// Add an init-capture to a lambda scope. - void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef); + bool isAlwaysConstantEvaluatedContext() const { + const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext(); + return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) && + !Ctx.InConditionallyConstantEvaluateContext; + } - /// Note that we have finished the explicit captures for the - /// given lambda. - void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); + /// Determines whether we are currently in a context that + /// is not evaluated as per C++ [expr] p5. + bool isUnevaluatedContext() const { + return currentEvaluationContext().isUnevaluated(); + } - /// Deduce a block or lambda's return type based on the return - /// statements present in the body. - void deduceClosureReturnType(sema::CapturingScopeInfo &CSI); + bool isImmediateFunctionContext() const { + return currentEvaluationContext().isImmediateFunctionContext(); + } - /// Once the Lambdas capture are known, we can start to create the closure, - /// call operator method, and keep track of the captures. - /// We do the capture lookup here, but they are not actually captured until - /// after we know what the qualifiers of the call operator are. - void ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, - Scope *CurContext); + bool isInLifetimeExtendingContext() const { + assert(!ExprEvalContexts.empty() && + "Must be in an expression evaluation context"); + return ExprEvalContexts.back().InLifetimeExtendingContext; + } - /// This is called after parsing the explicit template parameter list - /// on a lambda (if it exists) in C++2a. - void ActOnLambdaExplicitTemplateParameterList(LambdaIntroducer &Intro, - SourceLocation LAngleLoc, - ArrayRef TParams, - SourceLocation RAngleLoc, - ExprResult RequiresClause); + bool isCheckingDefaultArgumentOrInitializer() const { + const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext(); + return (Ctx.Context == + ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) || + Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer; + } - void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro, - SourceLocation MutableLoc); + std::optional + InnermostDeclarationWithDelayedImmediateInvocations() const { + assert(!ExprEvalContexts.empty() && + "Must be in an expression evaluation context"); + for (const auto &Ctx : llvm::reverse(ExprEvalContexts)) { + if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated && + Ctx.DelayedDefaultInitializationContext) + return Ctx.DelayedDefaultInitializationContext; + if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() || + Ctx.isUnevaluated()) + break; + } + return std::nullopt; + } - void ActOnLambdaClosureParameters( - Scope *LambdaScope, - MutableArrayRef ParamInfo); + std::optional + OutermostDeclarationWithDelayedImmediateInvocations() const { + assert(!ExprEvalContexts.empty() && + "Must be in an expression evaluation context"); + std::optional Res; + for (auto &Ctx : llvm::reverse(ExprEvalContexts)) { + if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated && + !Ctx.DelayedDefaultInitializationContext && Res) + break; + if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() || + Ctx.isUnevaluated()) + break; + Res = Ctx.DelayedDefaultInitializationContext; + } + return Res; + } - /// ActOnStartOfLambdaDefinition - This is called just before we start - /// parsing the body of a lambda; it analyzes the explicit captures and - /// arguments, and sets up various data-structures for the body of the - /// lambda. - void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, - Declarator &ParamInfo, const DeclSpec &DS); + /// keepInLifetimeExtendingContext - Pull down InLifetimeExtendingContext + /// flag from previous context. + void keepInLifetimeExtendingContext() { + if (ExprEvalContexts.size() > 2 && + ExprEvalContexts[ExprEvalContexts.size() - 2] + .InLifetimeExtendingContext) { + auto &LastRecord = ExprEvalContexts.back(); + auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; + LastRecord.InLifetimeExtendingContext = + PrevRecord.InLifetimeExtendingContext; + } + } - /// ActOnLambdaError - If there is an error parsing a lambda, this callback - /// is invoked to pop the information about the lambda. - void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, - bool IsInstantiation = false); + /// keepInMaterializeTemporaryObjectContext - Pull down + /// InMaterializeTemporaryObjectContext flag from previous context. + void keepInMaterializeTemporaryObjectContext() { + if (ExprEvalContexts.size() > 2 && + ExprEvalContexts[ExprEvalContexts.size() - 2] + .InMaterializeTemporaryObjectContext) { + auto &LastRecord = ExprEvalContexts.back(); + auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; + LastRecord.InMaterializeTemporaryObjectContext = + PrevRecord.InMaterializeTemporaryObjectContext; + } + } - /// ActOnLambdaExpr - This is called when the body of a lambda expression - /// was successfully completed. - ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body); + DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) { + return getDefaultedFunctionKind(FD).asComparison(); + } - /// Does copying/destroying the captured variable have side effects? - bool CaptureHasSideEffects(const sema::Capture &From); + /// Returns a field in a CXXRecordDecl that has the same name as the decl \p + /// SelfAssigned when inside a CXXMethodDecl. + const FieldDecl * + getSelfAssignmentClassMemberCandidate(const ValueDecl *SelfAssigned); - /// Diagnose if an explicit lambda capture is unused. Returns true if a - /// diagnostic is emitted. - bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, - const sema::Capture &From); + void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D); - /// Build a FieldDecl suitable to hold the given capture. - FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture); + template + bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID, + const Ts &...Args) { + SizelessTypeDiagnoser Diagnoser(DiagID, Args...); + return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser); + } - /// Initialize the given capture with a suitable expression. - ExprResult BuildCaptureInit(const sema::Capture &Capture, - SourceLocation ImplicitCaptureLoc, - bool IsOpenMPMapping = false); + template + bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID, + const Ts &...Args) { + SizelessTypeDiagnoser Diagnoser(DiagID, Args...); + return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser); + } - /// Complete a lambda-expression having processed and attached the - /// lambda body. - ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, - sema::LambdaScopeInfo *LSI); + /// Abstract class used to diagnose incomplete types. + struct TypeDiagnoser { + TypeDiagnoser() {} - /// Get the return type to use for a lambda's conversion function(s) to - /// function pointer type, given the type of the call operator. - QualType - getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType, - CallingConv CC); + virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0; + virtual ~TypeDiagnoser() {} + }; - /// Define the "body" of the conversion from a lambda object to a - /// function pointer. - /// - /// This routine doesn't actually define a sensible body; rather, it fills - /// in the initialization expression needed to copy the lambda object into - /// the block, and IR generation actually generates the real body of the - /// block pointer conversion. - void DefineImplicitLambdaToFunctionPointerConversion( - SourceLocation CurrentLoc, CXXConversionDecl *Conv); + template class BoundTypeDiagnoser : public TypeDiagnoser { + protected: + unsigned DiagID; + std::tuple Args; - /// Define the "body" of the conversion from a lambda object to a - /// block pointer. - /// - /// This routine doesn't actually define a sensible body; rather, it fills - /// in the initialization expression needed to copy the lambda object into - /// the block, and IR generation actually generates the real body of the - /// block pointer conversion. - void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc, - CXXConversionDecl *Conv); + template + void emit(const SemaDiagnosticBuilder &DB, + std::index_sequence) const { + // Apply all tuple elements to the builder in order. + bool Dummy[] = {false, (DB << getPrintable(std::get(Args)))...}; + (void)Dummy; + } - ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation, - SourceLocation ConvLocation, - CXXConversionDecl *Conv, - Expr *Src); + public: + BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args) + : TypeDiagnoser(), DiagID(DiagID), Args(Args...) { + assert(DiagID != 0 && "no diagnostic for type diagnoser"); + } - sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator); + void diagnose(Sema &S, SourceLocation Loc, QualType T) override { + const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID); + emit(DB, std::index_sequence_for()); + DB << T; + } + }; - class LambdaScopeForCallOperatorInstantiationRAII - : private FunctionScopeRAII { + /// A derivative of BoundTypeDiagnoser for which the diagnostic's type + /// parameter is preceded by a 0/1 enum that is 1 if the type is sizeless. + /// For example, a diagnostic with no other parameters would generally have + /// the form "...%select{incomplete|sizeless}0 type %1...". + template + class SizelessTypeDiagnoser : public BoundTypeDiagnoser { public: - LambdaScopeForCallOperatorInstantiationRAII( - Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, - LocalInstantiationScope &Scope, - bool ShouldAddDeclsFromParentScope = true); + SizelessTypeDiagnoser(unsigned DiagID, const Ts &...Args) + : BoundTypeDiagnoser(DiagID, Args...) {} + + void diagnose(Sema &S, SourceLocation Loc, QualType T) override { + const SemaDiagnosticBuilder &DB = S.Diag(Loc, this->DiagID); + this->emit(DB, std::index_sequence_for()); + DB << T->isSizelessType() << T; + } }; - /// Check whether the given expression is a valid constraint expression. - /// A diagnostic is emitted if it is not, false is returned, and - /// PossibleNonPrimary will be set to true if the failure might be due to a - /// non-primary expression being used as an atomic constraint. - bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(), - bool *PossibleNonPrimary = nullptr, - bool IsTrailingRequiresClause = false); + /// Check an argument list for placeholders that we won't try to + /// handle later. + bool CheckArgsForPlaceholders(MultiExprArg args); -private: - /// Caches pairs of template-like decls whose associated constraints were - /// checked for subsumption and whether or not the first's constraints did in - /// fact subsume the second's. - llvm::DenseMap, bool> SubsumptionCache; - /// Caches the normalized associated constraints of declarations (concepts or - /// constrained declarations). If an error occurred while normalizing the - /// associated constraints of the template or concept, nullptr will be cached - /// here. - llvm::DenseMap - NormalizationCache; + /// The C++ "std::source_location::__impl" struct, defined in + /// \. + RecordDecl *StdSourceLocationImplDecl; - llvm::ContextualFoldingSet - SatisfactionCache; + /// A stack of expression evaluation contexts. + SmallVector ExprEvalContexts; - /// Introduce the instantiated local variables into the local - /// instantiation scope. - void addInstantiatedLocalVarsToScope(FunctionDecl *Function, - const FunctionDecl *PatternDecl, - LocalInstantiationScope &Scope); - /// Introduce the instantiated function parameters into the local - /// instantiation scope, and set the parameter names to those used - /// in the template. - bool addInstantiatedParametersToScope( - FunctionDecl *Function, const FunctionDecl *PatternDecl, - LocalInstantiationScope &Scope, - const MultiLevelTemplateArgumentList &TemplateArgs); + // Set of failed immediate invocations to avoid double diagnosing. + llvm::SmallPtrSet FailedImmediateInvocations; - /// Introduce the instantiated captures of the lambda into the local - /// instantiation scope. - bool addInstantiatedCapturesToScope( - FunctionDecl *Function, const FunctionDecl *PatternDecl, - LocalInstantiationScope &Scope, - const MultiLevelTemplateArgumentList &TemplateArgs); - - /// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in - /// the case of lambdas) set up the LocalInstantiationScope of the current - /// function. - bool SetupConstraintScope( - FunctionDecl *FD, std::optional> TemplateArgs, - MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope); - - /// Used during constraint checking, sets up the constraint template argument - /// lists, and calls SetupConstraintScope to set up the - /// LocalInstantiationScope to have the proper set of ParVarDecls configured. - std::optional - SetupConstraintCheckingTemplateArgumentsAndScope( - FunctionDecl *FD, std::optional> TemplateArgs, - LocalInstantiationScope &Scope); + /// List of SourceLocations where 'self' is implicitly retained inside a + /// block. + llvm::SmallVector, 1> + ImplicitlyRetainedSelfLocs; private: - // The current stack of constraint satisfactions, so we can exit-early. - using SatisfactionStackEntryTy = - std::pair; - llvm::SmallVector - SatisfactionStack; + static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind); -public: - void PushSatisfactionStackEntry(const NamedDecl *D, - const llvm::FoldingSetNodeID &ID) { - const NamedDecl *Can = cast(D->getCanonicalDecl()); - SatisfactionStack.emplace_back(Can, ID); - } + /// Methods for marking which expressions involve dereferencing a pointer + /// marked with the 'noderef' attribute. Expressions are checked bottom up as + /// they are parsed, meaning that a noderef pointer may not be accessed. For + /// example, in `&*p` where `p` is a noderef pointer, we will first parse the + /// `*p`, but need to check that `address of` is called on it. This requires + /// keeping a container of all pending expressions and checking if the address + /// of them are eventually taken. + void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E); + void CheckAddressOfNoDeref(const Expr *E); - void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); } + ///@} - bool SatisfactionStackContains(const NamedDecl *D, - const llvm::FoldingSetNodeID &ID) const { - const NamedDecl *Can = cast(D->getCanonicalDecl()); - return llvm::find(SatisfactionStack, - SatisfactionStackEntryTy{Can, ID}) != - SatisfactionStack.end(); - } + // + // + // ------------------------------------------------------------------------- + // + // - // Resets the current SatisfactionStack for cases where we are instantiating - // constraints as a 'side effect' of normal instantiation in a way that is not - // indicative of recursive definition. - class SatisfactionStackResetRAII { - llvm::SmallVector - BackupSatisfactionStack; - Sema &SemaRef; + /// \name C++ Expressions + /// Implementations are in SemaExprCXX.cpp + ///@{ - public: - SatisfactionStackResetRAII(Sema &S) : SemaRef(S) { - SemaRef.SwapSatisfactionStack(BackupSatisfactionStack); - } +public: + /// The C++ "std::bad_alloc" class, which is defined by the C++ + /// standard library. + LazyDeclPtr StdBadAlloc; - ~SatisfactionStackResetRAII() { - SemaRef.SwapSatisfactionStack(BackupSatisfactionStack); - } - }; + /// The C++ "std::align_val_t" enum class, which is defined by the C++ + /// standard library. + LazyDeclPtr StdAlignValT; - void SwapSatisfactionStack( - llvm::SmallVectorImpl &NewSS) { - SatisfactionStack.swap(NewSS); - } + /// The C++ "type_info" declaration, which is defined in \. + RecordDecl *CXXTypeInfoDecl; - const NormalizedConstraint * - getNormalizedAssociatedConstraints( - NamedDecl *ConstrainedDecl, ArrayRef AssociatedConstraints); + /// A flag to remember whether the implicit forms of operator new and delete + /// have been declared. + bool GlobalNewDeleteDeclared; - /// \brief Check whether the given declaration's associated constraints are - /// at least as constrained than another declaration's according to the - /// partial ordering of constraints. - /// - /// \param Result If no error occurred, receives the result of true if D1 is - /// at least constrained than D2, and false otherwise. + /// Delete-expressions to be analyzed at the end of translation unit /// - /// \returns true if an error occurred, false otherwise. - bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef AC1, - NamedDecl *D2, MutableArrayRef AC2, - bool &Result); - - /// If D1 was not at least as constrained as D2, but would've been if a pair - /// of atomic constraints involved had been declared in a concept and not - /// repeated in two separate places in code. - /// \returns true if such a diagnostic was emitted, false otherwise. - bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, - ArrayRef AC1, NamedDecl *D2, ArrayRef AC2); + /// This list contains class members, and locations of delete-expressions + /// that could not be proven as to whether they mismatch with new-expression + /// used in initializer of the field. + llvm::MapVector DeleteExprs; - /// \brief Check whether the given list of constraint expressions are - /// satisfied (as if in a 'conjunction') given template arguments. - /// \param Template the template-like entity that triggered the constraints - /// check (either a concept or a constrained entity). - /// \param ConstraintExprs a list of constraint expressions, treated as if - /// they were 'AND'ed together. - /// \param TemplateArgLists the list of template arguments to substitute into - /// the constraint expression. - /// \param TemplateIDRange The source range of the template id that - /// caused the constraints check. - /// \param Satisfaction if true is returned, will contain details of the - /// satisfaction, with enough information to diagnose an unsatisfied - /// expression. - /// \returns true if an error occurred and satisfaction could not be checked, - /// false otherwise. - bool CheckConstraintSatisfaction( - const NamedDecl *Template, ArrayRef ConstraintExprs, - const MultiLevelTemplateArgumentList &TemplateArgLists, - SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { - llvm::SmallVector Converted; - return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted, - TemplateArgLists, TemplateIDRange, - Satisfaction); + bool isInMaterializeTemporaryObjectContext() const { + assert(!ExprEvalContexts.empty() && + "Must be in an expression evaluation context"); + return ExprEvalContexts.back().InMaterializeTemporaryObjectContext; } - /// \brief Check whether the given list of constraint expressions are - /// satisfied (as if in a 'conjunction') given template arguments. - /// Additionally, takes an empty list of Expressions which is populated with - /// the instantiated versions of the ConstraintExprs. - /// \param Template the template-like entity that triggered the constraints - /// check (either a concept or a constrained entity). - /// \param ConstraintExprs a list of constraint expressions, treated as if - /// they were 'AND'ed together. - /// \param ConvertedConstraints a out parameter that will get populated with - /// the instantiated version of the ConstraintExprs if we successfully checked - /// satisfaction. - /// \param TemplateArgList the multi-level list of template arguments to - /// substitute into the constraint expression. This should be relative to the - /// top-level (hence multi-level), since we need to instantiate fully at the - /// time of checking. - /// \param TemplateIDRange The source range of the template id that - /// caused the constraints check. - /// \param Satisfaction if true is returned, will contain details of the - /// satisfaction, with enough information to diagnose an unsatisfied - /// expression. - /// \returns true if an error occurred and satisfaction could not be checked, - /// false otherwise. - bool CheckConstraintSatisfaction( - const NamedDecl *Template, ArrayRef ConstraintExprs, - llvm::SmallVectorImpl &ConvertedConstraints, - const MultiLevelTemplateArgumentList &TemplateArgList, - SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction); - - /// \brief Check whether the given non-dependent constraint expression is - /// satisfied. Returns false and updates Satisfaction with the satisfaction - /// verdict if successful, emits a diagnostic and returns true if an error - /// occurred and satisfaction could not be determined. - /// - /// \returns true if an error occurred, false otherwise. - bool CheckConstraintSatisfaction(const Expr *ConstraintExpr, - ConstraintSatisfaction &Satisfaction); + ParsedType getInheritingConstructorName(CXXScopeSpec &SS, + SourceLocation NameLoc, + IdentifierInfo &Name); - /// Check whether the given function decl's trailing requires clause is - /// satisfied, if any. Returns false and updates Satisfaction with the - /// satisfaction verdict if successful, emits a diagnostic and returns true if - /// an error occurred and satisfaction could not be determined. - /// - /// \returns true if an error occurred, false otherwise. - bool CheckFunctionConstraints(const FunctionDecl *FD, - ConstraintSatisfaction &Satisfaction, - SourceLocation UsageLoc = SourceLocation(), - bool ForOverloadResolution = false); + ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + bool EnteringContext); + ParsedType getDestructorName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + ParsedType ObjectType, bool EnteringContext); - /// \brief Ensure that the given template arguments satisfy the constraints - /// associated with the given template, emitting a diagnostic if they do not. - /// - /// \param Template The template to which the template arguments are being - /// provided. - /// - /// \param TemplateArgs The converted, canonicalized template arguments. - /// - /// \param TemplateIDRange The source range of the template id that - /// caused the constraints check. - /// - /// \returns true if the constrains are not satisfied or could not be checked - /// for satisfaction, false if the constraints are satisfied. - bool EnsureTemplateArgumentListConstraints( - TemplateDecl *Template, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceRange TemplateIDRange); + ParsedType getDestructorTypeForDecltype(const DeclSpec &DS, + ParsedType ObjectType); - /// \brief Emit diagnostics explaining why a constraint expression was deemed - /// unsatisfied. - /// \param First whether this is the first time an unsatisfied constraint is - /// diagnosed for this error. - void - DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, - bool First = true); + ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, + TypeSourceInfo *Operand, SourceLocation RParenLoc); + ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, + Expr *Operand, SourceLocation RParenLoc); - /// \brief Emit diagnostics explaining why a constraint expression was deemed - /// unsatisfied. - void - DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction, - bool First = true); + /// ActOnCXXTypeid - Parse typeid( something ). + ExprResult ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, + SourceLocation RParenLoc); - // ParseObjCStringLiteral - Parse Objective-C string literals. - ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, - ArrayRef Strings); + ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, + TypeSourceInfo *Operand, SourceLocation RParenLoc); + ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, + Expr *Operand, SourceLocation RParenLoc); - ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S); + /// ActOnCXXUuidof - Parse __uuidof( something ). + ExprResult ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, + SourceLocation RParenLoc); - /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the - /// numeric literal expression. Type of the expression will be "NSNumber *" - /// or "id" if NSNumber is unavailable. - ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number); - ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc, - bool Value); - ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements); + //// ActOnCXXThis - Parse 'this' pointer. + ExprResult ActOnCXXThis(SourceLocation loc); - /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the - /// '@' prefixed parenthesized expression. The type of the expression will - /// either be "NSNumber *", "NSString *" or "NSValue *" depending on the type - /// of ValueType, which is allowed to be a built-in numeric type, "char *", - /// "const char *" or C structure with attribute 'objc_boxable'. - ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr); + /// Build a CXXThisExpr and mark it referenced in the current context. + Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit); + void MarkThisReferenced(CXXThisExpr *This); - ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, - Expr *IndexExpr, - ObjCMethodDecl *getterMethod, - ObjCMethodDecl *setterMethod); + /// Try to retrieve the type of the 'this' pointer. + /// + /// \returns The type of 'this', if possible. Otherwise, returns a NULL type. + QualType getCurrentThisType(); - ExprResult BuildObjCDictionaryLiteral(SourceRange SR, - MutableArrayRef Elements); + /// When non-NULL, the C++ 'this' expression is allowed despite the + /// current context not being a non-static member function. In such cases, + /// this provides the type used for 'this'. + QualType CXXThisTypeOverride; - ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc, - TypeSourceInfo *EncodedTypeInfo, - SourceLocation RParenLoc); - ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, - CXXConversionDecl *Method, - bool HadMultipleCandidates); + /// RAII object used to temporarily allow the C++ 'this' expression + /// to be used, with the given qualifiers on the current class type. + class CXXThisScopeRAII { + Sema &S; + QualType OldCXXThisTypeOverride; + bool Enabled; - ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, - SourceLocation EncodeLoc, - SourceLocation LParenLoc, - ParsedType Ty, - SourceLocation RParenLoc); + public: + /// Introduce a new scope where 'this' may be allowed (when enabled), + /// using the given declaration (which is either a class template or a + /// class) along with the given qualifiers. + /// along with the qualifiers placed on '*this'. + CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals, + bool Enabled = true); - /// ParseObjCSelectorExpression - Build selector expression for \@selector - ExprResult ParseObjCSelectorExpression(Selector Sel, - SourceLocation AtLoc, - SourceLocation SelLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc, - bool WarnMultipleSelectors); + ~CXXThisScopeRAII(); + }; - /// ParseObjCProtocolExpression - Build protocol expression for \@protocol - ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName, - SourceLocation AtLoc, - SourceLocation ProtoLoc, - SourceLocation LParenLoc, - SourceLocation ProtoIdLoc, - SourceLocation RParenLoc); + /// Make sure the value of 'this' is actually available in the current + /// context, if it is a potentially evaluated context. + /// + /// \param Loc The location at which the capture of 'this' occurs. + /// + /// \param Explicit Whether 'this' is explicitly captured in a lambda + /// capture list. + /// + /// \param FunctionScopeIndexToStopAt If non-null, it points to the index + /// of the FunctionScopeInfo stack beyond which we do not attempt to capture. + /// This is useful when enclosing lambdas must speculatively capture + /// 'this' that may or may not be used in certain specializations of + /// a nested generic lambda (depending on whether the name resolves to + /// a non-static member function or a static function). + /// \return returns 'true' if failed, 'false' if success. + bool CheckCXXThisCapture( + SourceLocation Loc, bool Explicit = false, bool BuildAndDiagnose = true, + const unsigned *const FunctionScopeIndexToStopAt = nullptr, + bool ByCopy = false); - //===--------------------------------------------------------------------===// - // C++ Declarations - // - Decl *ActOnStartLinkageSpecification(Scope *S, - SourceLocation ExternLoc, - Expr *LangStr, - SourceLocation LBraceLoc); - Decl *ActOnFinishLinkageSpecification(Scope *S, - Decl *LinkageSpec, - SourceLocation RBraceLoc); + /// Determine whether the given type is the type of *this that is used + /// outside of the body of a member function for a type that is currently + /// being defined. + bool isThisOutsideMemberFunctionBody(QualType BaseType); + /// ActOnCXXBoolLiteral - Parse {true,false} literals. + ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); - //===--------------------------------------------------------------------===// - // C++ Classes - // - CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS); - bool isCurrentClassName(const IdentifierInfo &II, Scope *S, - const CXXScopeSpec *SS = nullptr); - bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); + /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals. + ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind); - bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, - SourceLocation ColonLoc, - const ParsedAttributesView &Attrs); + ExprResult + ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs, + SourceLocation AtLoc, SourceLocation RParen); - NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, - Declarator &D, - MultiTemplateParamsArg TemplateParameterLists, - Expr *BitfieldWidth, const VirtSpecifiers &VS, - InClassInitStyle InitStyle); + /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. + ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc); - void ActOnStartCXXInClassMemberInitializer(); - void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl, - SourceLocation EqualLoc, - Expr *Init); + //// ActOnCXXThrow - Parse throw expressions. + ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr); + ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, + bool IsThrownVarInScope); + bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E); - MemInitResult ActOnMemInitializer(Decl *ConstructorD, - Scope *S, - CXXScopeSpec &SS, - IdentifierInfo *MemberOrBase, - ParsedType TemplateTypeTy, - const DeclSpec &DS, - SourceLocation IdLoc, - SourceLocation LParenLoc, - ArrayRef Args, - SourceLocation RParenLoc, - SourceLocation EllipsisLoc); + /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. + /// Can be interpreted either as function-style casting ("int(x)") + /// or class type construction ("ClassType(x,y,z)") + /// or creation of a value-initialized type ("int()"). + ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep, + SourceLocation LParenOrBraceLoc, + MultiExprArg Exprs, + SourceLocation RParenOrBraceLoc, + bool ListInitialization); - MemInitResult ActOnMemInitializer(Decl *ConstructorD, - Scope *S, - CXXScopeSpec &SS, - IdentifierInfo *MemberOrBase, - ParsedType TemplateTypeTy, - const DeclSpec &DS, - SourceLocation IdLoc, - Expr *InitList, - SourceLocation EllipsisLoc); + ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation RParenLoc, + bool ListInitialization); - MemInitResult BuildMemInitializer(Decl *ConstructorD, - Scope *S, - CXXScopeSpec &SS, - IdentifierInfo *MemberOrBase, - ParsedType TemplateTypeTy, - const DeclSpec &DS, - SourceLocation IdLoc, - Expr *Init, - SourceLocation EllipsisLoc); + /// ActOnCXXNew - Parsed a C++ 'new' expression. + ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + SourceRange TypeIdParens, Declarator &D, + Expr *Initializer); + ExprResult + BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, SourceLocation PlacementRParen, + SourceRange TypeIdParens, QualType AllocType, + TypeSourceInfo *AllocTypeInfo, std::optional ArraySize, + SourceRange DirectInitRange, Expr *Initializer); - MemInitResult BuildMemberInitializer(ValueDecl *Member, - Expr *Init, - SourceLocation IdLoc); + /// Determine whether \p FD is an aligned allocation or deallocation + /// function that is unavailable. + bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const; - MemInitResult BuildBaseInitializer(QualType BaseType, - TypeSourceInfo *BaseTInfo, - Expr *Init, - CXXRecordDecl *ClassDecl, - SourceLocation EllipsisLoc); + /// Produce diagnostics if \p FD is an aligned allocation or deallocation + /// function that is unavailable. + void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, + SourceLocation Loc); - MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, - Expr *Init, - CXXRecordDecl *ClassDecl); + bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, + SourceRange R); - bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, - CXXCtorInitializer *Initializer); + /// The scope in which to find allocation functions. + enum AllocationFunctionScope { + /// Only look for allocation functions in the global scope. + AFS_Global, + /// Only look for allocation functions in the scope of the + /// allocated class. + AFS_Class, + /// Look for allocation functions in both the global scope + /// and in the scope of the allocated class. + AFS_Both + }; - bool SetCtorInitializers( - CXXConstructorDecl *Constructor, bool AnyErrors, - ArrayRef Initializers = std::nullopt); + /// Finds the overloads of operator new and delete that are appropriate + /// for the allocation. + bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, + AllocationFunctionScope NewScope, + AllocationFunctionScope DeleteScope, + QualType AllocType, bool IsArray, + bool &PassAlignment, MultiExprArg PlaceArgs, + FunctionDecl *&OperatorNew, + FunctionDecl *&OperatorDelete, + bool Diagnose = true); + void DeclareGlobalNewDelete(); + void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, + ArrayRef Params); - void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); + bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, + DeclarationName Name, FunctionDecl *&Operator, + bool Diagnose = true, bool WantSize = false, + bool WantAligned = false); + FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc, + bool CanProvideSize, + bool Overaligned, + DeclarationName Name); + FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc, + CXXRecordDecl *RD); + /// ActOnCXXDelete - Parsed a C++ 'delete' expression + ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, + bool ArrayForm, Expr *Operand); + void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, + bool IsDelete, bool CallCanBeVirtual, + bool WarnOnNonAbstractTypes, + SourceLocation DtorLoc); - /// MarkBaseAndMemberDestructorsReferenced - Given a record decl, - /// mark all the non-trivial destructors of its members and bases as - /// referenced. - void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc, - CXXRecordDecl *Record); + ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen, + Expr *Operand, SourceLocation RParen); + ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, + SourceLocation RParen); - /// Mark destructors of virtual bases of this class referenced. In the Itanium - /// C++ ABI, this is done when emitting a destructor for any non-abstract - /// class. In the Microsoft C++ ABI, this is done any time a class's - /// destructor is referenced. - void MarkVirtualBaseDestructorsReferenced( - SourceLocation Location, CXXRecordDecl *ClassDecl, - llvm::SmallPtrSetImpl *DirectVirtualBases = nullptr); + ExprResult ActOnStartCXXMemberReference(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + ParsedType &ObjectType, + bool &MayBePseudoDestructor); - /// Do semantic checks to allow the complete destructor variant to be emitted - /// when the destructor is defined in another translation unit. In the Itanium - /// C++ ABI, destructor variants are emitted together. In the MS C++ ABI, they - /// can be emitted in separate TUs. To emit the complete variant, run a subset - /// of the checks performed when emitting a regular destructor. - void CheckCompleteDestructorVariant(SourceLocation CurrentLocation, - CXXDestructorDecl *Dtor); + ExprResult BuildPseudoDestructorExpr( + Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, + const CXXScopeSpec &SS, TypeSourceInfo *ScopeType, SourceLocation CCLoc, + SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType); - /// The list of classes whose vtables have been used within - /// this translation unit, and the source locations at which the - /// first use occurred. - typedef std::pair VTableUse; + ExprResult ActOnPseudoDestructorExpr( + Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, + CXXScopeSpec &SS, UnqualifiedId &FirstTypeName, SourceLocation CCLoc, + SourceLocation TildeLoc, UnqualifiedId &SecondTypeName); - /// The list of vtables that are required but have not yet been - /// materialized. - SmallVector VTableUses; + ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation TildeLoc, + const DeclSpec &DS); - /// The set of classes whose vtables have been used within - /// this translation unit, and a bit that will be true if the vtable is - /// required to be emitted (otherwise, it should be emitted only if needed - /// by code generation). - llvm::DenseMap VTablesUsed; + /// MaybeCreateExprWithCleanups - If the current full-expression + /// requires any cleanups, surround it with a ExprWithCleanups node. + /// Otherwise, just returns the passed-in expression. + Expr *MaybeCreateExprWithCleanups(Expr *SubExpr); + Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt); + ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr); - /// Load any externally-stored vtable uses. - void LoadExternalVTableUses(); + ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) { + return ActOnFinishFullExpr( + Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue); + } + ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, + bool DiscardedValue, bool IsConstexpr = false, + bool IsTemplateArgument = false); + StmtResult ActOnFinishFullStmt(Stmt *Stmt); - /// Note that the vtable for the given class was used at the - /// given location. - void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, - bool DefinitionRequired = false); + ExprResult ActOnDecltypeExpression(Expr *E); - /// Mark the exception specifications of all virtual member functions - /// in the given class as needed. - void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, - const CXXRecordDecl *RD); + bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id, + bool IsUDSuffix); - /// MarkVirtualMembersReferenced - Will mark all members of the given - /// CXXRecordDecl referenced. - void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD, - bool ConstexprOnly = false); + bool isUsualDeallocationFunction(const CXXMethodDecl *FD); - /// Define all of the vtables that have been used in this - /// translation unit and reference any virtual members used by those - /// vtables. - /// - /// \returns true if any work was done, false otherwise. - bool DefineUsedVTables(); + ConditionResult ActOnConditionVariable(Decl *ConditionVar, + SourceLocation StmtLoc, + ConditionKind CK); - void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); + ExprResult CheckConditionVariable(VarDecl *ConditionVar, + SourceLocation StmtLoc, ConditionKind CK); - void ActOnMemInitializers(Decl *ConstructorDecl, - SourceLocation ColonLoc, - ArrayRef MemInits, - bool AnyErrors); + /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. + ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false); - /// Check class-level dllimport/dllexport attribute. The caller must - /// ensure that referenceDLLExportedClassMethods is called some point later - /// when all outer classes of Class are complete. - void checkClassLevelDLLAttribute(CXXRecordDecl *Class); - void checkClassLevelCodeSegAttribute(CXXRecordDecl *Class); + bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType); - void referenceDLLExportedClassMethods(); + ExprResult + PerformImplicitConversion(Expr *From, QualType ToType, + const ImplicitConversionSequence &ICS, + AssignmentAction Action, + CheckedConversionKind CCK = CCK_ImplicitConversion); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + const StandardConversionSequence &SCS, + AssignmentAction Action, + CheckedConversionKind CCK); - void propagateDLLAttrToBaseClassTemplate( - CXXRecordDecl *Class, Attr *ClassAttr, - ClassTemplateSpecializationDecl *BaseTemplateSpec, - SourceLocation BaseLoc); + bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N); - /// Add gsl::Pointer attribute to std::container::iterator - /// \param ND The declaration that introduces the name - /// std::container::iterator. \param UnderlyingRecord The record named by ND. - void inferGslPointerAttribute(NamedDecl *ND, CXXRecordDecl *UnderlyingRecord); + /// Parsed one of the type trait support pseudo-functions. + ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc); + ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, + ArrayRef Args, + SourceLocation RParenLoc); - /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types. - void inferGslOwnerPointerAttribute(CXXRecordDecl *Record); + /// ActOnArrayTypeTrait - Parsed one of the binary type trait support + /// pseudo-functions. + ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc, + ParsedType LhsTy, Expr *DimExpr, + SourceLocation RParen); - /// Add [[gsl::Pointer]] attributes for std:: types. - void inferGslPointerAttribute(TypedefNameDecl *TD); + ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc, + TypeSourceInfo *TSInfo, Expr *DimExpr, + SourceLocation RParen); - void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record); + /// ActOnExpressionTrait - Parsed one of the unary type trait support + /// pseudo-functions. + ExprResult ActOnExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc, + Expr *Queried, SourceLocation RParen); - /// Check that the C++ class annoated with "trivial_abi" satisfies all the - /// conditions that are needed for the attribute to have an effect. - void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD); + ExprResult BuildExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc, + Expr *Queried, SourceLocation RParen); - void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc, - Decl *TagDecl, SourceLocation LBrac, - SourceLocation RBrac, - const ParsedAttributesView &AttrList); - void ActOnFinishCXXMemberDecls(); - void ActOnFinishCXXNonNestedClass(); + QualType CheckPointerToMemberOperands( // C++ 5.5 + ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, SourceLocation OpLoc, + bool isIndirect); + QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS, + ExprResult &RHS, + SourceLocation QuestionLoc); - void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param); - unsigned ActOnReenterTemplateScope(Decl *Template, - llvm::function_ref EnterScope); - void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); - void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); - void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); - void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record); - void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method); - void ActOnFinishDelayedMemberInitializers(Decl *Record); - void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD, - CachedTokens &Toks); - void UnmarkAsLateParsedTemplate(FunctionDecl *FD); - bool IsInsideALocalClassWithinATemplateFunction(); + QualType CheckSizelessVectorConditionalTypes(ExprResult &Cond, + ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc); - bool EvaluateStaticAssertMessageAsString(Expr *Message, std::string &Result, - ASTContext &Ctx, - bool ErrorOnInvalidMessage); - Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, - Expr *AssertExpr, - Expr *AssertMessageExpr, - SourceLocation RParenLoc); - Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, - Expr *AssertExpr, Expr *AssertMessageExpr, - SourceLocation RParenLoc, bool Failed); - void DiagnoseStaticAssertDetails(const Expr *E); + QualType CXXCheckConditionalOperands( // C++ 5.16 + ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, + ExprObjectKind &OK, SourceLocation questionLoc); - Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, - MultiTemplateParamsArg TemplateParams); - NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParams); + QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, + bool ConvertArgs = true); + QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1, + ExprResult &E2, bool ConvertArgs = true) { + Expr *E1Tmp = E1.get(), *E2Tmp = E2.get(); + QualType Composite = + FindCompositePointerType(Loc, E1Tmp, E2Tmp, ConvertArgs); + E1 = E1Tmp; + E2 = E2Tmp; + return Composite; + } - QualType CheckConstructorDeclarator(Declarator &D, QualType R, - StorageClass& SC); - void CheckConstructor(CXXConstructorDecl *Constructor); - QualType CheckDestructorDeclarator(Declarator &D, QualType R, - StorageClass& SC); - bool CheckDestructor(CXXDestructorDecl *Destructor); - void CheckConversionDeclarator(Declarator &D, QualType &R, - StorageClass& SC); - Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); - bool CheckDeductionGuideDeclarator(Declarator &D, QualType &R, - StorageClass &SC); - void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD); + /// MaybeBindToTemporary - If the passed in expression has a record type with + /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise + /// it simply returns the passed in expression. + ExprResult MaybeBindToTemporary(Expr *E); - void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD); + /// IgnoredValueConversions - Given that an expression's result is + /// syntactically ignored, perform any conversions that are + /// required. + ExprResult IgnoredValueConversions(Expr *E); - bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD, - CXXSpecialMember CSM, - SourceLocation DefaultLoc); - void CheckDelayedMemberExceptionSpecs(); + ExprResult CheckUnevaluatedOperand(Expr *E); - bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD, - DefaultedComparisonKind DCK); - void DeclareImplicitEqualityComparison(CXXRecordDecl *RD, - FunctionDecl *Spaceship); - void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD, - DefaultedComparisonKind DCK); + /// Process any TypoExprs in the given Expr and its children, + /// generating diagnostics as appropriate and returning a new Expr if there + /// were typos that were all successfully corrected and ExprError if one or + /// more typos could not be corrected. + /// + /// \param E The Expr to check for TypoExprs. + /// + /// \param InitDecl A VarDecl to avoid because the Expr being corrected is its + /// initializer. + /// + /// \param RecoverUncorrectedTypos If true, when typo correction fails, it + /// will rebuild the given Expr with all TypoExprs degraded to RecoveryExprs. + /// + /// \param Filter A function applied to a newly rebuilt Expr to determine if + /// it is an acceptable/usable result from a single combination of typo + /// corrections. As long as the filter returns ExprError, different + /// combinations of corrections will be tried until all are exhausted. + ExprResult CorrectDelayedTyposInExpr( + Expr *E, VarDecl *InitDecl = nullptr, + bool RecoverUncorrectedTypos = false, + llvm::function_ref Filter = + [](Expr *E) -> ExprResult { return E; }); - void CheckExplicitObjectMemberFunction(Declarator &D, DeclarationName Name, - QualType R, bool IsLambda, - DeclContext *DC = nullptr); - void CheckExplicitObjectMemberFunction(DeclContext *DC, Declarator &D, - DeclarationName Name, QualType R); - void CheckExplicitObjectLambda(Declarator &D); + ExprResult CorrectDelayedTyposInExpr( + ExprResult ER, VarDecl *InitDecl = nullptr, + bool RecoverUncorrectedTypos = false, + llvm::function_ref Filter = + [](Expr *E) -> ExprResult { return E; }) { + return ER.isInvalid() + ? ER + : CorrectDelayedTyposInExpr(ER.get(), InitDecl, + RecoverUncorrectedTypos, Filter); + } - //===--------------------------------------------------------------------===// - // C++ Derived Classes - // + /// Describes the result of an "if-exists" condition check. + enum IfExistsResult { + /// The symbol exists. + IER_Exists, - /// ActOnBaseSpecifier - Parsed a base specifier - CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class, - SourceRange SpecifierRange, - bool Virtual, AccessSpecifier Access, - TypeSourceInfo *TInfo, - SourceLocation EllipsisLoc); + /// The symbol does not exist. + IER_DoesNotExist, - BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, - const ParsedAttributesView &Attrs, bool Virtual, - AccessSpecifier Access, ParsedType basetype, - SourceLocation BaseLoc, - SourceLocation EllipsisLoc); + /// The name is a dependent name, so the results will differ + /// from one instantiation to the next. + IER_Dependent, - bool AttachBaseSpecifiers(CXXRecordDecl *Class, - MutableArrayRef Bases); - void ActOnBaseSpecifiers(Decl *ClassDecl, - MutableArrayRef Bases); + /// An error occurred. + IER_Error + }; - bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base); - bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, - CXXBasePaths &Paths); + IfExistsResult + CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS, + const DeclarationNameInfo &TargetNameInfo); - // FIXME: I don't like this name. - void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath); + IfExistsResult CheckMicrosoftIfExistsSymbol(Scope *S, + SourceLocation KeywordLoc, + bool IsIfExists, CXXScopeSpec &SS, + UnqualifiedId &Name); - bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, - SourceLocation Loc, SourceRange Range, - CXXCastPath *BasePath = nullptr, - bool IgnoreAccess = false); - bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, - unsigned InaccessibleBaseID, - unsigned AmbiguousBaseConvID, - SourceLocation Loc, SourceRange Range, - DeclarationName Name, - CXXCastPath *BasePath, - bool IgnoreAccess = false); + RequiresExprBodyDecl * + ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, + ArrayRef LocalParameters, + Scope *BodyScope); + void ActOnFinishRequiresExpr(); + concepts::Requirement *ActOnSimpleRequirement(Expr *E); + concepts::Requirement *ActOnTypeRequirement(SourceLocation TypenameKWLoc, + CXXScopeSpec &SS, + SourceLocation NameLoc, + IdentifierInfo *TypeName, + TemplateIdAnnotation *TemplateId); + concepts::Requirement *ActOnCompoundRequirement(Expr *E, + SourceLocation NoexceptLoc); + concepts::Requirement *ActOnCompoundRequirement( + Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS, + TemplateIdAnnotation *TypeConstraint, unsigned Depth); + concepts::Requirement *ActOnNestedRequirement(Expr *Constraint); + concepts::ExprRequirement *BuildExprRequirement( + Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc, + concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement); + concepts::ExprRequirement *BuildExprRequirement( + concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag, + bool IsSatisfied, SourceLocation NoexceptLoc, + concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement); + concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type); + concepts::TypeRequirement *BuildTypeRequirement( + concepts::Requirement::SubstitutionDiagnostic *SubstDiag); + concepts::NestedRequirement *BuildNestedRequirement(Expr *E); + concepts::NestedRequirement * + BuildNestedRequirement(StringRef InvalidConstraintEntity, + const ASTConstraintSatisfaction &Satisfaction); + ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc, + RequiresExprBodyDecl *Body, + SourceLocation LParenLoc, + ArrayRef LocalParameters, + SourceLocation RParenLoc, + ArrayRef Requirements, + SourceLocation ClosingBraceLoc); - std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths); +private: + ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, + bool IsDelete); - bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New, - const CXXMethodDecl *Old); + void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE); + void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, + bool DeleteWasArrayForm); - /// CheckOverridingFunctionReturnType - Checks whether the return types are - /// covariant, according to C++ [class.virtual]p5. - bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New, - const CXXMethodDecl *Old); + ///@} - // Check that the overriding method has no explicit object parameter. - bool CheckExplicitObjectOverride(CXXMethodDecl *New, - const CXXMethodDecl *Old); + // + // + // ------------------------------------------------------------------------- + // + // - /// CheckOverridingFunctionExceptionSpec - Checks whether the exception - /// spec is a subset of base spec. - bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, - const CXXMethodDecl *Old); + /// \name Member Access Expressions + /// Implementations are in SemaExprMember.cpp + ///@{ - bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange); +public: + ExprResult BuildPossibleImplicitMemberExpr( + const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, const Scope *S, + UnresolvedLookupExpr *AsULE = nullptr); + ExprResult + BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool IsDefiniteInstance, const Scope *S); + + ExprResult ActOnDependentMemberExpr( + Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); - /// CheckOverrideControl - Check C++11 override control semantics. - void CheckOverrideControl(NamedDecl *D); + ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, + tok::TokenKind OpKind, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + UnqualifiedId &Member, Decl *ObjCImpDecl); + + MemberExpr *BuildMemberExpr( + Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS, + SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, + bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, + QualType Ty, ExprValueKind VK, ExprObjectKind OK, + const TemplateArgumentListInfo *TemplateArgs = nullptr); + MemberExpr * + BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, + NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, + ValueDecl *Member, DeclAccessPair FoundDecl, + bool HadMultipleCandidates, + const DeclarationNameInfo &MemberNameInfo, QualType Ty, + ExprValueKind VK, ExprObjectKind OK, + const TemplateArgumentListInfo *TemplateArgs = nullptr); - /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was - /// not used in the declaration of an overriding method. - void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent); + bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, + const CXXScopeSpec &SS, + const LookupResult &R); - /// CheckForFunctionMarkedFinal - Checks whether a virtual member function - /// overrides a virtual member function marked 'final', according to - /// C++11 [class.virtual]p4. - bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, - const CXXMethodDecl *Old); + // This struct is for use by ActOnMemberAccess to allow + // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after + // changing the access operator from a '.' to a '->' (to see if that is the + // change needed to fix an error about an unknown member, e.g. when the class + // defines a custom operator->). + struct ActOnMemberAccessExtraArgs { + Scope *S; + UnqualifiedId &Id; + Decl *ObjCImpDecl; + }; + ExprResult BuildMemberReferenceExpr( + Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, const Scope *S, + ActOnMemberAccessExtraArgs *ExtraArgs = nullptr); - //===--------------------------------------------------------------------===// - // C++ Access Control + ExprResult + BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, + bool IsArrow, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierInScope, LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + const Scope *S, bool SuppressQualifierCheck = false, + ActOnMemberAccessExtraArgs *ExtraArgs = nullptr); + + ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, + SourceLocation OpLoc, + const CXXScopeSpec &SS, FieldDecl *Field, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo); + + ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow); + + ExprResult BuildAnonymousStructUnionMemberReference( + const CXXScopeSpec &SS, SourceLocation nameLoc, + IndirectFieldDecl *indirectField, + DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none), + Expr *baseObjectExpr = nullptr, SourceLocation opLoc = SourceLocation()); + +private: + void CheckMemberAccessOfNoDeref(const MemberExpr *E); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // // - enum AccessResult { - AR_accessible, - AR_inaccessible, - AR_dependent, - AR_delayed - }; + /// \name Initializers + /// Implementations are in SemaInit.cpp + ///@{ - bool SetMemberAccessSpecifier(NamedDecl *MemberDecl, - NamedDecl *PrevMemberDecl, - AccessSpecifier LexicalAS); +public: + /// Stack of types that correspond to the parameter entities that are + /// currently being copy-initialized. Can be empty. + llvm::SmallVector CurrentParameterCopyTypes; - AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, - DeclAccessPair FoundDecl); - AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, - DeclAccessPair FoundDecl); - AccessResult CheckAllocationAccess(SourceLocation OperatorLoc, - SourceRange PlacementRange, - CXXRecordDecl *NamingClass, - DeclAccessPair FoundDecl, - bool Diagnose = true); - AccessResult CheckConstructorAccess(SourceLocation Loc, - CXXConstructorDecl *D, - DeclAccessPair FoundDecl, - const InitializedEntity &Entity, - bool IsCopyBindingRefToTemp = false); - AccessResult CheckConstructorAccess(SourceLocation Loc, - CXXConstructorDecl *D, - DeclAccessPair FoundDecl, - const InitializedEntity &Entity, - const PartialDiagnostic &PDiag); - AccessResult CheckDestructorAccess(SourceLocation Loc, - CXXDestructorDecl *Dtor, - const PartialDiagnostic &PDiag, - QualType objectType = QualType()); - AccessResult CheckFriendAccess(NamedDecl *D); - AccessResult CheckMemberAccess(SourceLocation UseLoc, - CXXRecordDecl *NamingClass, - DeclAccessPair Found); - AccessResult - CheckStructuredBindingMemberAccess(SourceLocation UseLoc, - CXXRecordDecl *DecomposedClass, - DeclAccessPair Field); - AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, - const SourceRange &, - DeclAccessPair FoundDecl); - AccessResult CheckMemberOperatorAccess(SourceLocation Loc, - Expr *ObjectExpr, - Expr *ArgExpr, - DeclAccessPair FoundDecl); - AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, - ArrayRef ArgExprs, - DeclAccessPair FoundDecl); - AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr, - DeclAccessPair FoundDecl); - AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, - QualType Base, QualType Derived, - const CXXBasePath &Path, - unsigned DiagID, - bool ForceCheck = false, - bool ForceUnprivileged = false); - void CheckLookupAccess(const LookupResult &R); - bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass, - QualType BaseType); - bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, - DeclAccessPair Found, QualType ObjectType, - SourceLocation Loc, - const PartialDiagnostic &Diag); - bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, - DeclAccessPair Found, - QualType ObjectType) { - return isMemberAccessibleForDeletion(NamingClass, Found, ObjectType, - SourceLocation(), PDiag()); - } + llvm::DenseMap + AggregateDeductionCandidates; - void HandleDependentAccessCheck(const DependentDiagnostic &DD, - const MultiLevelTemplateArgumentList &TemplateArgs); - void PerformDependentDiagnostics(const DeclContext *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs); + bool IsStringInit(Expr *Init, const ArrayType *AT); - void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); + bool CanPerformAggregateInitializationForOverloadResolution( + const InitializedEntity &Entity, InitListExpr *From); - /// When true, access checking violations are treated as SFINAE - /// failures rather than hard errors. - bool AccessCheckingSFINAE; + ExprResult ActOnDesignatedInitializer(Designation &Desig, + SourceLocation EqualOrColonLoc, + bool GNUSyntax, ExprResult Init); - enum AbstractDiagSelID { - AbstractNone = -1, - AbstractReturnType, - AbstractParamType, - AbstractVariableType, - AbstractFieldType, - AbstractIvarType, - AbstractSynthesizedIvarType, - AbstractArrayType - }; + /// Check that the lifetime of the initializer (and its subobjects) is + /// sufficient for initializing the entity, and perform lifetime extension + /// (when permitted) if not. + void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init); - bool isAbstractType(SourceLocation Loc, QualType T); - bool RequireNonAbstractType(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser); - template - bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID, - const Ts &...Args) { - BoundTypeDiagnoser Diagnoser(DiagID, Args...); - return RequireNonAbstractType(Loc, T, Diagnoser); - } + MaterializeTemporaryExpr * + CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, + bool BoundToLvalueReference); - void DiagnoseAbstractType(const CXXRecordDecl *RD); + /// If \p E is a prvalue denoting an unmaterialized temporary, materialize + /// it as an xvalue. In C++98, the result will still be a prvalue, because + /// we don't have xvalues there. + ExprResult TemporaryMaterializationConversion(Expr *E); - //===--------------------------------------------------------------------===// - // C++ Overloaded Operators [C++ 13.5] - // + ExprResult PerformQualificationConversion( + Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue, + CheckedConversionKind CCK = CCK_ImplicitConversion); - bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl); + bool CanPerformCopyInitialization(const InitializedEntity &Entity, + ExprResult Init); + ExprResult PerformCopyInitialization(const InitializedEntity &Entity, + SourceLocation EqualLoc, ExprResult Init, + bool TopLevelOfInitList = false, + bool AllowExplicit = false); - bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl); + QualType DeduceTemplateSpecializationFromInitializer( + TypeSourceInfo *TInfo, const InitializedEntity &Entity, + const InitializationKind &Kind, MultiExprArg Init); + + ///@} - //===--------------------------------------------------------------------===// - // C++ Templates [C++ 14] // - void FilterAcceptableTemplateNames(LookupResult &R, - bool AllowFunctionTemplates = true, - bool AllowDependent = true); - bool hasAnyAcceptableTemplateNames(LookupResult &R, - bool AllowFunctionTemplates = true, - bool AllowDependent = true, - bool AllowNonTemplateFunctions = false); - /// Try to interpret the lookup result D as a template-name. - /// - /// \param D A declaration found by name lookup. - /// \param AllowFunctionTemplates Whether function templates should be - /// considered valid results. - /// \param AllowDependent Whether unresolved using declarations (that might - /// name templates) should be considered valid results. - static NamedDecl *getAsTemplateNameDecl(NamedDecl *D, - bool AllowFunctionTemplates = true, - bool AllowDependent = true); + // + // ------------------------------------------------------------------------- + // + // - enum TemplateNameIsRequiredTag { TemplateNameIsRequired }; - /// Whether and why a template name is required in this lookup. - class RequiredTemplateKind { - public: - /// Template name is required if TemplateKWLoc is valid. - RequiredTemplateKind(SourceLocation TemplateKWLoc = SourceLocation()) - : TemplateKW(TemplateKWLoc) {} - /// Template name is unconditionally required. - RequiredTemplateKind(TemplateNameIsRequiredTag) {} + /// \name C++ Lambda Expressions + /// Implementations are in SemaLambda.cpp + ///@{ - SourceLocation getTemplateKeywordLoc() const { - return TemplateKW.value_or(SourceLocation()); - } - bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - bool isRequired() const { return TemplateKW != SourceLocation(); } - explicit operator bool() const { return isRequired(); } +public: + /// Create a new lambda closure type. + CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, + TypeSourceInfo *Info, + unsigned LambdaDependencyKind, + LambdaCaptureDefault CaptureDefault); - private: - std::optional TemplateKW; - }; + /// Number lambda for linkage purposes if necessary. + void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method, + std::optional + NumberingOverride = std::nullopt); - enum class AssumedTemplateKind { - /// This is not assumed to be a template name. - None, - /// This is assumed to be a template name because lookup found nothing. - FoundNothing, - /// This is assumed to be a template name because lookup found one or more - /// functions (but no function templates). - FoundFunctions, - }; - bool LookupTemplateName( - LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType, - bool EnteringContext, bool &MemberOfUnknownSpecialization, - RequiredTemplateKind RequiredTemplate = SourceLocation(), - AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true); - - TemplateNameKind isTemplateName(Scope *S, - CXXScopeSpec &SS, - bool hasTemplateKeyword, - const UnqualifiedId &Name, - ParsedType ObjectType, - bool EnteringContext, - TemplateTy &Template, - bool &MemberOfUnknownSpecialization, - bool Disambiguation = false); + /// Endow the lambda scope info with the relevant properties. + void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator, + SourceRange IntroducerRange, + LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, bool ExplicitParams, + bool Mutable); - /// Try to resolve an undeclared template name as a type template. - /// - /// Sets II to the identifier corresponding to the template name, and updates - /// Name to a corresponding (typo-corrected) type template name and TNK to - /// the corresponding kind, if possible. - void ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &Name, - TemplateNameKind &TNK, - SourceLocation NameLoc, - IdentifierInfo *&II); + CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange, + CXXRecordDecl *Class); - bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name, - SourceLocation NameLoc, - bool Diagnose = true); + void AddTemplateParametersToLambdaCallOperator( + CXXMethodDecl *CallOperator, CXXRecordDecl *Class, + TemplateParameterList *TemplateParams); - /// Determine whether a particular identifier might be the name in a C++1z - /// deduction-guide declaration. - bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name, - SourceLocation NameLoc, CXXScopeSpec &SS, - ParsedTemplateTy *Template = nullptr); + void CompleteLambdaCallOperator( + CXXMethodDecl *Method, SourceLocation LambdaLoc, + SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause, + TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind, + StorageClass SC, ArrayRef Params, + bool HasExplicitResultType); - bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, - SourceLocation IILoc, - Scope *S, - const CXXScopeSpec *SS, - TemplateTy &SuggestedTemplate, - TemplateNameKind &SuggestedKind); + void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method); - bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, - NamedDecl *Instantiation, - bool InstantiatedFromMember, - const NamedDecl *Pattern, - const NamedDecl *PatternDef, - TemplateSpecializationKind TSK, - bool Complain = true); + /// Perform initialization analysis of the init-capture and perform + /// any implicit conversions such as an lvalue-to-rvalue conversion if + /// not being used to initialize a reference. + ParsedType actOnLambdaInitCaptureInitialization( + SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc, + IdentifierInfo *Id, LambdaCaptureInitKind InitKind, Expr *&Init) { + return ParsedType::make(buildLambdaInitCaptureInitialization( + Loc, ByRef, EllipsisLoc, std::nullopt, Id, + InitKind != LambdaCaptureInitKind::CopyInit, Init)); + } + QualType buildLambdaInitCaptureInitialization( + SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc, + std::optional NumExpansions, IdentifierInfo *Id, + bool DirectInit, Expr *&Init); - /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining - /// that the template parameter 'PrevDecl' is being shadowed by a new - /// declaration at location Loc. Returns true to indicate that this is - /// an error, and false otherwise. - /// - /// \param Loc The location of the declaration that shadows a template - /// parameter. - /// - /// \param PrevDecl The template parameter that the declaration shadows. + /// Create a dummy variable within the declcontext of the lambda's + /// call operator, for name lookup purposes for a lambda init capture. /// - /// \param SupportedForCompatibility Whether to issue the diagnostic as - /// a warning for compatibility with older versions of clang. - /// Ignored when MSVC compatibility is enabled. - void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl, - bool SupportedForCompatibility = false); - TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); - - NamedDecl *ActOnTypeParameter(Scope *S, bool Typename, - SourceLocation EllipsisLoc, - SourceLocation KeyLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, - unsigned Depth, unsigned Position, - SourceLocation EqualLoc, - ParsedType DefaultArg, bool HasTypeConstraint); + /// CodeGen handles emission of lambda captures, ignoring these dummy + /// variables appropriately. + VarDecl *createLambdaInitCaptureVarDecl( + SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc, + IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx); - bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint); + /// Add an init-capture to a lambda scope. + void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef); - bool ActOnTypeConstraint(const CXXScopeSpec &SS, - TemplateIdAnnotation *TypeConstraint, - TemplateTypeParmDecl *ConstrainedParameter, - SourceLocation EllipsisLoc); - bool BuildTypeConstraint(const CXXScopeSpec &SS, - TemplateIdAnnotation *TypeConstraint, - TemplateTypeParmDecl *ConstrainedParameter, - SourceLocation EllipsisLoc, - bool AllowUnexpandedPack); + /// Note that we have finished the explicit captures for the + /// given lambda. + void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); - bool AttachTypeConstraint(NestedNameSpecifierLoc NS, - DeclarationNameInfo NameInfo, - ConceptDecl *NamedConcept, - const TemplateArgumentListInfo *TemplateArgs, - TemplateTypeParmDecl *ConstrainedParameter, - SourceLocation EllipsisLoc); + /// Deduce a block or lambda's return type based on the return + /// statements present in the body. + void deduceClosureReturnType(sema::CapturingScopeInfo &CSI); - bool AttachTypeConstraint(AutoTypeLoc TL, - NonTypeTemplateParmDecl *NewConstrainedParm, - NonTypeTemplateParmDecl *OrigConstrainedParm, - SourceLocation EllipsisLoc); + /// Once the Lambdas capture are known, we can start to create the closure, + /// call operator method, and keep track of the captures. + /// We do the capture lookup here, but they are not actually captured until + /// after we know what the qualifiers of the call operator are. + void ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, + Scope *CurContext); - bool RequireStructuralType(QualType T, SourceLocation Loc); + /// This is called after parsing the explicit template parameter list + /// on a lambda (if it exists) in C++2a. + void ActOnLambdaExplicitTemplateParameterList(LambdaIntroducer &Intro, + SourceLocation LAngleLoc, + ArrayRef TParams, + SourceLocation RAngleLoc, + ExprResult RequiresClause); - QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, - SourceLocation Loc); - QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc); + void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro, + SourceLocation MutableLoc); - NamedDecl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, - unsigned Depth, - unsigned Position, - SourceLocation EqualLoc, - Expr *DefaultArg); - NamedDecl *ActOnTemplateTemplateParameter(Scope *S, - SourceLocation TmpLoc, - TemplateParameterList *Params, - SourceLocation EllipsisLoc, - IdentifierInfo *ParamName, - SourceLocation ParamNameLoc, - unsigned Depth, - unsigned Position, - SourceLocation EqualLoc, - ParsedTemplateArgument DefaultArg); + void ActOnLambdaClosureParameters( + Scope *LambdaScope, + MutableArrayRef ParamInfo); - TemplateParameterList * - ActOnTemplateParameterList(unsigned Depth, - SourceLocation ExportLoc, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ArrayRef Params, - SourceLocation RAngleLoc, - Expr *RequiresClause); + /// ActOnStartOfLambdaDefinition - This is called just before we start + /// parsing the body of a lambda; it analyzes the explicit captures and + /// arguments, and sets up various data-structures for the body of the + /// lambda. + void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, + Declarator &ParamInfo, const DeclSpec &DS); - /// The context in which we are checking a template parameter list. - enum TemplateParamListContext { - TPC_ClassTemplate, - TPC_VarTemplate, - TPC_FunctionTemplate, - TPC_ClassTemplateMember, - TPC_FriendClassTemplate, - TPC_FriendFunctionTemplate, - TPC_FriendFunctionTemplateDefinition, - TPC_TypeAliasTemplate - }; + /// ActOnLambdaError - If there is an error parsing a lambda, this callback + /// is invoked to pop the information about the lambda. + void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, + bool IsInstantiation = false); - bool CheckTemplateParameterList(TemplateParameterList *NewParams, - TemplateParameterList *OldParams, - TemplateParamListContext TPC, - SkipBodyInfo *SkipBody = nullptr); - TemplateParameterList *MatchTemplateParametersToScopeSpecifier( - SourceLocation DeclStartLoc, SourceLocation DeclLoc, - const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId, - ArrayRef ParamLists, - bool IsFriend, bool &IsMemberSpecialization, bool &Invalid, - bool SuppressDiagnostic = false); + /// ActOnLambdaExpr - This is called when the body of a lambda expression + /// was successfully completed. + ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body); - DeclResult CheckClassTemplate( - Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, - CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS, SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, - TemplateParameterList **OuterTemplateParamLists, - SkipBodyInfo *SkipBody = nullptr); + /// Does copying/destroying the captured variable have side effects? + bool CaptureHasSideEffects(const sema::Capture &From); - TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, - QualType NTTPType, - SourceLocation Loc); + /// Diagnose if an explicit lambda capture is unused. Returns true if a + /// diagnostic is emitted. + bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, + const sema::Capture &From); - /// Get a template argument mapping the given template parameter to itself, - /// e.g. for X in \c template, this would return an expression template - /// argument referencing X. - TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, - SourceLocation Location); + /// Build a FieldDecl suitable to hold the given capture. + FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture); - void translateTemplateArguments(const ASTTemplateArgsPtr &In, - TemplateArgumentListInfo &Out); + /// Initialize the given capture with a suitable expression. + ExprResult BuildCaptureInit(const sema::Capture &Capture, + SourceLocation ImplicitCaptureLoc, + bool IsOpenMPMapping = false); - ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType); + /// Complete a lambda-expression having processed and attached the + /// lambda body. + ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, + sema::LambdaScopeInfo *LSI); - void NoteAllFoundTemplates(TemplateName Name); + /// Get the return type to use for a lambda's conversion function(s) to + /// function pointer type, given the type of the call operator. + QualType + getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType, + CallingConv CC); - QualType CheckTemplateIdType(TemplateName Template, - SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs); + ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation, + SourceLocation ConvLocation, + CXXConversionDecl *Conv, Expr *Src); - TypeResult - ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - TemplateTy Template, IdentifierInfo *TemplateII, - SourceLocation TemplateIILoc, SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc, - bool IsCtorOrDtorName = false, bool IsClassName = false, - ImplicitTypenameContext AllowImplicitTypename = - ImplicitTypenameContext::No); + class LambdaScopeForCallOperatorInstantiationRAII + : private FunctionScopeRAII { + public: + LambdaScopeForCallOperatorInstantiationRAII( + Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, + LocalInstantiationScope &Scope, + bool ShouldAddDeclsFromParentScope = true); + }; - /// Parsed an elaborated-type-specifier that refers to a template-id, - /// such as \c class T::template apply. - TypeResult ActOnTagTemplateIdType(TagUseKind TUK, - TypeSpecifierType TagSpec, - SourceLocation TagLoc, - CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - TemplateTy TemplateD, - SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc); - - DeclResult ActOnVarTemplateSpecialization( - Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous, - SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, - StorageClass SC, bool IsPartialSpecialization); - - /// Get the specialization of the given variable template corresponding to - /// the specified argument list, or a null-but-valid result if the arguments - /// are dependent. - DeclResult CheckVarTemplateId(VarTemplateDecl *Template, - SourceLocation TemplateLoc, - SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs); - - /// Form a reference to the specialization of the given variable template - /// corresponding to the specified argument list, or a null-but-valid result - /// if the arguments are dependent. - ExprResult CheckVarTemplateId(const CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - VarTemplateDecl *Template, NamedDecl *FoundD, - SourceLocation TemplateLoc, - const TemplateArgumentListInfo *TemplateArgs); + /// Compute the mangling number context for a lambda expression or + /// block literal. Also return the extra mangling decl if any. + /// + /// \param DC - The DeclContext containing the lambda expression or + /// block literal. + std::tuple + getCurrentMangleNumberContext(const DeclContext *DC); - ExprResult - CheckConceptTemplateId(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const TemplateArgumentListInfo *TemplateArgs); + ///@} - void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc); + // + // + // ------------------------------------------------------------------------- + // + // - ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - LookupResult &R, - bool RequiresADL, - const TemplateArgumentListInfo *TemplateArgs); + /// \name Name Lookup + /// + /// These routines provide name lookup that is used during semantic + /// analysis to resolve the various kinds of names (identifiers, + /// overloaded operator names, constructor names, etc.) into zero or + /// more declarations within a particular scope. The major entry + /// points are LookupName, which performs unqualified name lookup, + /// and LookupQualifiedName, which performs qualified name lookup. + /// + /// All name lookup is performed based on some specific criteria, + /// which specify what names will be visible to name lookup and how + /// far name lookup should work. These criteria are important both + /// for capturing language semantics (certain lookups will ignore + /// certain names, for example) and for performance, since name + /// lookup is often a bottleneck in the compilation of C++. Name + /// lookup criteria is specified via the LookupCriteria enumeration. + /// + /// The results of name lookup can vary based on the kind of name + /// lookup performed, the current language, and the translation + /// unit. In C, for example, name lookup will either return nothing + /// (no entity found) or a single declaration. In C++, name lookup + /// can additionally refer to a set of overloaded functions or + /// result in an ambiguity. All of the possible results of name + /// lookup are captured by the LookupResult class, which provides + /// the ability to distinguish among them. + /// + /// Implementations are in SemaLookup.cpp + ///@{ - ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); +public: + /// Tracks whether we are in a context where typo correction is + /// disabled. + bool DisableTypoCorrection; - TemplateNameKind ActOnTemplateName( - Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, - TemplateTy &Template, bool AllowInjectedClassName = false); + /// The number of typos corrected by CorrectTypo. + unsigned TyposCorrected; - DeclResult ActOnClassTemplateSpecialization( - Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, CXXScopeSpec &SS, - TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr, - MultiTemplateParamsArg TemplateParameterLists, - SkipBodyInfo *SkipBody = nullptr); + typedef llvm::SmallSet SrcLocSet; + typedef llvm::DenseMap IdentifierSourceLocations; - bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, - TemplateDecl *PrimaryTemplate, - unsigned NumExplicitArgs, - ArrayRef Args); - void CheckTemplatePartialSpecialization( - ClassTemplatePartialSpecializationDecl *Partial); - void CheckTemplatePartialSpecialization( - VarTemplatePartialSpecializationDecl *Partial); + /// A cache containing identifiers for which typo correction failed and + /// their locations, so that repeated attempts to correct an identifier in a + /// given location are ignored if typo correction already failed for it. + IdentifierSourceLocations TypoCorrectionFailures; - Decl *ActOnTemplateDeclarator(Scope *S, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D); + /// SpecialMemberOverloadResult - The overloading result for a special member + /// function. + /// + /// This is basically a wrapper around PointerIntPair. The lowest bits of the + /// integer are used to determine whether overload resolution succeeded. + class SpecialMemberOverloadResult { + public: + enum Kind { NoMemberOrDeleted, Ambiguous, Success }; - bool - CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, - TemplateSpecializationKind NewTSK, - NamedDecl *PrevDecl, - TemplateSpecializationKind PrevTSK, - SourceLocation PrevPtOfInstantiation, - bool &SuppressNew); + private: + llvm::PointerIntPair Pair; - bool CheckDependentFunctionTemplateSpecialization( - FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs, - LookupResult &Previous); + public: + SpecialMemberOverloadResult() {} + SpecialMemberOverloadResult(CXXMethodDecl *MD) + : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {} - bool CheckFunctionTemplateSpecialization( - FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, - LookupResult &Previous, bool QualifiedFriend = false); - bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); - void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); + CXXMethodDecl *getMethod() const { return Pair.getPointer(); } + void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); } - DeclResult ActOnExplicitInstantiation( - Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, - unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, - TemplateTy Template, SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, const ParsedAttributesView &Attr); + Kind getKind() const { return static_cast(Pair.getInt()); } + void setKind(Kind K) { Pair.setInt(K); } + }; - DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, SourceLocation KWLoc, - CXXScopeSpec &SS, IdentifierInfo *Name, - SourceLocation NameLoc, - const ParsedAttributesView &Attr); + class SpecialMemberOverloadResultEntry : public llvm::FastFoldingSetNode, + public SpecialMemberOverloadResult { + public: + SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID) + : FastFoldingSetNode(ID) {} + }; - DeclResult ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - Declarator &D); + /// A cache of special member function overload resolution results + /// for C++ records. + llvm::FoldingSet SpecialMemberCache; - TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable( - TemplateDecl *Template, SourceLocation TemplateLoc, - SourceLocation RAngleLoc, Decl *Param, - ArrayRef SugaredConverted, - ArrayRef CanonicalConverted, bool &HasDefaultArg); + /// Holds TypoExprs that are created from `createDelayedTypo`. This is used by + /// `TransformTypos` in order to keep track of any TypoExprs that are created + /// recursively during typo correction and wipe them away if the correction + /// fails. + llvm::SmallVector TypoExprs; - SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const; + enum class AcceptableKind { Visible, Reachable }; - /// Specifies the context in which a particular template - /// argument is being checked. - enum CheckTemplateArgumentKind { - /// The template argument was specified in the code or was - /// instantiated with some deduced template arguments. - CTAK_Specified, + // Members have to be NamespaceDecl* or TranslationUnitDecl*. + // TODO: make this is a typesafe union. + typedef llvm::SmallSetVector AssociatedNamespaceSet; + typedef llvm::SmallSetVector AssociatedClassSet; - /// The template argument was deduced via template argument - /// deduction. - CTAK_Deduced, + /// Describes the kind of name lookup to perform. + enum LookupNameKind { + /// Ordinary name lookup, which finds ordinary names (functions, + /// variables, typedefs, etc.) in C and most kinds of names + /// (functions, variables, members, types, etc.) in C++. + LookupOrdinaryName = 0, + /// Tag name lookup, which finds the names of enums, classes, + /// structs, and unions. + LookupTagName, + /// Label name lookup. + LookupLabel, + /// Member name lookup, which finds the names of + /// class/struct/union members. + LookupMemberName, + /// Look up of an operator name (e.g., operator+) for use with + /// operator overloading. This lookup is similar to ordinary name + /// lookup, but will ignore any declarations that are class members. + LookupOperatorName, + /// Look up a name following ~ in a destructor name. This is an ordinary + /// lookup, but prefers tags to typedefs. + LookupDestructorName, + /// Look up of a name that precedes the '::' scope resolution + /// operator in C++. This lookup completely ignores operator, object, + /// function, and enumerator names (C++ [basic.lookup.qual]p1). + LookupNestedNameSpecifierName, + /// Look up a namespace name within a C++ using directive or + /// namespace alias definition, ignoring non-namespace names (C++ + /// [basic.lookup.udir]p1). + LookupNamespaceName, + /// Look up all declarations in a scope with the given name, + /// including resolved using declarations. This is appropriate + /// for checking redeclarations for a using declaration. + LookupUsingDeclName, + /// Look up an ordinary name that is going to be redeclared as a + /// name with linkage. This lookup ignores any declarations that + /// are outside of the current scope unless they have linkage. See + /// C99 6.2.2p4-5 and C++ [basic.link]p6. + LookupRedeclarationWithLinkage, + /// Look up a friend of a local class. This lookup does not look + /// outside the innermost non-class scope. See C++11 [class.friend]p11. + LookupLocalFriendName, + /// Look up the name of an Objective-C protocol. + LookupObjCProtocolName, + /// Look up implicit 'self' parameter of an objective-c method. + LookupObjCImplicitSelfParam, + /// Look up the name of an OpenMP user-defined reduction operation. + LookupOMPReductionName, + /// Look up the name of an OpenMP user-defined mapper. + LookupOMPMapperName, + /// Look up any declaration with any name. + LookupAnyName + }; - /// The template argument was deduced from an array bound - /// via template argument deduction. - CTAK_DeducedFromArrayBound + /// The possible outcomes of name lookup for a literal operator. + enum LiteralOperatorLookupResult { + /// The lookup resulted in an error. + LOLR_Error, + /// The lookup found no match but no diagnostic was issued. + LOLR_ErrorNoDiagnostic, + /// The lookup found a single 'cooked' literal operator, which + /// expects a normal literal to be built and passed to it. + LOLR_Cooked, + /// The lookup found a single 'raw' literal operator, which expects + /// a string literal containing the spelling of the literal token. + LOLR_Raw, + /// The lookup found an overload set of literal operator templates, + /// which expect the characters of the spelling of the literal token to be + /// passed as a non-type template argument pack. + LOLR_Template, + /// The lookup found an overload set of literal operator templates, + /// which expect the character type and characters of the spelling of the + /// string literal token to be passed as template arguments. + LOLR_StringTemplatePack, }; - bool - CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg, - NamedDecl *Template, SourceLocation TemplateLoc, - SourceLocation RAngleLoc, unsigned ArgumentPackIndex, - SmallVectorImpl &SugaredConverted, - SmallVectorImpl &CanonicalConverted, - CheckTemplateArgumentKind CTAK); + SpecialMemberOverloadResult + LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg, + bool VolatileArg, bool RValueThis, bool ConstThis, + bool VolatileThis); - /// Check that the given template arguments can be provided to - /// the given template, converting the arguments along the way. - /// - /// \param Template The template to which the template arguments are being - /// provided. - /// - /// \param TemplateLoc The location of the template name in the source. - /// - /// \param TemplateArgs The list of template arguments. If the template is - /// a template template parameter, this function may extend the set of - /// template arguments to also include substituted, defaulted template - /// arguments. - /// - /// \param PartialTemplateArgs True if the list of template arguments is - /// intentionally partial, e.g., because we're checking just the initial - /// set of template arguments. - /// - /// \param Converted Will receive the converted, canonicalized template - /// arguments. - /// - /// \param UpdateArgsWithConversions If \c true, update \p TemplateArgs to - /// contain the converted forms of the template arguments as written. - /// Otherwise, \p TemplateArgs will not be modified. - /// - /// \param ConstraintsNotSatisfied If provided, and an error occurred, will - /// receive true if the cause for the error is the associated constraints of - /// the template not being satisfied by the template arguments. - /// - /// \returns true if an error occurred, false otherwise. - bool CheckTemplateArgumentList( - TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl &SugaredConverted, - SmallVectorImpl &CanonicalConverted, - bool UpdateArgsWithConversions = true, - bool *ConstraintsNotSatisfied = nullptr); + typedef std::function TypoDiagnosticGenerator; + typedef std::function + TypoRecoveryCallback; - bool CheckTemplateTypeArgument( - TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, - SmallVectorImpl &SugaredConverted, - SmallVectorImpl &CanonicalConverted); + /// Specifies whether (or how) name lookup is being performed for a + /// redeclaration (vs. a reference). + enum RedeclarationKind { + /// The lookup is a reference to this name that is not for the + /// purpose of redeclaring the name. + NotForRedeclaration = 0, + /// The lookup results will be used for redeclaration of a name, + /// if an entity by that name already exists and is visible. + ForVisibleRedeclaration, + /// The lookup results will be used for redeclaration of a name + /// with external linkage; non-visible lookup results with external linkage + /// may also be found. + ForExternalRedeclaration + }; - bool CheckTemplateArgument(TypeSourceInfo *Arg); - ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param, - QualType InstantiatedParamType, Expr *Arg, - TemplateArgument &SugaredConverted, - TemplateArgument &CanonicalConverted, - CheckTemplateArgumentKind CTAK); - bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, - TemplateParameterList *Params, - TemplateArgumentLoc &Arg); + RedeclarationKind forRedeclarationInCurContext() const { + // A declaration with an owning module for linkage can never link against + // anything that is not visible. We don't need to check linkage here; if + // the context has internal linkage, redeclaration lookup won't find things + // from other TUs, and we can't safely compute linkage yet in general. + if (cast(CurContext) + ->getOwningModuleForLinkage(/*IgnoreLinkage*/ true)) + return ForVisibleRedeclaration; + return ForExternalRedeclaration; + } - void NoteTemplateLocation(const NamedDecl &Decl, - std::optional ParamRange = {}); - void NoteTemplateParameterLocation(const NamedDecl &Decl); + /// Look up a name, looking for a single declaration. Return + /// null if the results were absent, ambiguous, or overloaded. + /// + /// It is preferable to use the elaborated form and explicitly handle + /// ambiguity and overloaded. + NamedDecl *LookupSingleName(Scope *S, DeclarationName Name, + SourceLocation Loc, LookupNameKind NameKind, + RedeclarationKind Redecl = NotForRedeclaration); + bool LookupBuiltin(LookupResult &R); + void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID); + bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false, + bool ForceNoCPlusPlus = false); + bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + bool InUnqualifiedLookup = false); + bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + CXXScopeSpec &SS); + bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, + bool AllowBuiltinCreation = false, + bool EnteringContext = false); + ObjCProtocolDecl * + LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, + RedeclarationKind Redecl = NotForRedeclaration); + bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class); - ExprResult - BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, - QualType ParamType, - SourceLocation Loc); - ExprResult - BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, - SourceLocation Loc); + void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, + UnresolvedSetImpl &Functions); - /// Enumeration describing how template parameter lists are compared - /// for equality. - enum TemplateParameterListEqualKind { - /// We are matching the template parameter lists of two templates - /// that might be redeclarations. - /// - /// \code - /// template struct X; - /// template struct X; - /// \endcode - TPL_TemplateMatch, + LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, + SourceLocation GnuLabelLoc = SourceLocation()); - /// We are matching the template parameter lists of two template - /// template parameters as part of matching the template parameter lists - /// of two templates that might be redeclarations. - /// - /// \code - /// template class TT> struct X; - /// template class Other> struct X; - /// \endcode - TPL_TemplateTemplateParmMatch, + DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); + CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class); + CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class, + unsigned Quals); + CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals, + bool RValueThis, unsigned ThisQuals); + CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class, + unsigned Quals); + CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals, + bool RValueThis, unsigned ThisQuals); + CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); - /// We are matching the template parameter lists of a template - /// template argument against the template parameter lists of a template - /// template parameter. - /// - /// \code - /// template class Metafun> struct X; - /// template struct integer_c; - /// X xic; - /// \endcode - TPL_TemplateTemplateArgumentMatch, + /// Force the declaration of any implicitly-declared members of this + /// class. + void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class); - /// We are determining whether the template-parameters are equivalent - /// according to C++ [temp.over.link]/6. This comparison does not consider - /// constraints. - /// - /// \code - /// template void f(T); - /// template void f(T); - /// \endcode - TPL_TemplateParamsEquivalent, - }; + /// Make a merged definition of an existing hidden definition \p ND + /// visible at the specified location. + void makeMergedDefinitionVisible(NamedDecl *ND); - // A struct to represent the 'new' declaration, which is either itself just - // the named decl, or the important information we need about it in order to - // do constraint comparisons. - class TemplateCompareNewDeclInfo { - const NamedDecl *ND = nullptr; - const DeclContext *DC = nullptr; - const DeclContext *LexicalDC = nullptr; - SourceLocation Loc; + /// Get the set of additional modules that should be checked during + /// name lookup. A module and its imports become visible when instanting a + /// template defined within it. + llvm::DenseSet &getLookupModules(); - public: - TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {} - TemplateCompareNewDeclInfo(const DeclContext *DeclCtx, - const DeclContext *LexicalDeclCtx, - SourceLocation Loc) + bool hasVisibleMergedDefinition(const NamedDecl *Def); + bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def); - : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) { - assert(DC && LexicalDC && - "Constructor only for cases where we have the information to put " - "in here"); - } + /// Determine if the template parameter \p D has a visible default argument. + bool + hasVisibleDefaultArgument(const NamedDecl *D, + llvm::SmallVectorImpl *Modules = nullptr); + /// Determine if the template parameter \p D has a reachable default argument. + bool hasReachableDefaultArgument( + const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); + /// Determine if the template parameter \p D has a reachable default argument. + bool hasAcceptableDefaultArgument(const NamedDecl *D, + llvm::SmallVectorImpl *Modules, + Sema::AcceptableKind Kind); - // If this was constructed with no information, we cannot do substitution - // for constraint comparison, so make sure we can check that. - bool isInvalid() const { return !ND && !DC; } + /// Determine if there is a visible declaration of \p D that is an explicit + /// specialization declaration for a specialization of a template. (For a + /// member specialization, use hasVisibleMemberSpecialization.) + bool hasVisibleExplicitSpecialization( + const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); + /// Determine if there is a reachable declaration of \p D that is an explicit + /// specialization declaration for a specialization of a template. (For a + /// member specialization, use hasReachableMemberSpecialization.) + bool hasReachableExplicitSpecialization( + const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); - const NamedDecl *getDecl() const { return ND; } + /// Determine if there is a visible declaration of \p D that is a member + /// specialization declaration (as opposed to an instantiated declaration). + bool hasVisibleMemberSpecialization( + const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); + /// Determine if there is a reachable declaration of \p D that is a member + /// specialization declaration (as opposed to an instantiated declaration). + bool hasReachableMemberSpecialization( + const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); - bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; } + bool isModuleVisible(const Module *M, bool ModulePrivate = false); - const DeclContext *getLexicalDeclContext() const { - return ND ? ND->getLexicalDeclContext() : LexicalDC; - } + /// Determine whether any declaration of an entity is visible. + bool + hasVisibleDeclaration(const NamedDecl *D, + llvm::SmallVectorImpl *Modules = nullptr) { + return isVisible(D) || hasVisibleDeclarationSlow(D, Modules); + } - const DeclContext *getDeclContext() const { - return ND ? ND->getDeclContext() : DC; - } + bool hasVisibleDeclarationSlow(const NamedDecl *D, + llvm::SmallVectorImpl *Modules); + /// Determine whether any declaration of an entity is reachable. + bool + hasReachableDeclaration(const NamedDecl *D, + llvm::SmallVectorImpl *Modules = nullptr) { + return isReachable(D) || hasReachableDeclarationSlow(D, Modules); + } + bool hasReachableDeclarationSlow( + const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr); - SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; } - }; + void diagnoseTypo(const TypoCorrection &Correction, + const PartialDiagnostic &TypoDiag, + bool ErrorRecovery = true); - bool TemplateParameterListsAreEqual( - const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New, - const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, - TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc = SourceLocation()); + void diagnoseTypo(const TypoCorrection &Correction, + const PartialDiagnostic &TypoDiag, + const PartialDiagnostic &PrevNote, + bool ErrorRecovery = true); - bool TemplateParameterListsAreEqual( - TemplateParameterList *New, TemplateParameterList *Old, bool Complain, - TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc = SourceLocation()) { - return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain, - Kind, TemplateArgLoc); - } - - // Calculates whether two constraint expressions are equal irrespective of a - // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and - // 'New', which are the "source" of the constraint, since this is necessary - // for figuring out the relative 'depth' of the constraint. The depth of the - // 'primary template' and the 'instantiated from' templates aren't necessarily - // the same, such as a case when one is a 'friend' defined in a class. - bool AreConstraintExpressionsEqual(const NamedDecl *Old, - const Expr *OldConstr, - const TemplateCompareNewDeclInfo &New, - const Expr *NewConstr); + void FindAssociatedClassesAndNamespaces( + SourceLocation InstantiationLoc, ArrayRef Args, + AssociatedNamespaceSet &AssociatedNamespaces, + AssociatedClassSet &AssociatedClasses); - bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); + void DiagnoseAmbiguousLookup(LookupResult &Result); - /// Called when the parser has parsed a C++ typename - /// specifier, e.g., "typename T::type". - /// - /// \param S The scope in which this typename type occurs. - /// \param TypenameLoc the location of the 'typename' keyword - /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). - /// \param II the identifier we're retrieving (e.g., 'type' in the example). - /// \param IdLoc the location of the identifier. - /// \param IsImplicitTypename context where T::type refers to a type. - TypeResult ActOnTypenameType( - Scope *S, SourceLocation TypenameLoc, const CXXScopeSpec &SS, - const IdentifierInfo &II, SourceLocation IdLoc, - ImplicitTypenameContext IsImplicitTypename = ImplicitTypenameContext::No); + LiteralOperatorLookupResult + LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys, + bool AllowRaw, bool AllowTemplate, + bool AllowStringTemplate, bool DiagnoseMissing, + StringLiteral *StringLit = nullptr); - /// Called when the parser has parsed a C++ typename - /// specifier that ends in a template-id, e.g., - /// "typename MetaFun::template apply". - /// - /// \param S The scope in which this typename type occurs. - /// \param TypenameLoc the location of the 'typename' keyword - /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). - /// \param TemplateLoc the location of the 'template' keyword, if any. - /// \param TemplateName The template name. - /// \param TemplateII The identifier used to name the template. - /// \param TemplateIILoc The location of the template name. - /// \param LAngleLoc The location of the opening angle bracket ('<'). - /// \param TemplateArgs The template arguments. - /// \param RAngleLoc The location of the closing angle bracket ('>'). - TypeResult - ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, - SourceLocation TemplateLoc, - TemplateTy TemplateName, - IdentifierInfo *TemplateII, - SourceLocation TemplateIILoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc); + void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc, + ArrayRef Args, ADLResult &Functions); - QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, - SourceLocation KeywordLoc, - NestedNameSpecifierLoc QualifierLoc, - const IdentifierInfo &II, - SourceLocation IILoc, - TypeSourceInfo **TSI, - bool DeducedTSTContext); + void LookupVisibleDecls(Scope *S, LookupNameKind Kind, + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope = true, + bool LoadExternal = true); + void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope = true, + bool IncludeDependentBases = false, + bool LoadExternal = true); - QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, - SourceLocation KeywordLoc, - NestedNameSpecifierLoc QualifierLoc, - const IdentifierInfo &II, - SourceLocation IILoc, - bool DeducedTSTContext = true); + enum CorrectTypoKind { + CTK_NonError, // CorrectTypo used in a non error recovery situation. + CTK_ErrorRecovery // CorrectTypo used in normal error recovery. + }; + TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, + Sema::LookupNameKind LookupKind, Scope *S, + CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, + CorrectTypoKind Mode, + DeclContext *MemberContext = nullptr, + bool EnteringContext = false, + const ObjCObjectPointerType *OPT = nullptr, + bool RecordFailure = true); - TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, - SourceLocation Loc, - DeclarationName Name); - bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS); + TypoExpr *CorrectTypoDelayed( + const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, + Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, + TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC, + CorrectTypoKind Mode, DeclContext *MemberContext = nullptr, + bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr); - ExprResult RebuildExprInCurrentInstantiation(Expr *E); - bool RebuildTemplateParamsInCurrentInstantiation( - TemplateParameterList *Params); + /// Kinds of missing import. Note, the values of these enumerators correspond + /// to %select values in diagnostics. + enum class MissingImportKind { + Declaration, + Definition, + DefaultArgument, + ExplicitSpecialization, + PartialSpecialization + }; - std::string - getTemplateArgumentBindingsText(const TemplateParameterList *Params, - const TemplateArgumentList &Args); + /// Diagnose that the specified declaration needs to be visible but + /// isn't, and suggest a module import that would resolve the problem. + void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl, + MissingImportKind MIK, bool Recover = true); + void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl, + SourceLocation DeclLoc, ArrayRef Modules, + MissingImportKind MIK, bool Recover); - std::string - getTemplateArgumentBindingsText(const TemplateParameterList *Params, - const TemplateArgument *Args, - unsigned NumArgs); + struct TypoExprState { + std::unique_ptr Consumer; + TypoDiagnosticGenerator DiagHandler; + TypoRecoveryCallback RecoveryHandler; + TypoExprState(); + TypoExprState(TypoExprState &&other) noexcept; + TypoExprState &operator=(TypoExprState &&other) noexcept; + }; - //===--------------------------------------------------------------------===// - // C++ Concepts - //===--------------------------------------------------------------------===// - Decl *ActOnConceptDefinition( - Scope *S, MultiTemplateParamsArg TemplateParameterLists, - IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr); + const TypoExprState &getTypoExprState(TypoExpr *TE) const; - void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous, - bool &AddToScope); + /// Clears the state of the given TypoExpr. + void clearDelayedTypo(TypoExpr *TE); - RequiresExprBodyDecl * - ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, - ArrayRef LocalParameters, - Scope *BodyScope); - void ActOnFinishRequiresExpr(); - concepts::Requirement *ActOnSimpleRequirement(Expr *E); - concepts::Requirement *ActOnTypeRequirement( - SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc, - IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId); - concepts::Requirement *ActOnCompoundRequirement(Expr *E, - SourceLocation NoexceptLoc); - concepts::Requirement * - ActOnCompoundRequirement( - Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS, - TemplateIdAnnotation *TypeConstraint, unsigned Depth); - concepts::Requirement *ActOnNestedRequirement(Expr *Constraint); - concepts::ExprRequirement * - BuildExprRequirement( - Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement); - concepts::ExprRequirement * - BuildExprRequirement( - concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag, - bool IsSatisfied, SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement); - concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type); - concepts::TypeRequirement * - BuildTypeRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag); - concepts::NestedRequirement *BuildNestedRequirement(Expr *E); - concepts::NestedRequirement * - BuildNestedRequirement(StringRef InvalidConstraintEntity, - const ASTConstraintSatisfaction &Satisfaction); - ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, - SourceLocation LParenLoc, - ArrayRef LocalParameters, - SourceLocation RParenLoc, - ArrayRef Requirements, - SourceLocation ClosingBraceLoc); + /// Called on #pragma clang __debug dump II + void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II); - //===--------------------------------------------------------------------===// - // C++ Variadic Templates (C++0x [temp.variadic]) - //===--------------------------------------------------------------------===// + /// Called on #pragma clang __debug dump E + void ActOnPragmaDump(Expr *E); - /// Determine whether an unexpanded parameter pack might be permitted in this - /// location. Useful for error recovery. - bool isUnexpandedParameterPackPermitted(); +private: + // The set of known/encountered (unique, canonicalized) NamespaceDecls. + // + // The boolean value will be true to indicate that the namespace was loaded + // from an AST/PCH file, or false otherwise. + llvm::MapVector KnownNamespaces; - /// The context in which an unexpanded parameter pack is - /// being diagnosed. - /// - /// Note that the values of this enumeration line up with the first - /// argument to the \c err_unexpanded_parameter_pack diagnostic. - enum UnexpandedParameterPackContext { - /// An arbitrary expression. - UPPC_Expression = 0, + /// Whether we have already loaded known namespaces from an extenal + /// source. + bool LoadedExternalKnownNamespaces; - /// The base type of a class type. - UPPC_BaseType, + bool CppLookupName(LookupResult &R, Scope *S); - /// The type of an arbitrary declaration. - UPPC_DeclarationType, + bool isUsableModule(const Module *M); - /// The type of a data member. - UPPC_DataMemberType, + /// Helper for CorrectTypo and CorrectTypoDelayed used to create and + /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction + /// should be skipped entirely. + std::unique_ptr makeTypoCorrectionConsumer( + const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, + Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, + DeclContext *MemberContext, bool EnteringContext, + const ObjCObjectPointerType *OPT, bool ErrorRecovery); - /// The size of a bit-field. - UPPC_BitFieldWidth, + /// The set of unhandled TypoExprs and their associated state. + llvm::MapVector DelayedTypos; - /// The expression in a static assertion. - UPPC_StaticAssertExpression, + /// Creates a new TypoExpr AST node. + TypoExpr *createDelayedTypo(std::unique_ptr TCC, + TypoDiagnosticGenerator TDG, + TypoRecoveryCallback TRC, SourceLocation TypoLoc); - /// The fixed underlying type of an enumeration. - UPPC_FixedUnderlyingType, + /// Cache for module units which is usable for current module. + llvm::DenseSet UsableModuleUnitsCache; - /// The enumerator value. - UPPC_EnumeratorValue, + /// Record the typo correction failure and return an empty correction. + TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc, + bool RecordFailure = true) { + if (RecordFailure) + TypoCorrectionFailures[Typo].insert(TypoLoc); + return TypoCorrection(); + } - /// A using declaration. - UPPC_UsingDeclaration, + bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind); - /// A friend declaration. - UPPC_FriendDeclaration, + /// Determine whether two declarations should be linked together, given that + /// the old declaration might not be visible and the new declaration might + /// not have external linkage. + bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old, + const NamedDecl *New) { + if (isVisible(Old)) + return true; + // See comment in below overload for why it's safe to compute the linkage + // of the new declaration here. + if (New->isExternallyDeclarable()) { + assert(Old->isExternallyDeclarable() && + "should not have found a non-externally-declarable previous decl"); + return true; + } + return false; + } + bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New); - /// A declaration qualifier. - UPPC_DeclarationQualifier, + ///@} - /// An initializer. - UPPC_Initializer, + // + // + // ------------------------------------------------------------------------- + // + // - /// A default argument. - UPPC_DefaultArgument, + /// \name Modules + /// Implementations are in SemaModule.cpp + ///@{ - /// The type of a non-type template parameter. - UPPC_NonTypeTemplateParameterType, +public: + /// Get the module unit whose scope we are currently within. + Module *getCurrentModule() const { + return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module; + } - /// The type of an exception. - UPPC_ExceptionType, + /// Is the module scope we are an implementation unit? + bool currentModuleIsImplementation() const { + return ModuleScopes.empty() + ? false + : ModuleScopes.back().Module->isModuleImplementation(); + } - /// Explicit specialization. - UPPC_ExplicitSpecialization, + // When loading a non-modular PCH files, this is used to restore module + // visibility. + void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) { + VisibleModules.setVisible(Mod, ImportLoc); + } - /// Partial specialization. - UPPC_PartialSpecialization, + enum class ModuleDeclKind { + Interface, ///< 'export module X;' + Implementation, ///< 'module X;' + PartitionInterface, ///< 'export module X:Y;' + PartitionImplementation, ///< 'module X:Y;' + }; - /// Microsoft __if_exists. - UPPC_IfExists, + /// An enumeration to represent the transition of states in parsing module + /// fragments and imports. If we are not parsing a C++20 TU, or we find + /// an error in state transition, the state is set to NotACXX20Module. + enum class ModuleImportState { + FirstDecl, ///< Parsing the first decl in a TU. + GlobalFragment, ///< after 'module;' but before 'module X;' + ImportAllowed, ///< after 'module X;' but before any non-import decl. + ImportFinished, ///< after any non-import decl. + PrivateFragmentImportAllowed, ///< after 'module :private;' but before any + ///< non-import decl. + PrivateFragmentImportFinished, ///< after 'module :private;' but a + ///< non-import decl has already been seen. + NotACXX20Module ///< Not a C++20 TU, or an invalid state was found. + }; - /// Microsoft __if_not_exists. - UPPC_IfNotExists, + /// The parser has processed a module-declaration that begins the definition + /// of a module interface or implementation. + DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc, + SourceLocation ModuleLoc, ModuleDeclKind MDK, + ModuleIdPath Path, ModuleIdPath Partition, + ModuleImportState &ImportState); - /// Lambda expression. - UPPC_Lambda, + /// The parser has processed a global-module-fragment declaration that begins + /// the definition of the global module fragment of the current module unit. + /// \param ModuleLoc The location of the 'module' keyword. + DeclGroupPtrTy ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc); - /// Block expression. - UPPC_Block, + /// The parser has processed a private-module-fragment declaration that begins + /// the definition of the private module fragment of the current module unit. + /// \param ModuleLoc The location of the 'module' keyword. + /// \param PrivateLoc The location of the 'private' keyword. + DeclGroupPtrTy ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc, + SourceLocation PrivateLoc); - /// A type constraint. - UPPC_TypeConstraint, + /// The parser has processed a module import declaration. + /// + /// \param StartLoc The location of the first token in the declaration. This + /// could be the location of an '@', 'export', or 'import'. + /// \param ExportLoc The location of the 'export' keyword, if any. + /// \param ImportLoc The location of the 'import' keyword. + /// \param Path The module toplevel name as an access path. + /// \param IsPartition If the name is for a partition. + DeclResult ActOnModuleImport(SourceLocation StartLoc, + SourceLocation ExportLoc, + SourceLocation ImportLoc, ModuleIdPath Path, + bool IsPartition = false); + DeclResult ActOnModuleImport(SourceLocation StartLoc, + SourceLocation ExportLoc, + SourceLocation ImportLoc, Module *M, + ModuleIdPath Path = {}); - // A requirement in a requires-expression. - UPPC_Requirement, + /// The parser has processed a module import translated from a + /// #include or similar preprocessing directive. + void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); + void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod); - // A requires-clause. - UPPC_RequiresClause, - }; + /// The parsed has entered a submodule. + void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod); + /// The parser has left a submodule. + void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod); - /// Diagnose unexpanded parameter packs. - /// - /// \param Loc The location at which we should emit the diagnostic. - /// - /// \param UPPC The context in which we are diagnosing unexpanded - /// parameter packs. - /// - /// \param Unexpanded the set of unexpanded parameter packs. + /// Create an implicit import of the given module at the given + /// source location, for error recovery, if possible. /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPacks(SourceLocation Loc, - UnexpandedParameterPackContext UPPC, - ArrayRef Unexpanded); + /// This routine is typically used when an entity found by name lookup + /// is actually hidden within a module that we know about but the user + /// has forgotten to import. + void createImplicitModuleImportForErrorRecovery(SourceLocation Loc, + Module *Mod); - /// If the given type contains an unexpanded parameter pack, - /// diagnose the error. - /// - /// \param Loc The source location where a diagnostc should be emitted. - /// - /// \param T The type that is being checked for unexpanded parameter - /// packs. - /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, - UnexpandedParameterPackContext UPPC); + Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, + SourceLocation LBraceLoc); + Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl, + SourceLocation RBraceLoc); - /// If the given expression contains an unexpanded parameter - /// pack, diagnose the error. - /// - /// \param E The expression that is being checked for unexpanded - /// parameter packs. - /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPack(Expr *E, - UnexpandedParameterPackContext UPPC = UPPC_Expression); +private: + /// The parser has begun a translation unit to be compiled as a C++20 + /// Header Unit, helper for ActOnStartOfTranslationUnit() only. + void HandleStartOfHeaderUnit(); - /// If the given requirees-expression contains an unexpanded reference to one - /// of its own parameter packs, diagnose the error. - /// - /// \param RE The requiress-expression that is being checked for unexpanded - /// parameter packs. - /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE); + struct ModuleScope { + SourceLocation BeginLoc; + clang::Module *Module = nullptr; + VisibleModuleSet OuterVisibleModules; + }; + /// The modules we're currently parsing. + llvm::SmallVector ModuleScopes; - /// If the given nested-name-specifier contains an unexpanded - /// parameter pack, diagnose the error. - /// - /// \param SS The nested-name-specifier that is being checked for - /// unexpanded parameter packs. - /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, - UnexpandedParameterPackContext UPPC); + /// For an interface unit, this is the implicitly imported interface unit. + clang::Module *ThePrimaryInterface = nullptr; - /// If the given name contains an unexpanded parameter pack, - /// diagnose the error. - /// - /// \param NameInfo The name (with source location information) that - /// is being checked for unexpanded parameter packs. - /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, - UnexpandedParameterPackContext UPPC); + /// The explicit global module fragment of the current translation unit. + /// The explicit Global Module Fragment, as specified in C++ + /// [module.global.frag]. + clang::Module *TheGlobalModuleFragment = nullptr; - /// If the given template name contains an unexpanded parameter pack, - /// diagnose the error. - /// - /// \param Loc The location of the template name. - /// - /// \param Template The template name that is being checked for unexpanded - /// parameter packs. + /// The implicit global module fragments of the current translation unit. /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, - TemplateName Template, - UnexpandedParameterPackContext UPPC); + /// The contents in the implicit global module fragment can't be discarded. + clang::Module *TheImplicitGlobalModuleFragment = nullptr; - /// If the given template argument contains an unexpanded parameter - /// pack, diagnose the error. - /// - /// \param Arg The template argument that is being checked for unexpanded - /// parameter packs. - /// - /// \returns true if an error occurred, false otherwise. - bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, - UnexpandedParameterPackContext UPPC); + /// Namespace definitions that we will export when they finish. + llvm::SmallPtrSet DeferredExportedNamespaces; - /// Collect the set of unexpanded parameter packs within the given - /// template argument. - /// - /// \param Arg The template argument that will be traversed to find - /// unexpanded parameter packs. - void collectUnexpandedParameterPacks(TemplateArgument Arg, - SmallVectorImpl &Unexpanded); + /// In a C++ standard module, inline declarations require a definition to be + /// present at the end of a definition domain. This set holds the decls to + /// be checked at the end of the TU. + llvm::SmallPtrSet PendingInlineFuncDecls; - /// Collect the set of unexpanded parameter packs within the given - /// template argument. - /// - /// \param Arg The template argument that will be traversed to find - /// unexpanded parameter packs. - void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg, - SmallVectorImpl &Unexpanded); + /// Helper function to judge if we are in module purview. + /// Return false if we are not in a module. + bool isCurrentModulePurview() const; - /// Collect the set of unexpanded parameter packs within the given - /// type. - /// - /// \param T The type that will be traversed to find - /// unexpanded parameter packs. - void collectUnexpandedParameterPacks(QualType T, - SmallVectorImpl &Unexpanded); + /// Enter the scope of the explicit global module fragment. + Module *PushGlobalModuleFragment(SourceLocation BeginLoc); + /// Leave the scope of the explicit global module fragment. + void PopGlobalModuleFragment(); - /// Collect the set of unexpanded parameter packs within the given - /// type. - /// - /// \param TL The type that will be traversed to find - /// unexpanded parameter packs. - void collectUnexpandedParameterPacks(TypeLoc TL, - SmallVectorImpl &Unexpanded); + /// Enter the scope of an implicit global module fragment. + Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc); + /// Leave the scope of an implicit global module fragment. + void PopImplicitGlobalModuleFragment(); - /// Collect the set of unexpanded parameter packs within the given - /// nested-name-specifier. - /// - /// \param NNS The nested-name-specifier that will be traversed to find - /// unexpanded parameter packs. - void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS, - SmallVectorImpl &Unexpanded); + VisibleModuleSet VisibleModules; - /// Collect the set of unexpanded parameter packs within the given - /// name. - /// - /// \param NameInfo The name that will be traversed to find - /// unexpanded parameter packs. - void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo, - SmallVectorImpl &Unexpanded); + ///@} - /// Invoked when parsing a template argument followed by an - /// ellipsis, which creates a pack expansion. - /// - /// \param Arg The template argument preceding the ellipsis, which - /// may already be invalid. - /// - /// \param EllipsisLoc The location of the ellipsis. - ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg, - SourceLocation EllipsisLoc); + // + // + // ------------------------------------------------------------------------- + // + // - /// Invoked when parsing a type followed by an ellipsis, which - /// creates a pack expansion. - /// - /// \param Type The type preceding the ellipsis, which will become - /// the pattern of the pack expansion. - /// - /// \param EllipsisLoc The location of the ellipsis. - TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc); + /// \name C++ Overloading + /// Implementations are in SemaOverload.cpp + ///@{ - /// Construct a pack expansion type from the pattern of the pack - /// expansion. - TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern, - SourceLocation EllipsisLoc, - std::optional NumExpansions); - - /// Construct a pack expansion type from the pattern of the pack - /// expansion. - QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange, - SourceLocation EllipsisLoc, - std::optional NumExpansions); +public: + /// Whether deferrable diagnostics should be deferred. + bool DeferDiags = false; - /// Invoked when parsing an expression followed by an ellipsis, which - /// creates a pack expansion. - /// - /// \param Pattern The expression preceding the ellipsis, which will become - /// the pattern of the pack expansion. - /// - /// \param EllipsisLoc The location of the ellipsis. - ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc); + /// RAII class to control scope of DeferDiags. + class DeferDiagsRAII { + Sema &S; + bool SavedDeferDiags = false; - /// Invoked when parsing an expression followed by an ellipsis, which - /// creates a pack expansion. - /// - /// \param Pattern The expression preceding the ellipsis, which will become - /// the pattern of the pack expansion. - /// - /// \param EllipsisLoc The location of the ellipsis. - ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, - std::optional NumExpansions); + public: + DeferDiagsRAII(Sema &S, bool DeferDiags) + : S(S), SavedDeferDiags(S.DeferDiags) { + S.DeferDiags = DeferDiags; + } + ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; } + }; - /// Determine whether we could expand a pack expansion with the - /// given set of parameter packs into separate arguments by repeatedly - /// transforming the pattern. - /// - /// \param EllipsisLoc The location of the ellipsis that identifies the - /// pack expansion. - /// - /// \param PatternRange The source range that covers the entire pattern of - /// the pack expansion. - /// - /// \param Unexpanded The set of unexpanded parameter packs within the - /// pattern. - /// - /// \param ShouldExpand Will be set to \c true if the transformer should - /// expand the corresponding pack expansions into separate arguments. When - /// set, \c NumExpansions must also be set. - /// - /// \param RetainExpansion Whether the caller should add an unexpanded - /// pack expansion after all of the expanded arguments. This is used - /// when extending explicitly-specified template argument packs per - /// C++0x [temp.arg.explicit]p9. - /// - /// \param NumExpansions The number of separate arguments that will be in - /// the expanded form of the corresponding pack expansion. This is both an - /// input and an output parameter, which can be set by the caller if the - /// number of expansions is known a priori (e.g., due to a prior substitution) - /// and will be set by the callee when the number of expansions is known. - /// The callee must set this value when \c ShouldExpand is \c true; it may - /// set this value in other cases. + /// Flag indicating if Sema is building a recovery call expression. /// - /// \returns true if an error occurred (e.g., because the parameter packs - /// are to be instantiated with arguments of different lengths), false - /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions) - /// must be set. - bool CheckParameterPacksForExpansion( - SourceLocation EllipsisLoc, SourceRange PatternRange, - ArrayRef Unexpanded, - const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, - bool &RetainExpansion, std::optional &NumExpansions); + /// This flag is used to avoid building recovery call expressions + /// if Sema is already doing so, which would cause infinite recursions. + bool IsBuildingRecoveryCallExpr; - /// Determine the number of arguments in the given pack expansion - /// type. - /// - /// This routine assumes that the number of arguments in the expansion is - /// consistent across all of the unexpanded parameter packs in its pattern. - /// - /// Returns an empty Optional if the type can't be expanded. - std::optional getNumArgumentsInExpansion( - QualType T, const MultiLevelTemplateArgumentList &TemplateArgs); + enum OverloadKind { + /// This is a legitimate overload: the existing declarations are + /// functions or function templates with different signatures. + Ovl_Overload, - /// Determine whether the given declarator contains any unexpanded - /// parameter packs. - /// - /// This routine is used by the parser to disambiguate function declarators - /// with an ellipsis prior to the ')', e.g., - /// - /// \code - /// void f(T...); - /// \endcode - /// - /// To determine whether we have an (unnamed) function parameter pack or - /// a variadic function. - /// - /// \returns true if the declarator contains any unexpanded parameter packs, - /// false otherwise. - bool containsUnexpandedParameterPacks(Declarator &D); + /// This is not an overload because the signature exactly matches + /// an existing declaration. + Ovl_Match, - /// Returns the pattern of the pack expansion for a template argument. - /// - /// \param OrigLoc The template argument to expand. - /// - /// \param Ellipsis Will be set to the location of the ellipsis. - /// - /// \param NumExpansions Will be set to the number of expansions that will - /// be generated from this pack expansion, if known a priori. - TemplateArgumentLoc getTemplateArgumentPackExpansionPattern( - TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis, - std::optional &NumExpansions) const; + /// This is not an overload because the lookup results contain a + /// non-function. + Ovl_NonFunction + }; + OverloadKind CheckOverload(Scope *S, FunctionDecl *New, + const LookupResult &OldDecls, NamedDecl *&OldDecl, + bool UseMemberUsingDeclRules); + bool IsOverload(FunctionDecl *New, FunctionDecl *Old, + bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true); - /// Given a template argument that contains an unexpanded parameter pack, but - /// which has already been substituted, attempt to determine the number of - /// elements that will be produced once this argument is fully-expanded. - /// - /// This is intended for use when transforming 'sizeof...(Arg)' in order to - /// avoid actually expanding the pack where possible. - std::optional getFullyPackExpandedSize(TemplateArgument Arg); + // Checks whether MD constitutes an override the base class method BaseMD. + // When checking for overrides, the object object members are ignored. + bool IsOverride(FunctionDecl *MD, FunctionDecl *BaseMD, + bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true); - //===--------------------------------------------------------------------===// - // C++ Template Argument Deduction (C++ [temp.deduct]) - //===--------------------------------------------------------------------===// + enum class AllowedExplicit { + /// Allow no explicit functions to be used. + None, + /// Allow explicit conversion functions but not explicit constructors. + Conversions, + /// Allow both explicit conversion functions and explicit constructors. + All + }; - /// Adjust the type \p ArgFunctionType to match the calling convention, - /// noreturn, and optionally the exception specification of \p FunctionType. - /// Deduction often wants to ignore these properties when matching function - /// types. - QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType, - bool AdjustExceptionSpec = false); + ImplicitConversionSequence TryImplicitConversion( + Expr *From, QualType ToType, bool SuppressUserConversions, + AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, + bool AllowObjCWritebackConversion); - TemplateDeductionResult - DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, - ArrayRef TemplateArgs, - sema::TemplateDeductionInfo &Info); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit = false); - TemplateDeductionResult - DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, - ArrayRef TemplateArgs, - sema::TemplateDeductionInfo &Info); + bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType); + bool IsFloatingPointPromotion(QualType FromType, QualType ToType); + bool IsComplexPromotion(QualType FromType, QualType ToType); + bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType, + bool InOverloadResolution, QualType &ConvertedType, + bool &IncompatibleObjC); + bool isObjCPointerConversion(QualType FromType, QualType ToType, + QualType &ConvertedType, bool &IncompatibleObjC); + bool isObjCWritebackConversion(QualType FromType, QualType ToType, + QualType &ConvertedType); + bool IsBlockPointerConversion(QualType FromType, QualType ToType, + QualType &ConvertedType); - TemplateDeductionResult SubstituteExplicitTemplateArguments( - FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo &ExplicitTemplateArgs, - SmallVectorImpl &Deduced, - SmallVectorImpl &ParamTypes, QualType *FunctionType, - sema::TemplateDeductionInfo &Info); + bool FunctionParamTypesAreEqual(ArrayRef Old, + ArrayRef New, + unsigned *ArgPos = nullptr, + bool Reversed = false); - /// brief A function argument from which we performed template argument - // deduction for a call. - struct OriginalCallArg { - OriginalCallArg(QualType OriginalParamType, bool DecomposedParam, - unsigned ArgIdx, QualType OriginalArgType) - : OriginalParamType(OriginalParamType), - DecomposedParam(DecomposedParam), ArgIdx(ArgIdx), - OriginalArgType(OriginalArgType) {} + bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType, + const FunctionProtoType *NewType, + unsigned *ArgPos = nullptr, + bool Reversed = false); - QualType OriginalParamType; - bool DecomposedParam; - unsigned ArgIdx; - QualType OriginalArgType; - }; + bool FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction, + const FunctionDecl *NewFunction, + unsigned *ArgPos = nullptr, + bool Reversed = false); - TemplateDeductionResult FinishTemplateArgumentDeduction( - FunctionTemplateDecl *FunctionTemplate, - SmallVectorImpl &Deduced, - unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, - sema::TemplateDeductionInfo &Info, - SmallVectorImpl const *OriginalCallArgs = nullptr, - bool PartialOverloading = false, - llvm::function_ref CheckNonDependent = []{ return false; }); + void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, QualType FromType, + QualType ToType); - TemplateDeductionResult DeduceTemplateArguments( - FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, - FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - bool PartialOverloading, bool AggregateDeductionCandidate, - QualType ObjectType, Expr::Classification ObjectClassification, - llvm::function_ref)> CheckNonDependent); + bool CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind, + CXXCastPath &BasePath, bool IgnoreBaseAccess, + bool Diagnose = true); + bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, + bool InOverloadResolution, + QualType &ConvertedType); + bool CheckMemberPointerConversion(Expr *From, QualType ToType, CastKind &Kind, + CXXCastPath &BasePath, + bool IgnoreBaseAccess); + bool IsQualificationConversion(QualType FromType, QualType ToType, + bool CStyle, bool &ObjCLifetimeConversion); + bool IsFunctionConversion(QualType FromType, QualType ToType, + QualType &ResultTy); + bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo *ExplicitTemplateArgs, - QualType ArgFunctionType, - FunctionDecl *&Specialization, - sema::TemplateDeductionInfo &Info, - bool IsAddressOfFunction = false); + ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj, + FunctionDecl *Fun); + ExprResult PerformImplicitObjectArgumentInitialization( + Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, + CXXMethodDecl *Method); - TemplateDeductionResult DeduceTemplateArguments( - FunctionTemplateDecl *FunctionTemplate, QualType ObjectType, - Expr::Classification ObjectClassification, QualType ToType, - CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info); + ExprResult PerformContextuallyConvertToBool(Expr *From); + ExprResult PerformContextuallyConvertToObjCPointer(Expr *From); - TemplateDeductionResult - DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo *ExplicitTemplateArgs, - FunctionDecl *&Specialization, - sema::TemplateDeductionInfo &Info, - bool IsAddressOfFunction = false); - - /// Substitute Replacement for \p auto in \p TypeWithAuto - QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement); - /// Substitute Replacement for auto in TypeWithAuto - TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, - QualType Replacement); - - // Substitute auto in TypeWithAuto for a Dependent auto type - QualType SubstAutoTypeDependent(QualType TypeWithAuto); - - // Substitute auto in TypeWithAuto for a Dependent auto type - TypeSourceInfo * - SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto); - - /// Completely replace the \c auto in \p TypeWithAuto by - /// \p Replacement. This does not retain any \c auto type sugar. - QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement); - TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, - QualType Replacement); - - TemplateDeductionResult - DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result, - sema::TemplateDeductionInfo &Info, - bool DependentDeduction = false, - bool IgnoreConstraints = false, - TemplateSpecCandidateSet *FailedTSC = nullptr); - void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init); - bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, - bool Diagnose = true); - - bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD, - SourceLocation Loc); - - /// Declare implicit deduction guides for a class template if we've - /// not already done so. - void DeclareImplicitDeductionGuides(TemplateDecl *Template, - SourceLocation Loc); - FunctionTemplateDecl *DeclareImplicitDeductionGuideFromInitList( - TemplateDecl *Template, MutableArrayRef ParamTypes, - SourceLocation Loc); - llvm::DenseMap - AggregateDeductionCandidates; - - QualType DeduceTemplateSpecializationFromInitializer( - TypeSourceInfo *TInfo, const InitializedEntity &Entity, - const InitializationKind &Kind, MultiExprArg Init); - - QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name, - QualType Type, TypeSourceInfo *TSI, - SourceRange Range, bool DirectInit, - Expr *Init); - - TypeLoc getReturnTypeLoc(FunctionDecl *FD) const; - - bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, - SourceLocation ReturnLoc, Expr *RetExpr, - const AutoType *AT); - - FunctionTemplateDecl *getMoreSpecializedTemplate( - FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc, - TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1, - unsigned NumCallArguments2, bool Reversed = false); - UnresolvedSetIterator - getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd, - TemplateSpecCandidateSet &FailedCandidates, - SourceLocation Loc, - const PartialDiagnostic &NoneDiag, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &CandidateDiag, - bool Complain = true, QualType TargetType = QualType()); + /// Contexts in which a converted constant expression is required. + enum CCEKind { + CCEK_CaseValue, ///< Expression in a case label. + CCEK_Enumerator, ///< Enumerator value with fixed underlying type. + CCEK_TemplateArg, ///< Value of a non-type template parameter. + CCEK_ArrayBound, ///< Array bound in array declarator or new-expression. + CCEK_ExplicitBool, ///< Condition in an explicit(bool) specifier. + CCEK_Noexcept, ///< Condition in a noexcept(bool) specifier. + CCEK_StaticAssertMessageSize, ///< Call to size() in a static assert + ///< message. + CCEK_StaticAssertMessageData, ///< Call to data() in a static assert + ///< message. + }; - ClassTemplatePartialSpecializationDecl * - getMoreSpecializedPartialSpecialization( - ClassTemplatePartialSpecializationDecl *PS1, - ClassTemplatePartialSpecializationDecl *PS2, - SourceLocation Loc); + ExprResult BuildConvertedConstantExpression(Expr *From, QualType T, + CCEKind CCE, + NamedDecl *Dest = nullptr); - bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T, - sema::TemplateDeductionInfo &Info); + ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, + llvm::APSInt &Value, CCEKind CCE); + ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, + APValue &Value, CCEKind CCE, + NamedDecl *Dest = nullptr); - VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization( - VarTemplatePartialSpecializationDecl *PS1, - VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc); + ExprResult + EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, + CCEKind CCE, bool RequireInt, + const APValue &PreNarrowingValue); - bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T, - sema::TemplateDeductionInfo &Info); + /// Abstract base class used to perform a contextual implicit + /// conversion from an expression to any type passing a filter. + class ContextualImplicitConverter { + public: + bool Suppress; + bool SuppressConversion; - bool isTemplateTemplateParameterAtLeastAsSpecializedAs( - TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc); + ContextualImplicitConverter(bool Suppress = false, + bool SuppressConversion = false) + : Suppress(Suppress), SuppressConversion(SuppressConversion) {} - void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, - unsigned Depth, llvm::SmallBitVector &Used); + /// Determine whether the specified type is a valid destination type + /// for this conversion. + virtual bool match(QualType T) = 0; - void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, - bool OnlyDeduced, - unsigned Depth, - llvm::SmallBitVector &Used); - void MarkDeducedTemplateParameters( - const FunctionTemplateDecl *FunctionTemplate, - llvm::SmallBitVector &Deduced) { - return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced); - } - static void MarkDeducedTemplateParameters(ASTContext &Ctx, - const FunctionTemplateDecl *FunctionTemplate, - llvm::SmallBitVector &Deduced); + /// Emits a diagnostic complaining that the expression does not have + /// integral or enumeration type. + virtual SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc, + QualType T) = 0; - //===--------------------------------------------------------------------===// - // C++ Template Instantiation - // + /// Emits a diagnostic when the expression has incomplete class type. + virtual SemaDiagnosticBuilder + diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0; - MultiLevelTemplateArgumentList getTemplateInstantiationArgs( - const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false, - std::optional> Innermost = std::nullopt, - bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, - bool ForConstraintInstantiation = false, - bool SkipForSpecialization = false); + /// Emits a diagnostic when the only matching conversion function + /// is explicit. + virtual SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, + SourceLocation Loc, + QualType T, + QualType ConvTy) = 0; - /// A context in which code is being synthesized (where a source location - /// alone is not sufficient to identify the context). This covers template - /// instantiation and various forms of implicitly-generated functions. - struct CodeSynthesisContext { - /// The kind of template instantiation we are performing - enum SynthesisKind { - /// We are instantiating a template declaration. The entity is - /// the declaration we're instantiating (e.g., a CXXRecordDecl). - TemplateInstantiation, + /// Emits a note for the explicit conversion function. + virtual SemaDiagnosticBuilder + noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; - /// We are instantiating a default argument for a template - /// parameter. The Entity is the template parameter whose argument is - /// being instantiated, the Template is the template, and the - /// TemplateArgs/NumTemplateArguments provide the template arguments as - /// specified. - DefaultTemplateArgumentInstantiation, + /// Emits a diagnostic when there are multiple possible conversion + /// functions. + virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) = 0; - /// We are instantiating a default argument for a function. - /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs - /// provides the template arguments as specified. - DefaultFunctionArgumentInstantiation, + /// Emits a note for one of the candidate conversions. + virtual SemaDiagnosticBuilder + noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; - /// We are substituting explicit template arguments provided for - /// a function template. The entity is a FunctionTemplateDecl. - ExplicitTemplateArgumentSubstitution, + /// Emits a diagnostic when we picked a conversion function + /// (for cases when we are not allowed to pick a conversion function). + virtual SemaDiagnosticBuilder diagnoseConversion(Sema &S, + SourceLocation Loc, + QualType T, + QualType ConvTy) = 0; - /// We are substituting template argument determined as part of - /// template argument deduction for either a class template - /// partial specialization or a function template. The - /// Entity is either a {Class|Var}TemplatePartialSpecializationDecl or - /// a TemplateDecl. - DeducedTemplateArgumentSubstitution, + virtual ~ContextualImplicitConverter() {} + }; - /// We are substituting into a lambda expression. - LambdaExpressionSubstitution, + class ICEConvertDiagnoser : public ContextualImplicitConverter { + bool AllowScopedEnumerations; - /// We are substituting prior template arguments into a new - /// template parameter. The template parameter itself is either a - /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl. - PriorTemplateArgumentSubstitution, + public: + ICEConvertDiagnoser(bool AllowScopedEnumerations, bool Suppress, + bool SuppressConversion) + : ContextualImplicitConverter(Suppress, SuppressConversion), + AllowScopedEnumerations(AllowScopedEnumerations) {} - /// We are checking the validity of a default template argument that - /// has been used when naming a template-id. - DefaultTemplateArgumentChecking, + /// Match an integral or (possibly scoped) enumeration type. + bool match(QualType T) override; - /// We are computing the exception specification for a defaulted special - /// member function. - ExceptionSpecEvaluation, + SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc, + QualType T) override { + return diagnoseNotInt(S, Loc, T); + } - /// We are instantiating the exception specification for a function - /// template which was deferred until it was needed. - ExceptionSpecInstantiation, + /// Emits a diagnostic complaining that the expression does not have + /// integral or enumeration type. + virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) = 0; + }; - /// We are instantiating a requirement of a requires expression. - RequirementInstantiation, + /// Perform a contextual implicit conversion. + ExprResult + PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, + ContextualImplicitConverter &Converter); - /// We are checking the satisfaction of a nested requirement of a requires - /// expression. - NestedRequirementConstraintsCheck, + /// ReferenceCompareResult - Expresses the result of comparing two + /// types (cv1 T1 and cv2 T2) to determine their compatibility for the + /// purposes of initialization by reference (C++ [dcl.init.ref]p4). + enum ReferenceCompareResult { + /// Ref_Incompatible - The two types are incompatible, so direct + /// reference binding is not possible. + Ref_Incompatible = 0, + /// Ref_Related - The two types are reference-related, which means + /// that their unqualified forms (T1 and T2) are either the same + /// or T1 is a base class of T2. + Ref_Related, + /// Ref_Compatible - The two types are reference-compatible. + Ref_Compatible + }; - /// We are declaring an implicit special member function. - DeclaringSpecialMember, + // Fake up a scoped enumeration that still contextually converts to bool. + struct ReferenceConversionsScope { + /// The conversions that would be performed on an lvalue of type T2 when + /// binding a reference of type T1 to it, as determined when evaluating + /// whether T1 is reference-compatible with T2. + enum ReferenceConversions { + Qualification = 0x1, + NestedQualification = 0x2, + Function = 0x4, + DerivedToBase = 0x8, + ObjC = 0x10, + ObjCLifetime = 0x20, - /// We are declaring an implicit 'operator==' for a defaulted - /// 'operator<=>'. - DeclaringImplicitEqualityComparison, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime) + }; + }; + using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions; - /// We are defining a synthesized function (such as a defaulted special - /// member). - DefiningSynthesizedFunction, + ReferenceCompareResult + CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2, + ReferenceConversions *Conv = nullptr); - // We are checking the constraints associated with a constrained entity or - // the constraint expression of a concept. This includes the checks that - // atomic constraints have the type 'bool' and that they can be constant - // evaluated. - ConstraintsCheck, + void AddOverloadCandidate( + FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, + bool PartialOverloading = false, bool AllowExplicit = true, + bool AllowExplicitConversion = false, + ADLCallKind IsADLCandidate = ADLCallKind::NotADL, + ConversionSequenceList EarlyConversions = std::nullopt, + OverloadCandidateParamOrder PO = {}, + bool AggregateCandidateDeduction = false); + void AddFunctionCandidates( + const UnresolvedSetImpl &Functions, ArrayRef Args, + OverloadCandidateSet &CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, + bool SuppressUserConversions = false, bool PartialOverloading = false, + bool FirstArgumentIsBase = false); + void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, + Expr::Classification ObjectClassification, + ArrayRef Args, + OverloadCandidateSet &CandidateSet, + bool SuppressUserConversion = false, + OverloadCandidateParamOrder PO = {}); + void + AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, + ArrayRef Args, OverloadCandidateSet &CandidateSet, + bool SuppressUserConversions = false, + bool PartialOverloading = false, + ConversionSequenceList EarlyConversions = std::nullopt, + OverloadCandidateParamOrder PO = {}); + void AddMethodTemplateCandidate( + FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, + Expr::Classification ObjectClassification, ArrayRef Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, + bool PartialOverloading = false, OverloadCandidateParamOrder PO = {}); + void AddTemplateOverloadCandidate( + FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, + TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, + bool PartialOverloading = false, bool AllowExplicit = true, + ADLCallKind IsADLCandidate = ADLCallKind::NotADL, + OverloadCandidateParamOrder PO = {}, + bool AggregateCandidateDeduction = false); + bool CheckNonDependentConversions( + FunctionTemplateDecl *FunctionTemplate, ArrayRef ParamTypes, + ArrayRef Args, OverloadCandidateSet &CandidateSet, + ConversionSequenceList &Conversions, bool SuppressUserConversions, + CXXRecordDecl *ActingContext = nullptr, QualType ObjectType = QualType(), + Expr::Classification ObjectClassification = {}, + OverloadCandidateParamOrder PO = {}); + void AddConversionCandidate( + CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, + bool AllowExplicit, bool AllowResultConversion = true); + void AddTemplateConversionCandidate( + FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, + bool AllowExplicit, bool AllowResultConversion = true); + void AddSurrogateCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + const FunctionProtoType *Proto, Expr *Object, + ArrayRef Args, + OverloadCandidateSet &CandidateSet); + void AddNonMemberOperatorCandidates( + const UnresolvedSetImpl &Functions, ArrayRef Args, + OverloadCandidateSet &CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); + void AddMemberOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, ArrayRef Args, + OverloadCandidateSet &CandidateSet, + OverloadCandidateParamOrder PO = {}); + void AddBuiltinCandidate(QualType *ParamTys, ArrayRef Args, + OverloadCandidateSet &CandidateSet, + bool IsAssignmentOperator = false, + unsigned NumContextualBoolArguments = 0); + void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, ArrayRef Args, + OverloadCandidateSet &CandidateSet); + void AddArgumentDependentLookupCandidates( + DeclarationName Name, SourceLocation Loc, ArrayRef Args, + TemplateArgumentListInfo *ExplicitTemplateArgs, + OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); - // We are substituting template arguments into a constraint expression. - ConstraintSubstitution, + /// Check the enable_if expressions on the given function. Returns the first + /// failing attribute, or NULL if they were all successful. + EnableIfAttr *CheckEnableIf(FunctionDecl *Function, SourceLocation CallLoc, + ArrayRef Args, + bool MissingImplicitThis = false); - // We are normalizing a constraint expression. - ConstraintNormalization, + /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any + /// non-ArgDependent DiagnoseIfAttrs. + /// + /// Argument-dependent diagnose_if attributes should be checked each time a + /// function is used as a direct callee of a function call. + /// + /// Returns true if any errors were emitted. + bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function, + const Expr *ThisArg, + ArrayRef Args, + SourceLocation Loc); - // Instantiating a Requires Expression parameter clause. - RequirementParameterInstantiation, + /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any + /// ArgDependent DiagnoseIfAttrs. + /// + /// Argument-independent diagnose_if attributes should be checked on every use + /// of a function. + /// + /// Returns true if any errors were emitted. + bool diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, + SourceLocation Loc); - // We are substituting into the parameter mapping of an atomic constraint - // during normalization. - ParameterMappingSubstitution, + /// Determine if \p A and \p B are equivalent internal linkage declarations + /// from different modules, and thus an ambiguity error can be downgraded to + /// an extension warning. + bool isEquivalentInternalLinkageDeclaration(const NamedDecl *A, + const NamedDecl *B); + void diagnoseEquivalentInternalLinkageDeclarations( + SourceLocation Loc, const NamedDecl *D, + ArrayRef Equiv); - /// We are rewriting a comparison operator in terms of an operator<=>. - RewritingOperatorAsSpaceship, + // Emit as a 'note' the specific overload candidate + void NoteOverloadCandidate( + const NamedDecl *Found, const FunctionDecl *Fn, + OverloadCandidateRewriteKind RewriteKind = OverloadCandidateRewriteKind(), + QualType DestType = QualType(), bool TakingAddress = false); - /// We are initializing a structured binding. - InitializingStructuredBinding, + // Emit as a series of 'note's all template and non-templates identified by + // the expression Expr + void NoteAllOverloadCandidates(Expr *E, QualType DestType = QualType(), + bool TakingAddress = false); - /// We are marking a class as __dllexport. - MarkingClassDllexported, + /// Returns whether the given function's address can be taken or not, + /// optionally emitting a diagnostic if the address can't be taken. + /// + /// Returns false if taking the address of the function is illegal. + bool checkAddressOfFunctionIsAvailable(const FunctionDecl *Function, + bool Complain = false, + SourceLocation Loc = SourceLocation()); - /// We are building an implied call from __builtin_dump_struct. The - /// arguments are in CallArgs. - BuildingBuiltinDumpStructCall, + // [PossiblyAFunctionType] --> [Return] + // NonFunctionType --> NonFunctionType + // R (A) --> R(A) + // R (*)(A) --> R (A) + // R (&)(A) --> R (A) + // R (S::*)(A) --> R (A) + QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType); - /// Added for Template instantiation observation. - /// Memoization means we are _not_ instantiating a template because - /// it is already instantiated (but we entered a context where we - /// would have had to if it was not already instantiated). - Memoization, + FunctionDecl * + ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, + bool Complain, DeclAccessPair &Found, + bool *pHadMultipleCandidates = nullptr); - /// We are building deduction guides for a class. - BuildingDeductionGuides, - } Kind; + FunctionDecl * + resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult); - /// Was the enclosing context a non-instantiation SFINAE context? - bool SavedInNonInstantiationSFINAEContext; + bool resolveAndFixAddressOfSingleOverloadCandidate( + ExprResult &SrcExpr, bool DoFunctionPointerConversion = false); - /// The point of instantiation or synthesis within the source code. - SourceLocation PointOfInstantiation; + FunctionDecl *ResolveSingleFunctionTemplateSpecialization( + OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr, + TemplateSpecCandidateSet *FailedTSC = nullptr); - /// The entity that is being synthesized. - Decl *Entity; + bool ResolveAndFixSingleFunctionTemplateSpecialization( + ExprResult &SrcExpr, bool DoFunctionPointerConversion = false, + bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(), + QualType DestTypeForComplaining = QualType(), + unsigned DiagIDForComplaining = 0); - /// The template (or partial specialization) in which we are - /// performing the instantiation, for substitutions of prior template - /// arguments. - NamedDecl *Template; + void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, + ArrayRef Args, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading = false); + void AddOverloadedCallCandidates( + LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs, + ArrayRef Args, OverloadCandidateSet &CandidateSet); - union { - /// The list of template arguments we are substituting, if they - /// are not part of the entity. - const TemplateArgument *TemplateArgs; + // An enum used to represent the different possible results of building a + // range-based for loop. + enum ForRangeStatus { + FRS_Success, + FRS_NoViableFunction, + FRS_DiagnosticIssued + }; - /// The list of argument expressions in a synthesized call. - const Expr *const *CallArgs; - }; + ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc, + SourceLocation RangeLoc, + const DeclarationNameInfo &NameInfo, + LookupResult &MemberLookup, + OverloadCandidateSet *CandidateSet, + Expr *Range, ExprResult *CallExpr); - // FIXME: Wrap this union around more members, or perhaps store the - // kind-specific members in the RAII object owning the context. - union { - /// The number of template arguments in TemplateArgs. - unsigned NumTemplateArgs; + ExprResult BuildOverloadedCallExpr( + Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, + MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig, + bool AllowTypoCorrection = true, bool CalleesAddressIsTaken = false); - /// The number of expressions in CallArgs. - unsigned NumCallArgs; + bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, + MultiExprArg Args, SourceLocation RParenLoc, + OverloadCandidateSet *CandidateSet, + ExprResult *Result); - /// The special member being declared or defined. - CXXSpecialMember SpecialMember; - }; + ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc NNSLoc, + DeclarationNameInfo DNI, + const UnresolvedSetImpl &Fns, + bool PerformADL = true); - ArrayRef template_arguments() const { - assert(Kind != DeclaringSpecialMember); - return {TemplateArgs, NumTemplateArgs}; - } + ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, + UnaryOperatorKind Opc, + const UnresolvedSetImpl &Fns, Expr *input, + bool RequiresADL = true); - /// The template deduction info object associated with the - /// substitution or checking of explicit or deduced template arguments. - sema::TemplateDeductionInfo *DeductionInfo; + void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet, + OverloadedOperatorKind Op, + const UnresolvedSetImpl &Fns, + ArrayRef Args, bool RequiresADL = true); + ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, + const UnresolvedSetImpl &Fns, Expr *LHS, + Expr *RHS, bool RequiresADL = true, + bool AllowRewrittenCandidates = true, + FunctionDecl *DefaultedFn = nullptr); + ExprResult BuildSynthesizedThreeWayComparison(SourceLocation OpLoc, + const UnresolvedSetImpl &Fns, + Expr *LHS, Expr *RHS, + FunctionDecl *DefaultedFn); - /// The source range that covers the construct that cause - /// the instantiation, e.g., the template-id that causes a class - /// template instantiation. - SourceRange InstantiationRange; + ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, + SourceLocation RLoc, Expr *Base, + MultiExprArg Args); - CodeSynthesisContext() - : Kind(TemplateInstantiation), - SavedInNonInstantiationSFINAEContext(false), Entity(nullptr), - Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0), - DeductionInfo(nullptr) {} + ExprResult BuildCallToMemberFunction( + Scope *S, Expr *MemExpr, SourceLocation LParenLoc, MultiExprArg Args, + SourceLocation RParenLoc, Expr *ExecConfig = nullptr, + bool IsExecConfig = false, bool AllowRecovery = false); + ExprResult BuildCallToObjectOfClassType(Scope *S, Expr *Object, + SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation RParenLoc); - /// Determines whether this template is an actual instantiation - /// that should be counted toward the maximum instantiation depth. - bool isInstantiationRecord() const; - }; - - /// List of active code synthesis contexts. - /// - /// This vector is treated as a stack. As synthesis of one entity requires - /// synthesis of another, additional contexts are pushed onto the stack. - SmallVector CodeSynthesisContexts; + ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + bool *NoArrowOperatorFound = nullptr); - /// Specializations whose definitions are currently being instantiated. - llvm::DenseSet> InstantiatingSpecializations; + ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl, + CXXConversionDecl *Method, + bool HadMultipleCandidates); - /// Non-dependent types used in templates that have already been instantiated - /// by some template instantiation. - llvm::DenseSet InstantiatedNonDependentTypes; + ExprResult BuildLiteralOperatorCall( + LookupResult &R, DeclarationNameInfo &SuffixInfo, ArrayRef Args, + SourceLocation LitEndLoc, + TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); - /// Extra modules inspected when performing a lookup during a template - /// instantiation. Computed lazily. - SmallVector CodeSynthesisContextLookupModules; + ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, + FunctionDecl *Fn); + ExprResult FixOverloadedFunctionReference(ExprResult, + DeclAccessPair FoundDecl, + FunctionDecl *Fn); - /// Cache of additional modules that should be used for name lookup - /// within the current template instantiation. Computed lazily; use - /// getLookupModules() to get a complete set. - llvm::DenseSet LookupModulesCache; +private: + /// - Returns a selector which best matches given argument list or + /// nullptr if none could be found + ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args, + bool IsInstance, + SmallVectorImpl &Methods); - /// Get the set of additional modules that should be checked during - /// name lookup. A module and its imports become visible when instanting a - /// template defined within it. - llvm::DenseSet &getLookupModules(); + ///@} - /// Map from the most recent declaration of a namespace to the most - /// recent visible declaration of that namespace. - llvm::DenseMap VisibleNamespaceCache; + // + // + // ------------------------------------------------------------------------- + // + // - /// Whether we are in a SFINAE context that is not associated with - /// template instantiation. - /// - /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside - /// of a template instantiation or template argument deduction. - bool InNonInstantiationSFINAEContext; + /// \name Pseudo-Object + /// Implementations are in SemaPseudoObject.cpp + ///@{ - /// The number of \p CodeSynthesisContexts that are not template - /// instantiations and, therefore, should not be counted as part of the - /// instantiation depth. - /// - /// When the instantiation depth reaches the user-configurable limit - /// \p LangOptions::InstantiationDepth we will abort instantiation. - // FIXME: Should we have a similar limit for other forms of synthesis? - unsigned NonInstantiationEntries; +public: + void maybeExtendBlockObject(ExprResult &E); + CastKind PrepareCastToObjCObjectPointer(ExprResult &E); - /// The depth of the context stack at the point when the most recent - /// error or warning was produced. - /// - /// This value is used to suppress printing of redundant context stacks - /// when there are multiple errors or warnings in the same instantiation. - // FIXME: Does this belong in Sema? It's tough to implement it anywhere else. - unsigned LastEmittedCodeSynthesisContextDepth = 0; + enum ObjCSubscriptKind { OS_Array, OS_Dictionary, OS_Error }; + ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE); - /// The template instantiation callbacks to trace or track - /// instantiations (objects can be chained). - /// - /// This callbacks is used to print, trace or track template - /// instantiations as they are being constructed. - std::vector> - TemplateInstCallbacks; + ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc, + UnaryOperatorKind Opcode, Expr *Op); + ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc, + BinaryOperatorKind Opcode, Expr *LHS, + Expr *RHS); + ExprResult checkPseudoObjectRValue(Expr *E); + Expr *recreateSyntacticForm(PseudoObjectExpr *E); - /// The current index into pack expansion arguments that will be - /// used for substitution of parameter packs. - /// - /// The pack expansion index will be -1 to indicate that parameter packs - /// should be instantiated as themselves. Otherwise, the index specifies - /// which argument within the parameter pack will be used for substitution. - int ArgumentPackSubstitutionIndex; + ///@} - /// RAII object used to change the argument pack substitution index - /// within a \c Sema object. - /// - /// See \c ArgumentPackSubstitutionIndex for more information. - class ArgumentPackSubstitutionIndexRAII { - Sema &Self; - int OldSubstitutionIndex; + // + // + // ------------------------------------------------------------------------- + // + // - public: - ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex) - : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) { - Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex; - } + /// \name Statements + /// Implementations are in SemaStmt.cpp + ///@{ - ~ArgumentPackSubstitutionIndexRAII() { - Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex; - } - }; +public: + /// Stack of active SEH __finally scopes. Can be empty. + SmallVector CurrentSEHFinally; - friend class ArgumentPackSubstitutionRAII; + StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true); + StmtResult ActOnExprStmtError(); - /// For each declaration that involved template argument deduction, the - /// set of diagnostics that were suppressed during that template argument - /// deduction. - /// - /// FIXME: Serialize this structure to the AST file. - typedef llvm::DenseMap > - SuppressedDiagnosticsMap; - SuppressedDiagnosticsMap SuppressedDiagnostics; + StmtResult ActOnNullStmt(SourceLocation SemiLoc, + bool HasLeadingEmptyMacro = false); - /// A stack object to be created when performing template - /// instantiation. - /// - /// Construction of an object of type \c InstantiatingTemplate - /// pushes the current instantiation onto the stack of active - /// instantiations. If the size of this stack exceeds the maximum - /// number of recursive template instantiations, construction - /// produces an error and evaluates true. - /// - /// Destruction of this object will pop the named instantiation off - /// the stack. - struct InstantiatingTemplate { - /// Note that we are instantiating a class template, - /// function template, variable template, alias template, - /// or a member thereof. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - Decl *Entity, - SourceRange InstantiationRange = SourceRange()); + StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, + SourceLocation EndLoc); + void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); - struct ExceptionSpecification {}; - /// Note that we are instantiating an exception specification - /// of a function template. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - FunctionDecl *Entity, ExceptionSpecification, - SourceRange InstantiationRange = SourceRange()); + /// DiagnoseUnusedExprResult - If the statement passed in is an expression + /// whose result is unused, warn. + void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID); - /// Note that we are instantiating a default argument in a - /// template-id. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateParameter Param, TemplateDecl *Template, - ArrayRef TemplateArgs, - SourceRange InstantiationRange = SourceRange()); + void ActOnStartOfCompoundStmt(bool IsStmtExpr); + void ActOnAfterCompoundStatementLeadingPragmas(); + void ActOnFinishOfCompoundStmt(); + StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, + ArrayRef Elts, bool isStmtExpr); - /// Note that we are substituting either explicitly-specified or - /// deduced template arguments during function template argument deduction. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - FunctionTemplateDecl *FunctionTemplate, - ArrayRef TemplateArgs, - CodeSynthesisContext::SynthesisKind Kind, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange = SourceRange()); + sema::CompoundScopeInfo &getCurCompoundScope() const; - /// Note that we are instantiating as part of template - /// argument deduction for a class template declaration. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateDecl *Template, - ArrayRef TemplateArgs, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange = SourceRange()); + ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val); + StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS, + SourceLocation DotDotDotLoc, ExprResult RHS, + SourceLocation ColonLoc); + void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt); - /// Note that we are instantiating as part of template - /// argument deduction for a class template partial - /// specialization. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ClassTemplatePartialSpecializationDecl *PartialSpec, - ArrayRef TemplateArgs, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange = SourceRange()); + StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, + SourceLocation ColonLoc, Stmt *SubStmt, + Scope *CurScope); + StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, + SourceLocation ColonLoc, Stmt *SubStmt); - /// Note that we are instantiating as part of template - /// argument deduction for a variable template partial - /// specialization. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - VarTemplatePartialSpecializationDecl *PartialSpec, - ArrayRef TemplateArgs, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange = SourceRange()); + StmtResult BuildAttributedStmt(SourceLocation AttrsLoc, + ArrayRef Attrs, Stmt *SubStmt); + StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList, + Stmt *SubStmt); - /// Note that we are instantiating a default argument for a function - /// parameter. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ParmVarDecl *Param, - ArrayRef TemplateArgs, - SourceRange InstantiationRange = SourceRange()); + /// Check whether the given statement can have musttail applied to it, + /// issuing a diagnostic and returning false if not. In the success case, + /// the statement is rewritten to remove implicit nodes from the return + /// value. + bool checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA); - /// Note that we are substituting prior template arguments into a - /// non-type parameter. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - NamedDecl *Template, - NonTypeTemplateParmDecl *Param, - ArrayRef TemplateArgs, - SourceRange InstantiationRange); + StmtResult ActOnIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind, + SourceLocation LParenLoc, Stmt *InitStmt, + ConditionResult Cond, SourceLocation RParenLoc, + Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal); + StmtResult BuildIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind, + SourceLocation LParenLoc, Stmt *InitStmt, + ConditionResult Cond, SourceLocation RParenLoc, + Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal); - /// Note that we are substituting prior template arguments into a - /// template template parameter. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - NamedDecl *Template, - TemplateTemplateParmDecl *Param, - ArrayRef TemplateArgs, - SourceRange InstantiationRange); + ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond); - /// Note that we are checking the default template argument - /// against the template parameter for a given template-id. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateDecl *Template, - NamedDecl *Param, - ArrayRef TemplateArgs, - SourceRange InstantiationRange); + StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, + SourceLocation LParenLoc, Stmt *InitStmt, + ConditionResult Cond, + SourceLocation RParenLoc); + StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, + Stmt *Body); - struct ConstraintsCheck {}; - /// \brief Note that we are checking the constraints associated with some - /// constrained entity (a concept declaration or a template with associated - /// constraints). - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ConstraintsCheck, NamedDecl *Template, - ArrayRef TemplateArgs, - SourceRange InstantiationRange); + /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant + /// integer not in the range of enum values. + void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, + Expr *SrcExpr); - struct ConstraintSubstitution {}; - /// \brief Note that we are checking a constraint expression associated - /// with a template declaration or as part of the satisfaction check of a - /// concept. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ConstraintSubstitution, NamedDecl *Template, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange); + StmtResult ActOnWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc, + ConditionResult Cond, SourceLocation RParenLoc, + Stmt *Body); + StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, + SourceLocation WhileLoc, SourceLocation CondLParen, + Expr *Cond, SourceLocation CondRParen); - struct ConstraintNormalization {}; - /// \brief Note that we are normalizing a constraint expression. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ConstraintNormalization, NamedDecl *Template, - SourceRange InstantiationRange); + StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *First, ConditionResult Second, + FullExprArg Third, SourceLocation RParenLoc, + Stmt *Body); - struct ParameterMappingSubstitution {}; - /// \brief Note that we are subtituting into the parameter mapping of an - /// atomic constraint during constraint normalization. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - ParameterMappingSubstitution, NamedDecl *Template, - SourceRange InstantiationRange); + StmtResult ActOnForEachLValueExpr(Expr *E); - /// \brief Note that we are substituting template arguments into a part of - /// a requirement of a requires expression. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - concepts::Requirement *Req, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange = SourceRange()); + ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc, + Expr *collection); + StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, Stmt *First, + Expr *collection, + SourceLocation RParenLoc); + StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body); - /// \brief Note that we are checking the satisfaction of the constraint - /// expression inside of a nested requirement. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - concepts::NestedRequirement *Req, ConstraintsCheck, - SourceRange InstantiationRange = SourceRange()); + enum BuildForRangeKind { + /// Initial building of a for-range statement. + BFRK_Build, + /// Instantiation or recovery rebuild of a for-range statement. Don't + /// attempt any typo-correction. + BFRK_Rebuild, + /// Determining whether a for-range statement could be built. Avoid any + /// unnecessary or irreversible actions. + BFRK_Check + }; - /// \brief Note that we are checking a requires clause. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - const RequiresExpr *E, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange); + StmtResult ActOnCXXForRangeStmt( + Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, + Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection, + SourceLocation RParenLoc, BuildForRangeKind Kind, + ArrayRef LifetimeExtendTemps = {}); + StmtResult BuildCXXForRangeStmt( + SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, + SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, + Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, + BuildForRangeKind Kind, + ArrayRef LifetimeExtendTemps = {}); + StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body); - struct BuildingDeductionGuidesTag {}; - /// \brief Note that we are building deduction guides. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - TemplateDecl *Entity, BuildingDeductionGuidesTag, - SourceRange InstantiationRange = SourceRange()); + StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, + LabelDecl *TheDecl); + StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, + SourceLocation StarLoc, Expr *DestExp); + StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope); + StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope); - /// Note that we have finished instantiating this template. - void Clear(); + struct NamedReturnInfo { + const VarDecl *Candidate; - ~InstantiatingTemplate() { Clear(); } + enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable }; + Status S; - /// Determines whether we have exceeded the maximum - /// recursive template instantiations. - bool isInvalid() const { return Invalid; } + bool isMoveEligible() const { return S != None; }; + bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; } + }; + enum class SimplerImplicitMoveMode { ForceOff, Normal, ForceOn }; + NamedReturnInfo getNamedReturnInfo( + Expr *&E, SimplerImplicitMoveMode Mode = SimplerImplicitMoveMode::Normal); + NamedReturnInfo getNamedReturnInfo(const VarDecl *VD); + const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info, + QualType ReturnType); - /// Determine whether we are already instantiating this - /// specialization in some surrounding active instantiation. - bool isAlreadyInstantiating() const { return AlreadyInstantiating; } + ExprResult + PerformMoveOrCopyInitialization(const InitializedEntity &Entity, + const NamedReturnInfo &NRInfo, Expr *Value, + bool SupressSimplerImplicitMoves = false); - private: - Sema &SemaRef; - bool Invalid; - bool AlreadyInstantiating; - bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, - SourceRange InstantiationRange); + TypeLoc getReturnTypeLoc(FunctionDecl *FD) const; - InstantiatingTemplate( - Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind, - SourceLocation PointOfInstantiation, SourceRange InstantiationRange, - Decl *Entity, NamedDecl *Template = nullptr, - ArrayRef TemplateArgs = std::nullopt, - sema::TemplateDeductionInfo *DeductionInfo = nullptr); + bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, + SourceLocation ReturnLoc, Expr *RetExpr, + const AutoType *AT); - InstantiatingTemplate(const InstantiatingTemplate&) = delete; + StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, + Scope *CurScope); + StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, + bool AllowRecovery = false); + StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, + NamedReturnInfo &NRInfo, + bool SupressSimplerImplicitMoves); - InstantiatingTemplate& - operator=(const InstantiatingTemplate&) = delete; - }; + StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, + Decl *Parm, Stmt *Body); - void pushCodeSynthesisContext(CodeSynthesisContext Ctx); - void popCodeSynthesisContext(); + StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body); - /// Determine whether we are currently performing template instantiation. - bool inTemplateInstantiation() const { - return CodeSynthesisContexts.size() > NonInstantiationEntries; - } + StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, + MultiStmtArg Catch, Stmt *Finally); - void PrintContextStack() { - if (!CodeSynthesisContexts.empty() && - CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) { - PrintInstantiationStack(); - LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size(); - } - if (PragmaAttributeCurrentTargetDecl) - PrintPragmaAttributeInstantiationPoint(); - } - void PrintInstantiationStack(); + StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw); + StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, + Scope *CurScope); + ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, + Expr *operand); + StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SynchExpr, + Stmt *SynchBody); - void PrintPragmaAttributeInstantiationPoint(); + StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body); - /// Determines whether we are currently in a context where - /// template argument substitution failures are not considered - /// errors. - /// - /// \returns An empty \c Optional if we're not in a SFINAE context. - /// Otherwise, contains a pointer that, if non-NULL, contains the nearest - /// template-deduction context object, which can be used to capture - /// diagnostics that will be suppressed. - std::optional isSFINAEContext() const; + StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, + Stmt *HandlerBlock); + StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, + ArrayRef Handlers); - /// Whether the AST is currently being rebuilt to correct immediate - /// invocations. Immediate invocation candidates and references to consteval - /// functions aren't tracked when this is set. - bool RebuildingImmediateInvocation = false; + StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ? + SourceLocation TryLoc, Stmt *TryBlock, + Stmt *Handler); + StmtResult ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, + Stmt *Block); + void ActOnStartSEHFinallyBlock(); + void ActOnAbortSEHFinallyBlock(); + StmtResult ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block); + StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope); - /// Used to change context to isConstantEvaluated without pushing a heavy - /// ExpressionEvaluationContextRecord object. - bool isConstantEvaluatedOverride = false; + StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, + NestedNameSpecifierLoc QualifierLoc, + DeclarationNameInfo NameInfo, + Stmt *Nested); + StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc, + bool IsIfExists, CXXScopeSpec &SS, + UnqualifiedId &Name, Stmt *Nested); - const ExpressionEvaluationContextRecord ¤tEvaluationContext() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - return ExprEvalContexts.back(); - }; + void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, + CapturedRegionKind Kind, unsigned NumParams); + typedef std::pair CapturedParamNameType; + void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, + CapturedRegionKind Kind, + ArrayRef Params, + unsigned OpenMPCaptureLevel = 0); + StmtResult ActOnCapturedRegionEnd(Stmt *S); + void ActOnCapturedRegionError(); + RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD, + SourceLocation Loc, + unsigned NumParams); - bool isConstantEvaluatedContext() const { - return currentEvaluationContext().isConstantEvaluated() || - isConstantEvaluatedOverride; - } +private: + /// Check whether the given statement can have musttail applied to it, + /// issuing a diagnostic and returning false if not. + bool checkMustTailAttr(const Stmt *St, const Attr &MTA); - bool isAlwaysConstantEvaluatedContext() const { - const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext(); - return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) && - !Ctx.InConditionallyConstantEvaluateContext; - } + /// Check if the given expression contains 'break' or 'continue' + /// statement that produces control flow different from GCC. + void CheckBreakContinueBinding(Expr *E); - /// Determines whether we are currently in a context that - /// is not evaluated as per C++ [expr] p5. - bool isUnevaluatedContext() const { - return currentEvaluationContext().isUnevaluated(); - } + ///@} - bool isImmediateFunctionContext() const { - return currentEvaluationContext().isImmediateFunctionContext(); - } + // + // + // ------------------------------------------------------------------------- + // + // - bool isInLifetimeExtendingContext() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - return ExprEvalContexts.back().InLifetimeExtendingContext; - } + /// \name `inline asm` Statement + /// Implementations are in SemaStmtAsm.cpp + ///@{ - bool isInMaterializeTemporaryObjectContext() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - return ExprEvalContexts.back().InMaterializeTemporaryObjectContext; - } +public: + StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg Constraints, MultiExprArg Exprs, + Expr *AsmString, MultiExprArg Clobbers, + unsigned NumLabels, SourceLocation RParenLoc); - bool isCheckingDefaultArgumentOrInitializer() const { - const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext(); - return (Ctx.Context == - ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) || - Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer; - } + void FillInlineAsmIdentifierInfo(Expr *Res, + llvm::InlineAsmIdentifierInfo &Info); + ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + UnqualifiedId &Id, + bool IsUnevaluatedContext); + bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, + SourceLocation AsmLoc); + ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, + SourceLocation AsmLoc); + StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, + ArrayRef AsmToks, StringRef AsmString, + unsigned NumOutputs, unsigned NumInputs, + ArrayRef Constraints, + ArrayRef Clobbers, + ArrayRef Exprs, SourceLocation EndLoc); + LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName, + SourceLocation Location, bool AlwaysCreate); - std::optional - InnermostDeclarationWithDelayedImmediateInvocations() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - for (const auto &Ctx : llvm::reverse(ExprEvalContexts)) { - if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated && - Ctx.DelayedDefaultInitializationContext) - return Ctx.DelayedDefaultInitializationContext; - if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() || - Ctx.isUnevaluated()) - break; - } - return std::nullopt; - } + ///@} - std::optional - OutermostDeclarationWithDelayedImmediateInvocations() const { - assert(!ExprEvalContexts.empty() && - "Must be in an expression evaluation context"); - std::optional Res; - for (auto &Ctx : llvm::reverse(ExprEvalContexts)) { - if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated && - !Ctx.DelayedDefaultInitializationContext && Res) - break; - if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() || - Ctx.isUnevaluated()) - break; - Res = Ctx.DelayedDefaultInitializationContext; - } - return Res; - } + // + // + // ------------------------------------------------------------------------- + // + // - /// keepInLifetimeExtendingContext - Pull down InLifetimeExtendingContext - /// flag from previous context. - void keepInLifetimeExtendingContext() { - if (ExprEvalContexts.size() > 2 && - ExprEvalContexts[ExprEvalContexts.size() - 2] - .InLifetimeExtendingContext) { - auto &LastRecord = ExprEvalContexts.back(); - auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; - LastRecord.InLifetimeExtendingContext = - PrevRecord.InLifetimeExtendingContext; - } - } + /// \name Statement Attribute Handling + /// Implementations are in SemaStmtAttr.cpp + ///@{ - /// keepInMaterializeTemporaryObjectContext - Pull down - /// InMaterializeTemporaryObjectContext flag from previous context. - void keepInMaterializeTemporaryObjectContext() { - if (ExprEvalContexts.size() > 2 && - ExprEvalContexts[ExprEvalContexts.size() - 2] - .InMaterializeTemporaryObjectContext) { - auto &LastRecord = ExprEvalContexts.back(); - auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; - LastRecord.InMaterializeTemporaryObjectContext = - PrevRecord.InMaterializeTemporaryObjectContext; - } - } +public: + bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, + const AttributeCommonInfo &A); + bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, + const AttributeCommonInfo &A); - /// RAII class used to determine whether SFINAE has - /// trapped any errors that occur during template argument - /// deduction. - class SFINAETrap { - Sema &SemaRef; - unsigned PrevSFINAEErrors; - bool PrevInNonInstantiationSFINAEContext; - bool PrevAccessCheckingSFINAE; - bool PrevLastDiagnosticIgnored; + CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E); + bool CheckRebuiltStmtAttributes(ArrayRef Attrs); - public: - explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false) - : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors), - PrevInNonInstantiationSFINAEContext( - SemaRef.InNonInstantiationSFINAEContext), - PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE), - PrevLastDiagnosticIgnored( - SemaRef.getDiagnostics().isLastDiagnosticIgnored()) - { - if (!SemaRef.isSFINAEContext()) - SemaRef.InNonInstantiationSFINAEContext = true; - SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE; - } + /// Process the attributes before creating an attributed statement. Returns + /// the semantic attributes that have been processed. + void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs, + SmallVectorImpl &OutAttrs); - ~SFINAETrap() { - SemaRef.NumSFINAEErrors = PrevSFINAEErrors; - SemaRef.InNonInstantiationSFINAEContext - = PrevInNonInstantiationSFINAEContext; - SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE; - SemaRef.getDiagnostics().setLastDiagnosticIgnored( - PrevLastDiagnosticIgnored); - } + ///@} - /// Determine whether any SFINAE errors have been trapped. - bool hasErrorOccurred() const { - return SemaRef.NumSFINAEErrors > PrevSFINAEErrors; - } - }; + // + // + // ------------------------------------------------------------------------- + // + // - /// RAII class used to indicate that we are performing provisional - /// semantic analysis to determine the validity of a construct, so - /// typo-correction and diagnostics in the immediate context (not within - /// implicitly-instantiated templates) should be suppressed. - class TentativeAnalysisScope { - Sema &SemaRef; - // FIXME: Using a SFINAETrap for this is a hack. - SFINAETrap Trap; - bool PrevDisableTypoCorrection; + /// \name C++ Templates + /// Implementations are in SemaTemplate.cpp + ///@{ + +public: + // Saves the current floating-point pragma stack and clear it in this Sema. + class FpPragmaStackSaveRAII { public: - explicit TentativeAnalysisScope(Sema &SemaRef) - : SemaRef(SemaRef), Trap(SemaRef, true), - PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) { - SemaRef.DisableTypoCorrection = true; - } - ~TentativeAnalysisScope() { - SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection; + FpPragmaStackSaveRAII(Sema &S) + : S(S), SavedStack(std::move(S.FpPragmaStack)) { + S.FpPragmaStack.Stack.clear(); } + ~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); } + + private: + Sema &S; + PragmaStack SavedStack; }; - /// The current instantiation scope used to store local - /// variables. - LocalInstantiationScope *CurrentInstantiationScope; + void resetFPOptions(FPOptions FPO) { + CurFPFeatures = FPO; + FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts)); + } - /// Tracks whether we are in a context where typo correction is - /// disabled. - bool DisableTypoCorrection; + ArrayRef getInventedParameterInfos() const { + return llvm::ArrayRef(InventedParameterInfos.begin() + + InventedParameterInfosStart, + InventedParameterInfos.end()); + } - /// The number of typos corrected by CorrectTypo. - unsigned TyposCorrected; + /// The number of SFINAE diagnostics that have been trapped. + unsigned NumSFINAEErrors; - typedef llvm::SmallSet SrcLocSet; - typedef llvm::DenseMap IdentifierSourceLocations; + ArrayRef getFunctionScopes() const { + return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart, + FunctionScopes.end()); + } - /// A cache containing identifiers for which typo correction failed and - /// their locations, so that repeated attempts to correct an identifier in a - /// given location are ignored if typo correction already failed for it. - IdentifierSourceLocations TypoCorrectionFailures; + typedef llvm::MapVector> + LateParsedTemplateMapT; + LateParsedTemplateMapT LateParsedTemplateMap; - /// Worker object for performing CFG-based warnings. - sema::AnalysisBasedWarnings AnalysisWarnings; - threadSafety::BeforeSet *ThreadSafetyDeclCache; + /// Determine the number of levels of enclosing template parameters. This is + /// only usable while parsing. Note that this does not include dependent + /// contexts in which no template parameters have yet been declared, such as + /// in a terse function template or generic lambda before the first 'auto' is + /// encountered. + unsigned getTemplateDepth(Scope *S) const; - /// An entity for which implicit template instantiation is required. + void FilterAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates = true, + bool AllowDependent = true); + bool hasAnyAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates = true, + bool AllowDependent = true, + bool AllowNonTemplateFunctions = false); + /// Try to interpret the lookup result D as a template-name. /// - /// The source location associated with the declaration is the first place in - /// the source code where the declaration was "used". It is not necessarily - /// the point of instantiation (which will be either before or after the - /// namespace-scope declaration that triggered this implicit instantiation), - /// However, it is the location that diagnostics should generally refer to, - /// because users will need to know what code triggered the instantiation. - typedef std::pair PendingImplicitInstantiation; - - /// The queue of implicit template instantiations that are required - /// but have not yet been performed. - std::deque PendingInstantiations; - - /// Queue of implicit template instantiations that cannot be performed - /// eagerly. - SmallVector LateParsedInstantiations; - - SmallVector, 8> SavedVTableUses; - SmallVector, 8> - SavedPendingInstantiations; + /// \param D A declaration found by name lookup. + /// \param AllowFunctionTemplates Whether function templates should be + /// considered valid results. + /// \param AllowDependent Whether unresolved using declarations (that might + /// name templates) should be considered valid results. + static NamedDecl *getAsTemplateNameDecl(NamedDecl *D, + bool AllowFunctionTemplates = true, + bool AllowDependent = true); - class GlobalEagerInstantiationScope { + enum TemplateNameIsRequiredTag { TemplateNameIsRequired }; + /// Whether and why a template name is required in this lookup. + class RequiredTemplateKind { public: - GlobalEagerInstantiationScope(Sema &S, bool Enabled) - : S(S), Enabled(Enabled) { - if (!Enabled) return; - - S.SavedPendingInstantiations.emplace_back(); - S.SavedPendingInstantiations.back().swap(S.PendingInstantiations); + /// Template name is required if TemplateKWLoc is valid. + RequiredTemplateKind(SourceLocation TemplateKWLoc = SourceLocation()) + : TemplateKW(TemplateKWLoc) {} + /// Template name is unconditionally required. + RequiredTemplateKind(TemplateNameIsRequiredTag) {} - S.SavedVTableUses.emplace_back(); - S.SavedVTableUses.back().swap(S.VTableUses); + SourceLocation getTemplateKeywordLoc() const { + return TemplateKW.value_or(SourceLocation()); } - - void perform() { - if (Enabled) { - S.DefineUsedVTables(); - S.PerformPendingInstantiations(); - } + bool hasTemplateKeyword() const { + return getTemplateKeywordLoc().isValid(); } + bool isRequired() const { return TemplateKW != SourceLocation(); } + explicit operator bool() const { return isRequired(); } - ~GlobalEagerInstantiationScope() { - if (!Enabled) return; - - // Restore the set of pending vtables. - assert(S.VTableUses.empty() && - "VTableUses should be empty before it is discarded."); - S.VTableUses.swap(S.SavedVTableUses.back()); - S.SavedVTableUses.pop_back(); + private: + std::optional TemplateKW; + }; - // Restore the set of pending implicit instantiations. - if (S.TUKind != TU_Prefix || !S.LangOpts.PCHInstantiateTemplates) { - assert(S.PendingInstantiations.empty() && - "PendingInstantiations should be empty before it is discarded."); - S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); - S.SavedPendingInstantiations.pop_back(); - } else { - // Template instantiations in the PCH may be delayed until the TU. - S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); - S.PendingInstantiations.insert( - S.PendingInstantiations.end(), - S.SavedPendingInstantiations.back().begin(), - S.SavedPendingInstantiations.back().end()); - S.SavedPendingInstantiations.pop_back(); - } - } - - private: - Sema &S; - bool Enabled; + enum class AssumedTemplateKind { + /// This is not assumed to be a template name. + None, + /// This is assumed to be a template name because lookup found nothing. + FoundNothing, + /// This is assumed to be a template name because lookup found one or more + /// functions (but no function templates). + FoundFunctions, }; + bool LookupTemplateName( + LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType, + bool EnteringContext, bool &MemberOfUnknownSpecialization, + RequiredTemplateKind RequiredTemplate = SourceLocation(), + AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true); - /// The queue of implicit template instantiations that are required - /// and must be performed within the current local scope. - /// - /// This queue is only used for member functions of local classes in - /// templates, which must be instantiated in the same scope as their - /// enclosing function, so that they can reference function-local - /// types, static variables, enumerators, etc. - std::deque PendingLocalImplicitInstantiations; + TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS, + bool hasTemplateKeyword, + const UnqualifiedId &Name, + ParsedType ObjectType, bool EnteringContext, + TemplateTy &Template, + bool &MemberOfUnknownSpecialization, + bool Disambiguation = false); - class LocalEagerInstantiationScope { - public: - LocalEagerInstantiationScope(Sema &S) : S(S) { - SavedPendingLocalImplicitInstantiations.swap( - S.PendingLocalImplicitInstantiations); - } + /// Try to resolve an undeclared template name as a type template. + /// + /// Sets II to the identifier corresponding to the template name, and updates + /// Name to a corresponding (typo-corrected) type template name and TNK to + /// the corresponding kind, if possible. + void ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &Name, + TemplateNameKind &TNK, + SourceLocation NameLoc, + IdentifierInfo *&II); - void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); } + bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name, + SourceLocation NameLoc, + bool Diagnose = true); - ~LocalEagerInstantiationScope() { - assert(S.PendingLocalImplicitInstantiations.empty() && - "there shouldn't be any pending local implicit instantiations"); - SavedPendingLocalImplicitInstantiations.swap( - S.PendingLocalImplicitInstantiations); - } + /// Determine whether a particular identifier might be the name in a C++1z + /// deduction-guide declaration. + bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name, + SourceLocation NameLoc, CXXScopeSpec &SS, + ParsedTemplateTy *Template = nullptr); - private: - Sema &S; - std::deque - SavedPendingLocalImplicitInstantiations; - }; + bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind); - /// A helper class for building up ExtParameterInfos. - class ExtParameterInfoBuilder { - SmallVector Infos; - bool HasInteresting = false; + bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, + NamedDecl *Instantiation, + bool InstantiatedFromMember, + const NamedDecl *Pattern, + const NamedDecl *PatternDef, + TemplateSpecializationKind TSK, + bool Complain = true); - public: - /// Set the ExtParameterInfo for the parameter at the given index, - /// - void set(unsigned index, FunctionProtoType::ExtParameterInfo info) { - assert(Infos.size() <= index); - Infos.resize(index); - Infos.push_back(info); + /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining + /// that the template parameter 'PrevDecl' is being shadowed by a new + /// declaration at location Loc. Returns true to indicate that this is + /// an error, and false otherwise. + /// + /// \param Loc The location of the declaration that shadows a template + /// parameter. + /// + /// \param PrevDecl The template parameter that the declaration shadows. + /// + /// \param SupportedForCompatibility Whether to issue the diagnostic as + /// a warning for compatibility with older versions of clang. + /// Ignored when MSVC compatibility is enabled. + void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl, + bool SupportedForCompatibility = false); + TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); - if (!HasInteresting) - HasInteresting = (info != FunctionProtoType::ExtParameterInfo()); - } + NamedDecl *ActOnTypeParameter(Scope *S, bool Typename, + SourceLocation EllipsisLoc, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, unsigned Depth, + unsigned Position, SourceLocation EqualLoc, + ParsedType DefaultArg, bool HasTypeConstraint); - /// Return a pointer (suitable for setting in an ExtProtoInfo) to the - /// ExtParameterInfo array we've built up. - const FunctionProtoType::ExtParameterInfo * - getPointerOrNull(unsigned numParams) { - if (!HasInteresting) return nullptr; - Infos.resize(numParams); - return Infos.data(); - } - }; + bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint); - void PerformPendingInstantiations(bool LocalOnly = false); + bool ActOnTypeConstraint(const CXXScopeSpec &SS, + TemplateIdAnnotation *TypeConstraint, + TemplateTypeParmDecl *ConstrainedParameter, + SourceLocation EllipsisLoc); + bool BuildTypeConstraint(const CXXScopeSpec &SS, + TemplateIdAnnotation *TypeConstraint, + TemplateTypeParmDecl *ConstrainedParameter, + SourceLocation EllipsisLoc, + bool AllowUnexpandedPack); - TypeSourceInfo *SubstType(TypeSourceInfo *T, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity, - bool AllowDeducedTST = false); + bool AttachTypeConstraint(NestedNameSpecifierLoc NS, + DeclarationNameInfo NameInfo, + ConceptDecl *NamedConcept, + const TemplateArgumentListInfo *TemplateArgs, + TemplateTypeParmDecl *ConstrainedParameter, + SourceLocation EllipsisLoc); - QualType SubstType(QualType T, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity); + bool AttachTypeConstraint(AutoTypeLoc TL, + NonTypeTemplateParmDecl *NewConstrainedParm, + NonTypeTemplateParmDecl *OrigConstrainedParm, + SourceLocation EllipsisLoc); - TypeSourceInfo *SubstType(TypeLoc TL, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity); + bool RequireStructuralType(QualType T, SourceLocation Loc); - TypeSourceInfo *SubstFunctionDeclType( - TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals, bool EvaluateConstraints = true); - void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, - const MultiLevelTemplateArgumentList &Args); - bool SubstExceptionSpec(SourceLocation Loc, - FunctionProtoType::ExceptionSpecInfo &ESI, - SmallVectorImpl &ExceptionStorage, - const MultiLevelTemplateArgumentList &Args); - ParmVarDecl * - SubstParmVarDecl(ParmVarDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs, - int indexAdjustment, std::optional NumExpansions, - bool ExpectParameterPack, bool EvaluateConstraints = true); - bool SubstParmTypes(SourceLocation Loc, ArrayRef Params, - const FunctionProtoType::ExtParameterInfo *ExtParamInfos, - const MultiLevelTemplateArgumentList &TemplateArgs, - SmallVectorImpl &ParamTypes, - SmallVectorImpl *OutParams, - ExtParameterInfoBuilder &ParamInfos); - bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool ForCallExpr = false); - ExprResult SubstExpr(Expr *E, - const MultiLevelTemplateArgumentList &TemplateArgs); + QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, + SourceLocation Loc); + QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc); - // A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator - // to disable constraint evaluation, then restore the state. - template struct ConstraintEvalRAII { - InstTy &TI; - bool OldValue; + NamedDecl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + Expr *DefaultArg); + NamedDecl *ActOnTemplateTemplateParameter( + Scope *S, SourceLocation TmpLoc, TemplateParameterList *Params, + SourceLocation EllipsisLoc, IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, unsigned Depth, unsigned Position, + SourceLocation EqualLoc, ParsedTemplateArgument DefaultArg); + + TemplateParameterList *ActOnTemplateParameterList( + unsigned Depth, SourceLocation ExportLoc, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, ArrayRef Params, + SourceLocation RAngleLoc, Expr *RequiresClause); - ConstraintEvalRAII(InstTy &TI) - : TI(TI), OldValue(TI.getEvaluateConstraints()) { - TI.setEvaluateConstraints(false); - } - ~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); } + /// The context in which we are checking a template parameter list. + enum TemplateParamListContext { + TPC_ClassTemplate, + TPC_VarTemplate, + TPC_FunctionTemplate, + TPC_ClassTemplateMember, + TPC_FriendClassTemplate, + TPC_FriendFunctionTemplate, + TPC_FriendFunctionTemplateDefinition, + TPC_TypeAliasTemplate }; - // Must be used instead of SubstExpr at 'constraint checking' time. - ExprResult - SubstConstraintExpr(Expr *E, - const MultiLevelTemplateArgumentList &TemplateArgs); - // Unlike the above, this does not evaluates constraints. - ExprResult SubstConstraintExprWithoutSatisfaction( - Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); - - /// Substitute the given template arguments into a list of - /// expressions, expanding pack expansions if required. - /// - /// \param Exprs The list of expressions to substitute into. - /// - /// \param IsCall Whether this is some form of call, in which case - /// default arguments will be dropped. - /// - /// \param TemplateArgs The set of template arguments to substitute. - /// - /// \param Outputs Will receive all of the substituted arguments. - /// - /// \returns true if an error occurred, false otherwise. - bool SubstExprs(ArrayRef Exprs, bool IsCall, - const MultiLevelTemplateArgumentList &TemplateArgs, - SmallVectorImpl &Outputs); + bool CheckTemplateParameterList(TemplateParameterList *NewParams, + TemplateParameterList *OldParams, + TemplateParamListContext TPC, + SkipBodyInfo *SkipBody = nullptr); + TemplateParameterList *MatchTemplateParametersToScopeSpecifier( + SourceLocation DeclStartLoc, SourceLocation DeclLoc, + const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId, + ArrayRef ParamLists, bool IsFriend, + bool &IsMemberSpecialization, bool &Invalid, + bool SuppressDiagnostic = false); - StmtResult SubstStmt(Stmt *S, - const MultiLevelTemplateArgumentList &TemplateArgs); + DeclResult CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, + SkipBodyInfo *SkipBody = nullptr); - TemplateParameterList * - SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool EvaluateConstraints = true); - - bool - SubstTemplateArguments(ArrayRef Args, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateArgumentListInfo &Outputs); - - Decl *SubstDecl(Decl *D, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs); - - /// Substitute the name and return type of a defaulted 'operator<=>' to form - /// an implicit 'operator=='. - FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD, - FunctionDecl *Spaceship); - - ExprResult SubstInitializer(Expr *E, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool CXXDirectInit); - - bool - SubstBaseSpecifiers(CXXRecordDecl *Instantiation, - CXXRecordDecl *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs); + void translateTemplateArguments(const ASTTemplateArgsPtr &In, + TemplateArgumentListInfo &Out); - bool - InstantiateClass(SourceLocation PointOfInstantiation, - CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK, - bool Complain = true); + ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType); - bool InstantiateEnum(SourceLocation PointOfInstantiation, - EnumDecl *Instantiation, EnumDecl *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK); + void NoteAllFoundTemplates(TemplateName Name); - bool InstantiateInClassInitializer( - SourceLocation PointOfInstantiation, FieldDecl *Instantiation, - FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs); + QualType CheckTemplateIdType(TemplateName Template, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs); - struct LateInstantiatedAttribute { - const Attr *TmplAttr; - LocalInstantiationScope *Scope; - Decl *NewDecl; + TypeResult + ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + TemplateTy Template, IdentifierInfo *TemplateII, + SourceLocation TemplateIILoc, SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc, + bool IsCtorOrDtorName = false, bool IsClassName = false, + ImplicitTypenameContext AllowImplicitTypename = + ImplicitTypenameContext::No); - LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S, - Decl *D) - : TmplAttr(A), Scope(S), NewDecl(D) - { } - }; - typedef SmallVector LateInstantiatedAttrVec; + /// Parsed an elaborated-type-specifier that refers to a template-id, + /// such as \c class T::template apply. + TypeResult ActOnTagTemplateIdType( + TagUseKind TUK, TypeSpecifierType TagSpec, SourceLocation TagLoc, + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, TemplateTy TemplateD, + SourceLocation TemplateLoc, SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc); - void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Pattern, Decl *Inst, - LateInstantiatedAttrVec *LateAttrs = nullptr, - LocalInstantiationScope *OuterMostScope = nullptr); - void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst); + DeclResult ActOnVarTemplateSpecialization( + Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous, + SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, + StorageClass SC, bool IsPartialSpecialization); - void - InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Pattern, Decl *Inst, - LateInstantiatedAttrVec *LateAttrs = nullptr, - LocalInstantiationScope *OuterMostScope = nullptr); + /// Get the specialization of the given variable template corresponding to + /// the specified argument list, or a null-but-valid result if the arguments + /// are dependent. + DeclResult CheckVarTemplateId(VarTemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation TemplateNameLoc, + const TemplateArgumentListInfo &TemplateArgs); - void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor); + /// Form a reference to the specialization of the given variable template + /// corresponding to the specified argument list, or a null-but-valid result + /// if the arguments are dependent. + ExprResult CheckVarTemplateId(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + VarTemplateDecl *Template, NamedDecl *FoundD, + SourceLocation TemplateLoc, + const TemplateArgumentListInfo *TemplateArgs); - bool usesPartialOrExplicitSpecialization( - SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec); + ExprResult + CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const TemplateArgumentListInfo *TemplateArgs); - bool - InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, - ClassTemplateSpecializationDecl *ClassTemplateSpec, - TemplateSpecializationKind TSK, - bool Complain = true); + void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc); - void InstantiateClassMembers(SourceLocation PointOfInstantiation, - CXXRecordDecl *Instantiation, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK); + ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo *TemplateArgs); - void InstantiateClassTemplateSpecializationMembers( - SourceLocation PointOfInstantiation, - ClassTemplateSpecializationDecl *ClassTemplateSpec, - TemplateSpecializationKind TSK); + ExprResult + BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); - NestedNameSpecifierLoc - SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, - const MultiLevelTemplateArgumentList &TemplateArgs); + TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + const UnqualifiedId &Name, + ParsedType ObjectType, + bool EnteringContext, TemplateTy &Template, + bool AllowInjectedClassName = false); - DeclarationNameInfo - SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, - const MultiLevelTemplateArgumentList &TemplateArgs); - TemplateName - SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, - SourceLocation Loc, - const MultiLevelTemplateArgumentList &TemplateArgs); + DeclResult ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, CXXScopeSpec &SS, + TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, + SkipBodyInfo *SkipBody = nullptr); - bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool EvaluateConstraint); + bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, + TemplateDecl *PrimaryTemplate, + unsigned NumExplicitArgs, + ArrayRef Args); + void CheckTemplatePartialSpecialization( + ClassTemplatePartialSpecializationDecl *Partial); + void CheckTemplatePartialSpecialization( + VarTemplatePartialSpecializationDecl *Partial); - bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, - ParmVarDecl *Param); - void InstantiateExceptionSpec(SourceLocation PointOfInstantiation, - FunctionDecl *Function); - bool CheckInstantiatedFunctionTemplateConstraints( - SourceLocation PointOfInstantiation, FunctionDecl *Decl, - ArrayRef TemplateArgs, - ConstraintSatisfaction &Satisfaction); - FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, - const TemplateArgumentList *Args, - SourceLocation Loc); - void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, - FunctionDecl *Function, - bool Recursive = false, - bool DefinitionRequired = false, - bool AtEndOfTU = false); - VarTemplateSpecializationDecl *BuildVarTemplateInstantiation( - VarTemplateDecl *VarTemplate, VarDecl *FromVar, - const TemplateArgumentList *PartialSpecArgs, - const TemplateArgumentListInfo &TemplateArgsInfo, - SmallVectorImpl &Converted, - SourceLocation PointOfInstantiation, - LateInstantiatedAttrVec *LateAttrs = nullptr, - LocalInstantiationScope *StartingScope = nullptr); - VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl( - VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, - const MultiLevelTemplateArgumentList &TemplateArgs); - void - BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs, - LateInstantiatedAttrVec *LateAttrs, - DeclContext *Owner, - LocalInstantiationScope *StartingScope, - bool InstantiatingVarTemplate = false, - VarTemplateSpecializationDecl *PrevVTSD = nullptr); + Decl *ActOnTemplateDeclarator(Scope *S, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D); - void InstantiateVariableInitializer( - VarDecl *Var, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs); - void InstantiateVariableDefinition(SourceLocation PointOfInstantiation, - VarDecl *Var, bool Recursive = false, - bool DefinitionRequired = false, - bool AtEndOfTU = false); + bool CheckSpecializationInstantiationRedecl( + SourceLocation NewLoc, + TemplateSpecializationKind ActOnExplicitInstantiationNewTSK, + NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK, + SourceLocation PrevPtOfInstantiation, bool &SuppressNew); - void InstantiateMemInitializers(CXXConstructorDecl *New, - const CXXConstructorDecl *Tmpl, - const MultiLevelTemplateArgumentList &TemplateArgs); + bool CheckDependentFunctionTemplateSpecialization( + FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs, + LookupResult &Previous); - ExplicitSpecifier instantiateExplicitSpecifier( - const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES); + bool CheckFunctionTemplateSpecialization( + FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, + LookupResult &Previous, bool QualifiedFriend = false); + bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); + void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); - NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool FindingInstantiatedContext = false); - DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC, - const MultiLevelTemplateArgumentList &TemplateArgs); + DeclResult ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy Template, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr); - // Objective-C declarations. - enum ObjCContainerKind { - OCK_None = -1, - OCK_Interface = 0, - OCK_Protocol, - OCK_Category, - OCK_ClassExtension, - OCK_Implementation, - OCK_CategoryImplementation - }; - ObjCContainerKind getObjCContainerKind() const; + DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr); - DeclResult actOnObjCTypeParam(Scope *S, - ObjCTypeParamVariance variance, - SourceLocation varianceLoc, - unsigned index, - IdentifierInfo *paramName, - SourceLocation paramLoc, - SourceLocation colonLoc, - ParsedType typeBound); + DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, + Declarator &D); - ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc, - ArrayRef typeParams, - SourceLocation rAngleLoc); - void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); + TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable( + TemplateDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, Decl *Param, + ArrayRef SugaredConverted, + ArrayRef CanonicalConverted, bool &HasDefaultArg); - ObjCInterfaceDecl *ActOnStartClassInterface( - Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, - SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, - Decl *const *ProtoRefs, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, - const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody); + SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const; - void ActOnSuperClassOfClassInterface(Scope *S, - SourceLocation AtInterfaceLoc, - ObjCInterfaceDecl *IDecl, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, - SourceRange SuperTypeArgsRange); + /// Specifies the context in which a particular template + /// argument is being checked. + enum CheckTemplateArgumentKind { + /// The template argument was specified in the code or was + /// instantiated with some deduced template arguments. + CTAK_Specified, - void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs, - SmallVectorImpl &ProtocolLocs, - IdentifierInfo *SuperName, - SourceLocation SuperLoc); + /// The template argument was deduced via template argument + /// deduction. + CTAK_Deduced, - Decl *ActOnCompatibilityAlias( - SourceLocation AtCompatibilityAliasLoc, - IdentifierInfo *AliasName, SourceLocation AliasLocation, - IdentifierInfo *ClassName, SourceLocation ClassLocation); + /// The template argument was deduced from an array bound + /// via template argument deduction. + CTAK_DeducedFromArrayBound + }; - bool CheckForwardProtocolDeclarationForCircularDependency( - IdentifierInfo *PName, - SourceLocation &PLoc, SourceLocation PrevLoc, - const ObjCList &PList); + bool + CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg, + NamedDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, unsigned ArgumentPackIndex, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted, + CheckTemplateArgumentKind CTAK); - ObjCProtocolDecl *ActOnStartProtocolInterface( - SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, - SourceLocation ProtocolLoc, Decl *const *ProtoRefNames, - unsigned NumProtoRefs, const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList, - SkipBodyInfo *SkipBody); - - ObjCCategoryDecl *ActOnStartCategoryInterface( - SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, - SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, SourceLocation CategoryLoc, - Decl *const *ProtoRefs, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, - const ParsedAttributesView &AttrList); - - ObjCImplementationDecl *ActOnStartClassImplementation( - SourceLocation AtClassImplLoc, IdentifierInfo *ClassName, - SourceLocation ClassLoc, IdentifierInfo *SuperClassname, - SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList); - - ObjCCategoryImplDecl *ActOnStartCategoryImplementation( - SourceLocation AtCatImplLoc, IdentifierInfo *ClassName, - SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc, - const ParsedAttributesView &AttrList); - - DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl, - ArrayRef Decls); - - DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc, - IdentifierInfo **IdentList, - SourceLocation *IdentLocs, - ArrayRef TypeParamLists, - unsigned NumElts); + /// Check that the given template arguments can be provided to + /// the given template, converting the arguments along the way. + /// + /// \param Template The template to which the template arguments are being + /// provided. + /// + /// \param TemplateLoc The location of the template name in the source. + /// + /// \param TemplateArgs The list of template arguments. If the template is + /// a template template parameter, this function may extend the set of + /// template arguments to also include substituted, defaulted template + /// arguments. + /// + /// \param PartialTemplateArgs True if the list of template arguments is + /// intentionally partial, e.g., because we're checking just the initial + /// set of template arguments. + /// + /// \param Converted Will receive the converted, canonicalized template + /// arguments. + /// + /// \param UpdateArgsWithConversions If \c true, update \p TemplateArgs to + /// contain the converted forms of the template arguments as written. + /// Otherwise, \p TemplateArgs will not be modified. + /// + /// \param ConstraintsNotSatisfied If provided, and an error occurred, will + /// receive true if the cause for the error is the associated constraints of + /// the template not being satisfied by the template arguments. + /// + /// \returns true if an error occurred, false otherwise. + bool CheckTemplateArgumentList( + TemplateDecl *Template, SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted, + bool UpdateArgsWithConversions = true, + bool *ConstraintsNotSatisfied = nullptr); - DeclGroupPtrTy - ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, - ArrayRef IdentList, - const ParsedAttributesView &attrList); + bool CheckTemplateTypeArgument( + TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted); - void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, - ArrayRef ProtocolId, - SmallVectorImpl &Protocols); + bool CheckTemplateArgument(TypeSourceInfo *Arg); + ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param, + QualType InstantiatedParamType, Expr *Arg, + TemplateArgument &SugaredConverted, + TemplateArgument &CanonicalConverted, + CheckTemplateArgumentKind CTAK); + bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, + TemplateParameterList *Params, + TemplateArgumentLoc &Arg); - void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, - SourceLocation ProtocolLoc, - IdentifierInfo *TypeArgId, - SourceLocation TypeArgLoc, - bool SelectProtocolFirst = false); + void NoteTemplateLocation(const NamedDecl &Decl, + std::optional ParamRange = {}); + void NoteTemplateParameterLocation(const NamedDecl &Decl); - /// Given a list of identifiers (and their locations), resolve the - /// names to either Objective-C protocol qualifiers or type - /// arguments, as appropriate. - void actOnObjCTypeArgsOrProtocolQualifiers( - Scope *S, - ParsedType baseType, - SourceLocation lAngleLoc, - ArrayRef identifiers, - ArrayRef identifierLocs, - SourceLocation rAngleLoc, - SourceLocation &typeArgsLAngleLoc, - SmallVectorImpl &typeArgs, - SourceLocation &typeArgsRAngleLoc, - SourceLocation &protocolLAngleLoc, - SmallVectorImpl &protocols, - SourceLocation &protocolRAngleLoc, - bool warnOnIncompleteProtocols); + ExprResult BuildExpressionFromDeclTemplateArgument( + const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc); + ExprResult + BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, + SourceLocation Loc); - /// Build a an Objective-C protocol-qualified 'id' type where no - /// base type was specified. - TypeResult actOnObjCProtocolQualifierType( - SourceLocation lAngleLoc, - ArrayRef protocols, - ArrayRef protocolLocs, - SourceLocation rAngleLoc); + /// Enumeration describing how template parameter lists are compared + /// for equality. + enum TemplateParameterListEqualKind { + /// We are matching the template parameter lists of two templates + /// that might be redeclarations. + /// + /// \code + /// template struct X; + /// template struct X; + /// \endcode + TPL_TemplateMatch, - /// Build a specialized and/or protocol-qualified Objective-C type. - TypeResult actOnObjCTypeArgsAndProtocolQualifiers( - Scope *S, - SourceLocation Loc, - ParsedType BaseType, - SourceLocation TypeArgsLAngleLoc, - ArrayRef TypeArgs, - SourceLocation TypeArgsRAngleLoc, - SourceLocation ProtocolLAngleLoc, - ArrayRef Protocols, - ArrayRef ProtocolLocs, - SourceLocation ProtocolRAngleLoc); + /// We are matching the template parameter lists of two template + /// template parameters as part of matching the template parameter lists + /// of two templates that might be redeclarations. + /// + /// \code + /// template class TT> struct X; + /// template class Other> struct X; + /// \endcode + TPL_TemplateTemplateParmMatch, - /// Build an Objective-C type parameter type. - QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, - SourceLocation ProtocolLAngleLoc, - ArrayRef Protocols, - ArrayRef ProtocolLocs, - SourceLocation ProtocolRAngleLoc, - bool FailOnError = false); + /// We are matching the template parameter lists of a template + /// template argument against the template parameter lists of a template + /// template parameter. + /// + /// \code + /// template class Metafun> struct X; + /// template struct integer_c; + /// X xic; + /// \endcode + TPL_TemplateTemplateArgumentMatch, - /// Build an Objective-C object pointer type. - QualType BuildObjCObjectType( - QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, - ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc, - SourceLocation ProtocolLAngleLoc, ArrayRef Protocols, - ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc, - bool FailOnError, bool Rebuilding); + /// We are determining whether the template-parameters are equivalent + /// according to C++ [temp.over.link]/6. This comparison does not consider + /// constraints. + /// + /// \code + /// template void f(T); + /// template void f(T); + /// \endcode + TPL_TemplateParamsEquivalent, + }; - /// Ensure attributes are consistent with type. - /// \param [in, out] Attributes The attributes to check; they will - /// be modified to be consistent with \p PropertyTy. - void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, - SourceLocation Loc, - unsigned &Attributes, - bool propertyInPrimaryClass); + // A struct to represent the 'new' declaration, which is either itself just + // the named decl, or the important information we need about it in order to + // do constraint comparisons. + class TemplateCompareNewDeclInfo { + const NamedDecl *ND = nullptr; + const DeclContext *DC = nullptr; + const DeclContext *LexicalDC = nullptr; + SourceLocation Loc; - /// Process the specified property declaration and create decls for the - /// setters and getters as needed. - /// \param property The property declaration being processed - void ProcessPropertyDecl(ObjCPropertyDecl *property); + public: + TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {} + TemplateCompareNewDeclInfo(const DeclContext *DeclCtx, + const DeclContext *LexicalDeclCtx, + SourceLocation Loc) + : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) { + assert(DC && LexicalDC && + "Constructor only for cases where we have the information to put " + "in here"); + } - void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, - ObjCPropertyDecl *SuperProperty, - const IdentifierInfo *Name, - bool OverridingProtocolProperty); + // If this was constructed with no information, we cannot do substitution + // for constraint comparison, so make sure we can check that. + bool isInvalid() const { return !ND && !DC; } - void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, - ObjCInterfaceDecl *ID); + const NamedDecl *getDecl() const { return ND; } - Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd, - ArrayRef allMethods = std::nullopt, - ArrayRef allTUVars = std::nullopt); + bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; } - Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, - SourceLocation LParenLoc, - FieldDeclarator &FD, ObjCDeclSpec &ODS, - Selector GetterSel, Selector SetterSel, - tok::ObjCKeywordKind MethodImplKind, - DeclContext *lexicalDC = nullptr); + const DeclContext *getLexicalDeclContext() const { + return ND ? ND->getLexicalDeclContext() : LexicalDC; + } - Decl *ActOnPropertyImplDecl(Scope *S, - SourceLocation AtLoc, - SourceLocation PropertyLoc, - bool ImplKind, - IdentifierInfo *PropertyId, - IdentifierInfo *PropertyIvar, - SourceLocation PropertyIvarLoc, - ObjCPropertyQueryKind QueryKind); + const DeclContext *getDeclContext() const { + return ND ? ND->getDeclContext() : DC; + } - enum ObjCSpecialMethodKind { - OSMK_None, - OSMK_Alloc, - OSMK_New, - OSMK_Copy, - OSMK_RetainingInit, - OSMK_NonRetainingInit + SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; } }; - struct ObjCArgInfo { - IdentifierInfo *Name; - SourceLocation NameLoc; - // The Type is null if no type was specified, and the DeclSpec is invalid - // in this case. - ParsedType Type; - ObjCDeclSpec DeclSpec; + bool TemplateParameterListsAreEqual( + const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New, + const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, + TemplateParameterListEqualKind Kind, + SourceLocation TemplateArgLoc = SourceLocation()); - /// ArgAttrs - Attribute list for this argument. - ParsedAttributesView ArgAttrs; - }; + bool TemplateParameterListsAreEqual( + TemplateParameterList *New, TemplateParameterList *Old, bool Complain, + TemplateParameterListEqualKind Kind, + SourceLocation TemplateArgLoc = SourceLocation()) { + return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain, + Kind, TemplateArgLoc); + } - Decl *ActOnMethodDeclaration( - Scope *S, - SourceLocation BeginLoc, // location of the + or -. - SourceLocation EndLoc, // location of the ; or {. - tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef SelectorLocs, Selector Sel, - // optional arguments. The number of types/arguments is obtained - // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, - unsigned CNumArgs, // c-style args - const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind, - bool isVariadic, bool MethodDefinition); + bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); - ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, - const ObjCObjectPointerType *OPT, - bool IsInstance); - ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty, - bool IsInstance); - - bool CheckARCMethodDecl(ObjCMethodDecl *method); - bool inferObjCARCLifetime(ValueDecl *decl); + /// Called when the parser has parsed a C++ typename + /// specifier, e.g., "typename T::type". + /// + /// \param S The scope in which this typename type occurs. + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param II the identifier we're retrieving (e.g., 'type' in the example). + /// \param IdLoc the location of the identifier. + /// \param IsImplicitTypename context where T::type refers to a type. + TypeResult ActOnTypenameType( + Scope *S, SourceLocation TypenameLoc, const CXXScopeSpec &SS, + const IdentifierInfo &II, SourceLocation IdLoc, + ImplicitTypenameContext IsImplicitTypename = ImplicitTypenameContext::No); - void deduceOpenCLAddressSpace(ValueDecl *decl); + /// Called when the parser has parsed a C++ typename + /// specifier that ends in a template-id, e.g., + /// "typename MetaFun::template apply". + /// + /// \param S The scope in which this typename type occurs. + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param TemplateLoc the location of the 'template' keyword, if any. + /// \param TemplateName The template name. + /// \param TemplateII The identifier used to name the template. + /// \param TemplateIILoc The location of the template name. + /// \param LAngleLoc The location of the opening angle bracket ('<'). + /// \param TemplateArgs The template arguments. + /// \param RAngleLoc The location of the closing angle bracket ('>'). + TypeResult + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, SourceLocation TemplateLoc, + TemplateTy TemplateName, IdentifierInfo *TemplateII, + SourceLocation TemplateIILoc, SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc); - ExprResult - HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, - Expr *BaseExpr, - SourceLocation OpLoc, - DeclarationName MemberName, - SourceLocation MemberLoc, - SourceLocation SuperLoc, QualType SuperType, - bool Super); + QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, + SourceLocation KeywordLoc, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, SourceLocation IILoc, + TypeSourceInfo **TSI, bool DeducedTSTContext); - ExprResult - ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, - IdentifierInfo &propertyName, - SourceLocation receiverNameLoc, - SourceLocation propertyNameLoc); + QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, + SourceLocation KeywordLoc, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, SourceLocation IILoc, + bool DeducedTSTContext = true); - ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc); + TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, + SourceLocation Loc, + DeclarationName Name); + bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS); - /// Describes the kind of message expression indicated by a message - /// send that starts with an identifier. - enum ObjCMessageKind { - /// The message is sent to 'super'. - ObjCSuperMessage, - /// The message is an instance message. - ObjCInstanceMessage, - /// The message is a class message, and the identifier is a type - /// name. - ObjCClassMessage - }; + ExprResult RebuildExprInCurrentInstantiation(Expr *E); + bool + RebuildTemplateParamsInCurrentInstantiation(TemplateParameterList *Params); - ObjCMessageKind getObjCMessageKind(Scope *S, - IdentifierInfo *Name, - SourceLocation NameLoc, - bool IsSuper, - bool HasTrailingDot, - ParsedType &ReceiverType); + std::string + getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgumentList &Args); - ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, - Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args); + std::string + getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgument *Args, + unsigned NumArgs); - ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args, - bool isImplicit = false); + void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, + SourceLocation Less, + SourceLocation Greater); - ExprResult BuildClassMessageImplicit(QualType ReceiverType, - bool isSuperReceiver, - SourceLocation Loc, - Selector Sel, - ObjCMethodDecl *Method, - MultiExprArg Args); + ExprResult ActOnDependentIdExpression( + const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, + const TemplateArgumentListInfo *TemplateArgs); - ExprResult ActOnClassMessage(Scope *S, - ParsedType Receiver, - Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args); + ExprResult + BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); - ExprResult BuildInstanceMessage(Expr *Receiver, - QualType ReceiverType, - SourceLocation SuperLoc, - Selector Sel, - ObjCMethodDecl *Method, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args, - bool isImplicit = false); + // Calculates whether the expression Constraint depends on an enclosing + // template, for the purposes of [temp.friend] p9. + // TemplateDepth is the 'depth' of the friend function, which is used to + // compare whether a declaration reference is referring to a containing + // template, or just the current friend function. A 'lower' TemplateDepth in + // the AST refers to a 'containing' template. As the constraint is + // uninstantiated, this is relative to the 'top' of the TU. + bool + ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, + unsigned TemplateDepth, + const Expr *Constraint); - ExprResult BuildInstanceMessageImplicit(Expr *Receiver, - QualType ReceiverType, - SourceLocation Loc, - Selector Sel, - ObjCMethodDecl *Method, - MultiExprArg Args); + /// Declare implicit deduction guides for a class template if we've + /// not already done so. + void DeclareImplicitDeductionGuides(TemplateDecl *Template, + SourceLocation Loc); + FunctionTemplateDecl *DeclareImplicitDeductionGuideFromInitList( + TemplateDecl *Template, MutableArrayRef ParamTypes, + SourceLocation Loc); - ExprResult ActOnInstanceMessage(Scope *S, - Expr *Receiver, - Selector Sel, - SourceLocation LBracLoc, - ArrayRef SelectorLocs, - SourceLocation RBracLoc, - MultiExprArg Args); + /// Find the failed Boolean condition within a given Boolean + /// constant expression, and describe it with a string. + std::pair findFailedBooleanCondition(Expr *Cond); - ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc, - ObjCBridgeCastKind Kind, - SourceLocation BridgeKeywordLoc, - TypeSourceInfo *TSInfo, - Expr *SubExpr); + void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD); - ExprResult ActOnObjCBridgedCast(Scope *S, - SourceLocation LParenLoc, - ObjCBridgeCastKind Kind, - SourceLocation BridgeKeywordLoc, - ParsedType Type, - SourceLocation RParenLoc, - Expr *SubExpr); + Decl *ActOnConceptDefinition(Scope *S, + MultiTemplateParamsArg TemplateParameterLists, + IdentifierInfo *Name, SourceLocation NameLoc, + Expr *ConstraintExpr); - void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr); + void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous, + bool &AddToScope); - void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr); + TypeResult ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + const CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation TagLoc, SourceLocation NameLoc); - bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, - CastKind &Kind); + void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD, + CachedTokens &Toks); + void UnmarkAsLateParsedTemplate(FunctionDecl *FD); + bool IsInsideALocalClassWithinATemplateFunction(); - bool checkObjCBridgeRelatedComponents(SourceLocation Loc, - QualType DestType, QualType SrcType, - ObjCInterfaceDecl *&RelatedClass, - ObjCMethodDecl *&ClassMethod, - ObjCMethodDecl *&InstanceMethod, - TypedefNameDecl *&TDNDecl, - bool CfToNs, bool Diagnose = true); + /// We've found a use of a templated declaration that would trigger an + /// implicit instantiation. Check that any relevant explicit specializations + /// and partial specializations are visible/reachable, and diagnose if not. + void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec); + void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec); - bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, - QualType DestType, QualType SrcType, - Expr *&SrcExpr, bool Diagnose = true); + ///@} - bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr, - bool Diagnose = true); + // + // + // ------------------------------------------------------------------------- + // + // - bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); + /// \name C++ Template Argument Deduction + /// Implementations are in SemaTemplateDeduction.cpp + ///@{ - /// Check whether the given new method is a valid override of the - /// given overridden method, and set any properties that should be inherited. - void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, - const ObjCMethodDecl *Overridden); +public: + /// When true, access checking violations are treated as SFINAE + /// failures rather than hard errors. + bool AccessCheckingSFINAE; - /// Describes the compatibility of a result type with its method. - enum ResultTypeCompatibilityKind { - RTC_Compatible, - RTC_Incompatible, - RTC_Unknown - }; + /// RAII class used to determine whether SFINAE has + /// trapped any errors that occur during template argument + /// deduction. + class SFINAETrap { + Sema &SemaRef; + unsigned PrevSFINAEErrors; + bool PrevInNonInstantiationSFINAEContext; + bool PrevAccessCheckingSFINAE; + bool PrevLastDiagnosticIgnored; - void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, - ObjCMethodDecl *overridden); + public: + explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false) + : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors), + PrevInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext), + PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE), + PrevLastDiagnosticIgnored( + SemaRef.getDiagnostics().isLastDiagnosticIgnored()) { + if (!SemaRef.isSFINAEContext()) + SemaRef.InNonInstantiationSFINAEContext = true; + SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE; + } - void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, - ObjCInterfaceDecl *CurrentClass, - ResultTypeCompatibilityKind RTC); + ~SFINAETrap() { + SemaRef.NumSFINAEErrors = PrevSFINAEErrors; + SemaRef.InNonInstantiationSFINAEContext = + PrevInNonInstantiationSFINAEContext; + SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE; + SemaRef.getDiagnostics().setLastDiagnosticIgnored( + PrevLastDiagnosticIgnored); + } - enum PragmaOptionsAlignKind { - POAK_Native, // #pragma options align=native - POAK_Natural, // #pragma options align=natural - POAK_Packed, // #pragma options align=packed - POAK_Power, // #pragma options align=power - POAK_Mac68k, // #pragma options align=mac68k - POAK_Reset // #pragma options align=reset + /// Determine whether any SFINAE errors have been trapped. + bool hasErrorOccurred() const { + return SemaRef.NumSFINAEErrors > PrevSFINAEErrors; + } }; - /// ActOnPragmaClangSection - Called on well formed \#pragma clang section - void ActOnPragmaClangSection(SourceLocation PragmaLoc, - PragmaClangSectionAction Action, - PragmaClangSectionKind SecKind, StringRef SecName); - - /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align. - void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, - SourceLocation PragmaLoc); - - /// ActOnPragmaPack - Called on well formed \#pragma pack(...). - void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, - StringRef SlotLabel, Expr *Alignment); + /// RAII class used to indicate that we are performing provisional + /// semantic analysis to determine the validity of a construct, so + /// typo-correction and diagnostics in the immediate context (not within + /// implicitly-instantiated templates) should be suppressed. + class TentativeAnalysisScope { + Sema &SemaRef; + // FIXME: Using a SFINAETrap for this is a hack. + SFINAETrap Trap; + bool PrevDisableTypoCorrection; - enum class PragmaAlignPackDiagnoseKind { - NonDefaultStateAtInclude, - ChangedStateAtExit + public: + explicit TentativeAnalysisScope(Sema &SemaRef) + : SemaRef(SemaRef), Trap(SemaRef, true), + PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) { + SemaRef.DisableTypoCorrection = true; + } + ~TentativeAnalysisScope() { + SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection; + } }; - void DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind, - SourceLocation IncludeLoc); - void DiagnoseUnterminatedPragmaAlignPack(); + /// For each declaration that involved template argument deduction, the + /// set of diagnostics that were suppressed during that template argument + /// deduction. + /// + /// FIXME: Serialize this structure to the AST file. + typedef llvm::DenseMap> + SuppressedDiagnosticsMap; + SuppressedDiagnosticsMap SuppressedDiagnostics; - /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma - /// strict_gs_check. - void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation, - PragmaMsStackAction Action, - bool Value); + bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg); - /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off]. - void ActOnPragmaMSStruct(PragmaMSStructKind Kind); + TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, + QualType NTTPType, + SourceLocation Loc); - /// ActOnPragmaMSComment - Called on well formed - /// \#pragma comment(kind, "arg"). - void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind, - StringRef Arg); + /// Get a template argument mapping the given template parameter to itself, + /// e.g. for X in \c template, this would return an expression template + /// argument referencing X. + TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, + SourceLocation Location); - /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma - /// pointers_to_members(representation method[, general purpose - /// representation]). - void ActOnPragmaMSPointersToMembers( - LangOptions::PragmaMSPointersToMembersKind Kind, - SourceLocation PragmaLoc); + /// Adjust the type \p ArgFunctionType to match the calling convention, + /// noreturn, and optionally the exception specification of \p FunctionType. + /// Deduction often wants to ignore these properties when matching function + /// types. + QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType, + bool AdjustExceptionSpec = false); - /// Called on well formed \#pragma vtordisp(). - void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, - SourceLocation PragmaLoc, - MSVtorDispMode Value); + TemplateDeductionResult + DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, + ArrayRef TemplateArgs, + sema::TemplateDeductionInfo &Info); - enum PragmaSectionKind { - PSK_DataSeg, - PSK_BSSSeg, - PSK_ConstSeg, - PSK_CodeSeg, - }; + TemplateDeductionResult + DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, + ArrayRef TemplateArgs, + sema::TemplateDeductionInfo &Info); - bool UnifySection(StringRef SectionName, int SectionFlags, - NamedDecl *TheDecl); - bool UnifySection(StringRef SectionName, - int SectionFlags, - SourceLocation PragmaSectionLocation); + TemplateDeductionResult SubstituteExplicitTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo &ExplicitTemplateArgs, + SmallVectorImpl &Deduced, + SmallVectorImpl &ParamTypes, QualType *FunctionType, + sema::TemplateDeductionInfo &Info); - /// Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg. - void ActOnPragmaMSSeg(SourceLocation PragmaLocation, - PragmaMsStackAction Action, - llvm::StringRef StackSlotLabel, - StringLiteral *SegmentName, - llvm::StringRef PragmaName); + /// brief A function argument from which we performed template argument + // deduction for a call. + struct OriginalCallArg { + OriginalCallArg(QualType OriginalParamType, bool DecomposedParam, + unsigned ArgIdx, QualType OriginalArgType) + : OriginalParamType(OriginalParamType), + DecomposedParam(DecomposedParam), ArgIdx(ArgIdx), + OriginalArgType(OriginalArgType) {} - /// Called on well formed \#pragma section(). - void ActOnPragmaMSSection(SourceLocation PragmaLocation, - int SectionFlags, StringLiteral *SegmentName); + QualType OriginalParamType; + bool DecomposedParam; + unsigned ArgIdx; + QualType OriginalArgType; + }; - /// Called on well-formed \#pragma init_seg(). - void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, - StringLiteral *SegmentName); + TemplateDeductionResult FinishTemplateArgumentDeduction( + FunctionTemplateDecl *FunctionTemplate, + SmallVectorImpl &Deduced, + unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info, + SmallVectorImpl const *OriginalCallArgs = nullptr, + bool PartialOverloading = false, + llvm::function_ref CheckNonDependent = [] { return false; }); - /// Called on well-formed \#pragma alloc_text(). - void ActOnPragmaMSAllocText( - SourceLocation PragmaLocation, StringRef Section, - const SmallVector> - &Functions); + TemplateDeductionResult DeduceTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, + FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, + bool PartialOverloading, bool AggregateDeductionCandidate, + QualType ObjectType, Expr::Classification ObjectClassification, + llvm::function_ref)> CheckNonDependent); - /// Called on #pragma clang __debug dump II - void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II); + TemplateDeductionResult DeduceTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, + FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, + bool IsAddressOfFunction = false); - /// Called on #pragma clang __debug dump E - void ActOnPragmaDump(Expr *E); + TemplateDeductionResult DeduceTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, QualType ObjectType, + Expr::Classification ObjectClassification, QualType ToType, + CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info); - /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch - void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, - StringRef Value); + TemplateDeductionResult + DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, + FunctionDecl *&Specialization, + sema::TemplateDeductionInfo &Info, + bool IsAddressOfFunction = false); - /// Are precise floating point semantics currently enabled? - bool isPreciseFPEnabled() { - return !CurFPFeatures.getAllowFPReassociate() && - !CurFPFeatures.getNoSignedZero() && - !CurFPFeatures.getAllowReciprocal() && - !CurFPFeatures.getAllowApproxFunc(); - } + /// Substitute Replacement for \p auto in \p TypeWithAuto + QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement); + /// Substitute Replacement for auto in TypeWithAuto + TypeSourceInfo *SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, + QualType Replacement); - void ActOnPragmaFPEvalMethod(SourceLocation Loc, - LangOptions::FPEvalMethodKind Value); + // Substitute auto in TypeWithAuto for a Dependent auto type + QualType SubstAutoTypeDependent(QualType TypeWithAuto); - /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control - void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action, - PragmaFloatControlKind Value); + // Substitute auto in TypeWithAuto for a Dependent auto type + TypeSourceInfo * + SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto); - /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'. - void ActOnPragmaUnused(const Token &Identifier, - Scope *curScope, - SourceLocation PragmaLoc); + /// Completely replace the \c auto in \p TypeWithAuto by + /// \p Replacement. This does not retain any \c auto type sugar. + QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement); + TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, + QualType Replacement); - /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... . - void ActOnPragmaVisibility(const IdentifierInfo* VisType, - SourceLocation PragmaLoc); + TemplateDeductionResult + DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result, + sema::TemplateDeductionInfo &Info, + bool DependentDeduction = false, + bool IgnoreConstraints = false, + TemplateSpecCandidateSet *FailedTSC = nullptr); + void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init); + bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, + bool Diagnose = true); - NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II, - SourceLocation Loc); - void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W); + bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD, + SourceLocation Loc); - /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident. - void ActOnPragmaWeakID(IdentifierInfo* WeakName, - SourceLocation PragmaLoc, - SourceLocation WeakNameLoc); + ClassTemplatePartialSpecializationDecl * + getMoreSpecializedPartialSpecialization( + ClassTemplatePartialSpecializationDecl *PS1, + ClassTemplatePartialSpecializationDecl *PS2, SourceLocation Loc); - /// ActOnPragmaRedefineExtname - Called on well formed - /// \#pragma redefine_extname oldname newname. - void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName, - IdentifierInfo* AliasName, - SourceLocation PragmaLoc, - SourceLocation WeakNameLoc, - SourceLocation AliasNameLoc); + bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T, + sema::TemplateDeductionInfo &Info); - /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident. - void ActOnPragmaWeakAlias(IdentifierInfo* WeakName, - IdentifierInfo* AliasName, - SourceLocation PragmaLoc, - SourceLocation WeakNameLoc, - SourceLocation AliasNameLoc); + VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization( + VarTemplatePartialSpecializationDecl *PS1, + VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc); - /// ActOnPragmaFPContract - Called on well formed - /// \#pragma {STDC,OPENCL} FP_CONTRACT and - /// \#pragma clang fp contract - void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC); + bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T, + sema::TemplateDeductionInfo &Info); - /// Called on well formed - /// \#pragma clang fp reassociate - /// or - /// \#pragma clang fp reciprocal - void ActOnPragmaFPValueChangingOption(SourceLocation Loc, PragmaFPKind Kind, - bool IsEnabled); + bool isTemplateTemplateParameterAtLeastAsSpecializedAs( + TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc); - /// ActOnPragmaFenvAccess - Called on well formed - /// \#pragma STDC FENV_ACCESS - void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled); + void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, + unsigned Depth, llvm::SmallBitVector &Used); - /// ActOnPragmaCXLimitedRange - Called on well formed - /// \#pragma STDC CX_LIMITED_RANGE - void ActOnPragmaCXLimitedRange(SourceLocation Loc, - LangOptions::ComplexRangeKind Range); + void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, + bool OnlyDeduced, unsigned Depth, + llvm::SmallBitVector &Used); + void + MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate, + llvm::SmallBitVector &Deduced) { + return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced); + } + static void + MarkDeducedTemplateParameters(ASTContext &Ctx, + const FunctionTemplateDecl *FunctionTemplate, + llvm::SmallBitVector &Deduced); - /// Called on well formed '\#pragma clang fp' that has option 'exceptions'. - void ActOnPragmaFPExceptions(SourceLocation Loc, - LangOptions::FPExceptionModeKind); + FunctionTemplateDecl *getMoreSpecializedTemplate( + FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc, + TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1, + unsigned NumCallArguments2, bool Reversed = false); + UnresolvedSetIterator + getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd, + TemplateSpecCandidateSet &FailedCandidates, + SourceLocation Loc, const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag, + bool Complain = true, QualType TargetType = QualType()); - /// Called to set constant rounding mode for floating point operations. - void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode); + ///@} - /// Called to set exception behavior for floating point operations. - void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind); + // + // + // ------------------------------------------------------------------------- + // + // - /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to - /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'. - void AddAlignmentAttributesForRecord(RecordDecl *RD); + /// \name C++ Template Instantiation + /// Implementations are in SemaTemplateInstantiate.cpp + ///@{ - /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record. - void AddMsStructLayoutForRecord(RecordDecl *RD); +public: + /// A helper class for building up ExtParameterInfos. + class ExtParameterInfoBuilder { + SmallVector Infos; + bool HasInteresting = false; - /// PushNamespaceVisibilityAttr - Note that we've entered a - /// namespace with a visibility attribute. - void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, - SourceLocation Loc); + public: + /// Set the ExtParameterInfo for the parameter at the given index, + /// + void set(unsigned index, FunctionProtoType::ExtParameterInfo info) { + assert(Infos.size() <= index); + Infos.resize(index); + Infos.push_back(info); - /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used, - /// add an appropriate visibility attribute. - void AddPushedVisibilityAttribute(Decl *RD); + if (!HasInteresting) + HasInteresting = (info != FunctionProtoType::ExtParameterInfo()); + } - /// PopPragmaVisibility - Pop the top element of the visibility stack; used - /// for '\#pragma GCC visibility' and visibility attributes on namespaces. - void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc); + /// Return a pointer (suitable for setting in an ExtProtoInfo) to the + /// ExtParameterInfo array we've built up. + const FunctionProtoType::ExtParameterInfo * + getPointerOrNull(unsigned numParams) { + if (!HasInteresting) + return nullptr; + Infos.resize(numParams); + return Infos.data(); + } + }; - /// FreeVisContext - Deallocate and null out VisContext. - void FreeVisContext(); + /// The current instantiation scope used to store local + /// variables. + LocalInstantiationScope *CurrentInstantiationScope; - /// AddCFAuditedAttribute - Check whether we're currently within - /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding - /// the appropriate attribute. - void AddCFAuditedAttribute(Decl *D); + typedef llvm::DenseMap> + UnparsedDefaultArgInstantiationsMap; - void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute, - SourceLocation PragmaLoc, - attr::ParsedSubjectMatchRuleSet Rules); - void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, - const IdentifierInfo *Namespace); + /// A mapping from parameters with unparsed default arguments to the + /// set of instantiations of each parameter. + /// + /// This mapping is a temporary data structure used when parsing + /// nested class templates or nested classes of class templates, + /// where we might end up instantiating an inner class before the + /// default arguments of its methods have been parsed. + UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations; - /// Called on well-formed '\#pragma clang attribute pop'. - void ActOnPragmaAttributePop(SourceLocation PragmaLoc, - const IdentifierInfo *Namespace); + /// A context in which code is being synthesized (where a source location + /// alone is not sufficient to identify the context). This covers template + /// instantiation and various forms of implicitly-generated functions. + struct CodeSynthesisContext { + /// The kind of template instantiation we are performing + enum SynthesisKind { + /// We are instantiating a template declaration. The entity is + /// the declaration we're instantiating (e.g., a CXXRecordDecl). + TemplateInstantiation, - /// Adds the attributes that have been specified using the - /// '\#pragma clang attribute push' directives to the given declaration. - void AddPragmaAttributes(Scope *S, Decl *D); + /// We are instantiating a default argument for a template + /// parameter. The Entity is the template parameter whose argument is + /// being instantiated, the Template is the template, and the + /// TemplateArgs/NumTemplateArguments provide the template arguments as + /// specified. + DefaultTemplateArgumentInstantiation, - void DiagnoseUnterminatedPragmaAttribute(); + /// We are instantiating a default argument for a function. + /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs + /// provides the template arguments as specified. + DefaultFunctionArgumentInstantiation, - /// Called on well formed \#pragma clang optimize. - void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc); + /// We are substituting explicit template arguments provided for + /// a function template. The entity is a FunctionTemplateDecl. + ExplicitTemplateArgumentSubstitution, - /// #pragma optimize("[optimization-list]", on | off). - void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn); + /// We are substituting template argument determined as part of + /// template argument deduction for either a class template + /// partial specialization or a function template. The + /// Entity is either a {Class|Var}TemplatePartialSpecializationDecl or + /// a TemplateDecl. + DeducedTemplateArgumentSubstitution, - /// Call on well formed \#pragma function. - void - ActOnPragmaMSFunction(SourceLocation Loc, - const llvm::SmallVectorImpl &NoBuiltins); + /// We are substituting into a lambda expression. + LambdaExpressionSubstitution, - /// Get the location for the currently active "\#pragma clang optimize - /// off". If this location is invalid, then the state of the pragma is "on". - SourceLocation getOptimizeOffPragmaLocation() const { - return OptimizeOffPragmaLocation; - } + /// We are substituting prior template arguments into a new + /// template parameter. The template parameter itself is either a + /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl. + PriorTemplateArgumentSubstitution, - /// Only called on function definitions; if there is a pragma in scope - /// with the effect of a range-based optnone, consider marking the function - /// with attribute optnone. - void AddRangeBasedOptnone(FunctionDecl *FD); + /// We are checking the validity of a default template argument that + /// has been used when naming a template-id. + DefaultTemplateArgumentChecking, - /// Only called on function definitions; if there is a `#pragma alloc_text` - /// that decides which code section the function should be in, add - /// attribute section to the function. - void AddSectionMSAllocText(FunctionDecl *FD); + /// We are computing the exception specification for a defaulted special + /// member function. + ExceptionSpecEvaluation, - /// Adds the 'optnone' attribute to the function declaration if there - /// are no conflicts; Loc represents the location causing the 'optnone' - /// attribute to be added (usually because of a pragma). - void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc); + /// We are instantiating the exception specification for a function + /// template which was deferred until it was needed. + ExceptionSpecInstantiation, - /// Only called on function definitions; if there is a MSVC #pragma optimize - /// in scope, consider changing the function's attributes based on the - /// optimization list passed to the pragma. - void ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD); + /// We are instantiating a requirement of a requires expression. + RequirementInstantiation, - /// Only called on function definitions; if there is a pragma in scope - /// with the effect of a range-based no_builtin, consider marking the function - /// with attribute no_builtin. - void AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD); + /// We are checking the satisfaction of a nested requirement of a requires + /// expression. + NestedRequirementConstraintsCheck, - /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. - void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, - bool IsPackExpansion); - void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, TypeSourceInfo *T, - bool IsPackExpansion); + /// We are declaring an implicit special member function. + DeclaringSpecialMember, - /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular - /// declaration. - void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, - Expr *OE); + /// We are declaring an implicit 'operator==' for a defaulted + /// 'operator<=>'. + DeclaringImplicitEqualityComparison, - /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular - /// declaration. - void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI, - Expr *ParamExpr); + /// We are defining a synthesized function (such as a defaulted special + /// member). + DefiningSynthesizedFunction, - /// AddAlignValueAttr - Adds an align_value attribute to a particular - /// declaration. - void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E); + // We are checking the constraints associated with a constrained entity or + // the constraint expression of a concept. This includes the checks that + // atomic constraints have the type 'bool' and that they can be constant + // evaluated. + ConstraintsCheck, - /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D. - void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI, - StringRef Annot, MutableArrayRef Args); + // We are substituting template arguments into a constraint expression. + ConstraintSubstitution, - /// ConstantFoldAttrArgs - Folds attribute arguments into ConstantExprs - /// (unless they are value dependent or type dependent). Returns false - /// and emits a diagnostic if one or more of the arguments could not be - /// folded into a constant. - bool ConstantFoldAttrArgs(const AttributeCommonInfo &CI, - MutableArrayRef Args); + // We are normalizing a constraint expression. + ConstraintNormalization, - /// Create an CUDALaunchBoundsAttr attribute. - CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, - Expr *MaxThreads, - Expr *MinBlocks, - Expr *MaxBlocks); + // Instantiating a Requires Expression parameter clause. + RequirementParameterInstantiation, - /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular - /// declaration. - void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI, - Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks); + // We are substituting into the parameter mapping of an atomic constraint + // during normalization. + ParameterMappingSubstitution, - /// AddModeAttr - Adds a mode attribute to a particular declaration. - void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name, - bool InInstantiation = false); + /// We are rewriting a comparison operator in terms of an operator<=>. + RewritingOperatorAsSpaceship, - void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI, - ParameterABI ABI); + /// We are initializing a structured binding. + InitializingStructuredBinding, - enum class RetainOwnershipKind {NS, CF, OS}; - void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI, - RetainOwnershipKind K, bool IsTemplateInstantiation); + /// We are marking a class as __dllexport. + MarkingClassDllexported, - /// Create an AMDGPUWavesPerEUAttr attribute. - AMDGPUFlatWorkGroupSizeAttr * - CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, - Expr *Max); + /// We are building an implied call from __builtin_dump_struct. The + /// arguments are in CallArgs. + BuildingBuiltinDumpStructCall, - /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size - /// attribute to a particular declaration. - void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI, - Expr *Min, Expr *Max); + /// Added for Template instantiation observation. + /// Memoization means we are _not_ instantiating a template because + /// it is already instantiated (but we entered a context where we + /// would have had to if it was not already instantiated). + Memoization, - /// Create an AMDGPUWavesPerEUAttr attribute. - AMDGPUWavesPerEUAttr * - CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, - Expr *Max); + /// We are building deduction guides for a class. + BuildingDeductionGuides, + } Kind; - /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a - /// particular declaration. - void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI, - Expr *Min, Expr *Max); + /// Was the enclosing context a non-instantiation SFINAE context? + bool SavedInNonInstantiationSFINAEContext; - bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type); + /// The point of instantiation or synthesis within the source code. + SourceLocation PointOfInstantiation; - //===--------------------------------------------------------------------===// - // C++ Coroutines - // - bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, - StringRef Keyword); - ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E); - ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E); - StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E); + /// The entity that is being synthesized. + Decl *Entity; - ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc); - ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E, - UnresolvedLookupExpr *Lookup); - ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, - Expr *Awaiter, bool IsImplicit = false); - ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, - UnresolvedLookupExpr *Lookup); - ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E); - StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, - bool IsImplicit = false); - StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs); - bool buildCoroutineParameterMoves(SourceLocation Loc); - VarDecl *buildCoroutinePromise(SourceLocation Loc); - void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); + /// The template (or partial specialization) in which we are + /// performing the instantiation, for substitutions of prior template + /// arguments. + NamedDecl *Template; - // Heuristically tells if the function is `get_return_object` member of a - // coroutine promise_type by matching the function name. - static bool CanBeGetReturnObject(const FunctionDecl *FD); - static bool CanBeGetReturnTypeOnAllocFailure(const FunctionDecl *FD); + union { + /// The list of template arguments we are substituting, if they + /// are not part of the entity. + const TemplateArgument *TemplateArgs; - // As a clang extension, enforces that a non-coroutine function must be marked - // with [[clang::coro_wrapper]] if it returns a type marked with - // [[clang::coro_return_type]]. - // Expects that FD is not a coroutine. - void CheckCoroutineWrapper(FunctionDecl *FD); - /// Lookup 'coroutine_traits' in std namespace and std::experimental - /// namespace. The namespace found is recorded in Namespace. - ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, - SourceLocation FuncLoc); - /// Check that the expression co_await promise.final_suspend() shall not be - /// potentially-throwing. - bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend); + /// The list of argument expressions in a synthesized call. + const Expr *const *CallArgs; + }; - //===--------------------------------------------------------------------===// - // OpenMP directives and clauses. - // -private: - void *VarDataSharingAttributesStack; + // FIXME: Wrap this union around more members, or perhaps store the + // kind-specific members in the RAII object owning the context. + union { + /// The number of template arguments in TemplateArgs. + unsigned NumTemplateArgs; - struct DeclareTargetContextInfo { - struct MapInfo { - OMPDeclareTargetDeclAttr::MapTypeTy MT; - SourceLocation Loc; + /// The number of expressions in CallArgs. + unsigned NumCallArgs; + + /// The special member being declared or defined. + CXXSpecialMember SpecialMember; }; - /// Explicitly listed variables and functions in a 'to' or 'link' clause. - llvm::DenseMap ExplicitlyMapped; - /// The 'device_type' as parsed from the clause. - OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; + ArrayRef template_arguments() const { + assert(Kind != DeclaringSpecialMember); + return {TemplateArgs, NumTemplateArgs}; + } - /// The directive kind, `begin declare target` or `declare target`. - OpenMPDirectiveKind Kind; + /// The template deduction info object associated with the + /// substitution or checking of explicit or deduced template arguments. + sema::TemplateDeductionInfo *DeductionInfo; - /// The directive with indirect clause. - std::optional Indirect; + /// The source range that covers the construct that cause + /// the instantiation, e.g., the template-id that causes a class + /// template instantiation. + SourceRange InstantiationRange; - /// The directive location. - SourceLocation Loc; + CodeSynthesisContext() + : Kind(TemplateInstantiation), + SavedInNonInstantiationSFINAEContext(false), Entity(nullptr), + Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0), + DeductionInfo(nullptr) {} - DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc) - : Kind(Kind), Loc(Loc) {} + /// Determines whether this template is an actual instantiation + /// that should be counted toward the maximum instantiation depth. + bool isInstantiationRecord() const; }; - /// Number of nested '#pragma omp declare target' directives. - SmallVector DeclareTargetNesting; - - /// Initialization of data-sharing attributes stack. - void InitDataSharingAttributesStack(); - void DestroyDataSharingAttributesStack(); + /// A stack object to be created when performing template + /// instantiation. + /// + /// Construction of an object of type \c InstantiatingTemplate + /// pushes the current instantiation onto the stack of active + /// instantiations. If the size of this stack exceeds the maximum + /// number of recursive template instantiations, construction + /// produces an error and evaluates true. + /// + /// Destruction of this object will pop the named instantiation off + /// the stack. + struct InstantiatingTemplate { + /// Note that we are instantiating a class template, + /// function template, variable template, alias template, + /// or a member thereof. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + Decl *Entity, + SourceRange InstantiationRange = SourceRange()); - /// Returns OpenMP nesting level for current directive. - unsigned getOpenMPNestingLevel() const; + struct ExceptionSpecification {}; + /// Note that we are instantiating an exception specification + /// of a function template. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + FunctionDecl *Entity, ExceptionSpecification, + SourceRange InstantiationRange = SourceRange()); - /// Adjusts the function scopes index for the target-based regions. - void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex, - unsigned Level) const; + /// Note that we are instantiating a default argument in a + /// template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateParameter Param, TemplateDecl *Template, + ArrayRef TemplateArgs, + SourceRange InstantiationRange = SourceRange()); - /// Returns the number of scopes associated with the construct on the given - /// OpenMP level. - int getNumberOfConstructScopes(unsigned Level) const; + /// Note that we are substituting either explicitly-specified or + /// deduced template arguments during function template argument deduction. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + FunctionTemplateDecl *FunctionTemplate, + ArrayRef TemplateArgs, + CodeSynthesisContext::SynthesisKind Kind, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange = SourceRange()); - /// Push new OpenMP function region for non-capturing function. - void pushOpenMPFunctionRegion(); + /// Note that we are instantiating as part of template + /// argument deduction for a class template declaration. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + ArrayRef TemplateArgs, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange = SourceRange()); - /// Pop OpenMP function region for non-capturing function. - void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI); + /// Note that we are instantiating as part of template + /// argument deduction for a class template partial + /// specialization. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ClassTemplatePartialSpecializationDecl *PartialSpec, + ArrayRef TemplateArgs, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange = SourceRange()); - /// Analyzes and checks a loop nest for use by a loop transformation. - /// - /// \param Kind The loop transformation directive kind. - /// \param NumLoops How many nested loops the directive is expecting. - /// \param AStmt Associated statement of the transformation directive. - /// \param LoopHelpers [out] The loop analysis result. - /// \param Body [out] The body code nested in \p NumLoops loop. - /// \param OriginalInits [out] Collection of statements and declarations that - /// must have been executed/declared before entering the - /// loop. - /// - /// \return Whether there was any error. - bool checkTransformableLoopNest( - OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, - SmallVectorImpl &LoopHelpers, - Stmt *&Body, - SmallVectorImpl, 0>> - &OriginalInits); + /// Note that we are instantiating as part of template + /// argument deduction for a variable template partial + /// specialization. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + VarTemplatePartialSpecializationDecl *PartialSpec, + ArrayRef TemplateArgs, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange = SourceRange()); - /// Helper to keep information about the current `omp begin/end declare - /// variant` nesting. - struct OMPDeclareVariantScope { - /// The associated OpenMP context selector. - OMPTraitInfo *TI; + /// Note that we are instantiating a default argument for a function + /// parameter. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ParmVarDecl *Param, + ArrayRef TemplateArgs, + SourceRange InstantiationRange = SourceRange()); - /// The associated OpenMP context selector mangling. - std::string NameSuffix; + /// Note that we are substituting prior template arguments into a + /// non-type parameter. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + NamedDecl *Template, NonTypeTemplateParmDecl *Param, + ArrayRef TemplateArgs, + SourceRange InstantiationRange); - OMPDeclareVariantScope(OMPTraitInfo &TI); - }; + /// Note that we are substituting prior template arguments into a + /// template template parameter. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + NamedDecl *Template, TemplateTemplateParmDecl *Param, + ArrayRef TemplateArgs, + SourceRange InstantiationRange); - /// Return the OMPTraitInfo for the surrounding scope, if any. - OMPTraitInfo *getOMPTraitInfoForSurroundingScope() { - return OMPDeclareVariantScopes.empty() ? nullptr - : OMPDeclareVariantScopes.back().TI; - } + /// Note that we are checking the default template argument + /// against the template parameter for a given template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, NamedDecl *Param, + ArrayRef TemplateArgs, + SourceRange InstantiationRange); - /// The current `omp begin/end declare variant` scopes. - SmallVector OMPDeclareVariantScopes; + struct ConstraintsCheck {}; + /// \brief Note that we are checking the constraints associated with some + /// constrained entity (a concept declaration or a template with associated + /// constraints). + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ConstraintsCheck, NamedDecl *Template, + ArrayRef TemplateArgs, + SourceRange InstantiationRange); - /// The current `omp begin/end assumes` scopes. - SmallVector OMPAssumeScoped; + struct ConstraintSubstitution {}; + /// \brief Note that we are checking a constraint expression associated + /// with a template declaration or as part of the satisfaction check of a + /// concept. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ConstraintSubstitution, NamedDecl *Template, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange); - /// All `omp assumes` we encountered so far. - SmallVector OMPAssumeGlobal; + struct ConstraintNormalization {}; + /// \brief Note that we are normalizing a constraint expression. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ConstraintNormalization, NamedDecl *Template, + SourceRange InstantiationRange); - /// OMPD_loop is mapped to OMPD_for, OMPD_distribute or OMPD_simd depending - /// on the parameter of the bind clause. In the methods for the - /// mapped directives, check the parameters of the lastprivate clause. - bool checkLastPrivateForMappedDirectives(ArrayRef Clauses); - /// Depending on the bind clause of OMPD_loop map the directive to new - /// directives. - /// 1) loop bind(parallel) --> OMPD_for - /// 2) loop bind(teams) --> OMPD_distribute - /// 3) loop bind(thread) --> OMPD_simd - /// This is being handled in Sema instead of Codegen because of the need for - /// rigorous semantic checking in the new mapped directives. - bool mapLoopConstruct(llvm::SmallVector &ClausesWithoutBind, - ArrayRef Clauses, - OpenMPBindClauseKind &BindKind, - OpenMPDirectiveKind &Kind, - OpenMPDirectiveKind &PrevMappedDirective, - SourceLocation StartLoc, SourceLocation EndLoc, - const DeclarationNameInfo &DirName, - OpenMPDirectiveKind CancelRegion); + struct ParameterMappingSubstitution {}; + /// \brief Note that we are subtituting into the parameter mapping of an + /// atomic constraint during constraint normalization. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + ParameterMappingSubstitution, NamedDecl *Template, + SourceRange InstantiationRange); -public: - /// The declarator \p D defines a function in the scope \p S which is nested - /// in an `omp begin/end declare variant` scope. In this method we create a - /// declaration for \p D and rename \p D according to the OpenMP context - /// selector of the surrounding scope. Return all base functions in \p Bases. - void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope( - Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, - SmallVectorImpl &Bases); + /// \brief Note that we are substituting template arguments into a part of + /// a requirement of a requires expression. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + concepts::Requirement *Req, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange = SourceRange()); - /// Register \p D as specialization of all base functions in \p Bases in the - /// current `omp begin/end declare variant` scope. - void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( - Decl *D, SmallVectorImpl &Bases); + /// \brief Note that we are checking the satisfaction of the constraint + /// expression inside of a nested requirement. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + concepts::NestedRequirement *Req, ConstraintsCheck, + SourceRange InstantiationRange = SourceRange()); - /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`. - void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D); + /// \brief Note that we are checking a requires clause. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + const RequiresExpr *E, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange); - /// Can we exit an OpenMP declare variant scope at the moment. - bool isInOpenMPDeclareVariantScope() const { - return !OMPDeclareVariantScopes.empty(); - } + struct BuildingDeductionGuidesTag {}; + /// \brief Note that we are building deduction guides. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Entity, BuildingDeductionGuidesTag, + SourceRange InstantiationRange = SourceRange()); - ExprResult - VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, - bool StrictlyPositive = true, - bool SuppressExprDiags = false); + /// Note that we have finished instantiating this template. + void Clear(); - /// Given the potential call expression \p Call, determine if there is a - /// specialization via the OpenMP declare variant mechanism available. If - /// there is, return the specialized call expression, otherwise return the - /// original \p Call. - ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, - SourceLocation LParenLoc, MultiExprArg ArgExprs, - SourceLocation RParenLoc, Expr *ExecConfig); + ~InstantiatingTemplate() { Clear(); } - /// Handle a `omp begin declare variant`. - void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI); + /// Determines whether we have exceeded the maximum + /// recursive template instantiations. + bool isInvalid() const { return Invalid; } - /// Handle a `omp end declare variant`. - void ActOnOpenMPEndDeclareVariant(); + /// Determine whether we are already instantiating this + /// specialization in some surrounding active instantiation. + bool isAlreadyInstantiating() const { return AlreadyInstantiating; } - /// Checks if the variant/multiversion functions are compatible. - bool areMultiversionVariantFunctionsCompatible( - const FunctionDecl *OldFD, const FunctionDecl *NewFD, - const PartialDiagnostic &NoProtoDiagID, - const PartialDiagnosticAt &NoteCausedDiagIDAt, - const PartialDiagnosticAt &NoSupportDiagIDAt, - const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported, - bool ConstexprSupported, bool CLinkageMayDiffer); + private: + Sema &SemaRef; + bool Invalid; + bool AlreadyInstantiating; + bool CheckInstantiationDepth(SourceLocation PointOfInstantiation, + SourceRange InstantiationRange); - /// Function tries to capture lambda's captured variables in the OpenMP region - /// before the original lambda is captured. - void tryCaptureOpenMPLambdas(ValueDecl *V); + InstantiatingTemplate( + Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind, + SourceLocation PointOfInstantiation, SourceRange InstantiationRange, + Decl *Entity, NamedDecl *Template = nullptr, + ArrayRef TemplateArgs = std::nullopt, + sema::TemplateDeductionInfo *DeductionInfo = nullptr); - /// Return true if the provided declaration \a VD should be captured by - /// reference. - /// \param Level Relative level of nested OpenMP construct for that the check - /// is performed. - /// \param OpenMPCaptureLevel Capture level within an OpenMP construct. - bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, - unsigned OpenMPCaptureLevel) const; + InstantiatingTemplate(const InstantiatingTemplate &) = delete; - /// Check if the specified variable is used in one of the private - /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP - /// constructs. - VarDecl *isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo = false, - unsigned StopAt = 0); + InstantiatingTemplate &operator=(const InstantiatingTemplate &) = delete; + }; - /// The member expression(this->fd) needs to be rebuilt in the template - /// instantiation to generate private copy for OpenMP when default - /// clause is used. The function will return true if default - /// cluse is used. - bool isOpenMPRebuildMemberExpr(ValueDecl *D); + bool + SubstTemplateArguments(ArrayRef Args, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateArgumentListInfo &Outputs); - ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, - ExprObjectKind OK, SourceLocation Loc); + MultiLevelTemplateArgumentList getTemplateInstantiationArgs( + const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false, + std::optional> Innermost = std::nullopt, + bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, + bool ForConstraintInstantiation = false, + bool SkipForSpecialization = false); - /// If the current region is a loop-based region, mark the start of the loop - /// construct. - void startOpenMPLoop(); + /// RAII object to handle the state changes required to synthesize + /// a function body. + class SynthesizedFunctionScope { + Sema &S; + Sema::ContextRAII SavedContext; + bool PushedCodeSynthesisContext = false; - /// If the current region is a range loop-based region, mark the start of the - /// loop construct. - void startOpenMPCXXRangeFor(); + public: + SynthesizedFunctionScope(Sema &S, DeclContext *DC) + : S(S), SavedContext(S, DC) { + auto *FD = dyn_cast(DC); + S.PushFunctionScope(); + S.PushExpressionEvaluationContext( + (FD && FD->isConsteval()) + ? ExpressionEvaluationContext::ImmediateFunctionContext + : ExpressionEvaluationContext::PotentiallyEvaluated); + if (FD) { + FD->setWillHaveBody(true); + S.ExprEvalContexts.back().InImmediateFunctionContext = + FD->isImmediateFunction() || + S.ExprEvalContexts[S.ExprEvalContexts.size() - 2] + .isConstantEvaluated(); + S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext = + S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating(); + } else + assert(isa(DC)); + } - /// Check if the specified variable is used in 'private' clause. - /// \param Level Relative level of nested OpenMP construct for that the check - /// is performed. - OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, - unsigned CapLevel) const; + void addContextNote(SourceLocation UseLoc) { + assert(!PushedCodeSynthesisContext); - /// Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) - /// for \p FD based on DSA for the provided corresponding captured declaration - /// \p D. - void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level); + Sema::CodeSynthesisContext Ctx; + Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction; + Ctx.PointOfInstantiation = UseLoc; + Ctx.Entity = cast(S.CurContext); + S.pushCodeSynthesisContext(Ctx); - /// Check if the specified variable is captured by 'target' directive. - /// \param Level Relative level of nested OpenMP construct for that the check - /// is performed. - bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, - unsigned CaptureLevel) const; + PushedCodeSynthesisContext = true; + } - /// Check if the specified global variable must be captured by outer capture - /// regions. - /// \param Level Relative level of nested OpenMP construct for that - /// the check is performed. - bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, - unsigned CaptureLevel) const; + ~SynthesizedFunctionScope() { + if (PushedCodeSynthesisContext) + S.popCodeSynthesisContext(); + if (auto *FD = dyn_cast(S.CurContext)) { + FD->setWillHaveBody(false); + S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction()); + } + S.PopExpressionEvaluationContext(); + S.PopFunctionScopeInfo(); + } + }; - ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, - Expr *Op); - /// Called on start of new data sharing attribute block. - void StartOpenMPDSABlock(OpenMPDirectiveKind K, - const DeclarationNameInfo &DirName, Scope *CurScope, - SourceLocation Loc); - /// Start analysis of clauses. - void StartOpenMPClause(OpenMPClauseKind K); - /// End analysis of clauses. - void EndOpenMPClause(); - /// Called on end of data sharing attribute block. - void EndOpenMPDSABlock(Stmt *CurDirective); + /// List of active code synthesis contexts. + /// + /// This vector is treated as a stack. As synthesis of one entity requires + /// synthesis of another, additional contexts are pushed onto the stack. + SmallVector CodeSynthesisContexts; - /// Check if the current region is an OpenMP loop region and if it is, - /// mark loop control variable, used in \p Init for loop initialization, as - /// private by default. - /// \param Init First part of the for loop. - void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init); + /// Specializations whose definitions are currently being instantiated. + llvm::DenseSet> InstantiatingSpecializations; - /// Called on well-formed '\#pragma omp metadirective' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPMetaDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); + /// Non-dependent types used in templates that have already been instantiated + /// by some template instantiation. + llvm::DenseSet InstantiatedNonDependentTypes; - // OpenMP directives and clauses. - /// Called on correct id-expression from the '#pragma omp - /// threadprivate'. - ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, - const DeclarationNameInfo &Id, - OpenMPDirectiveKind Kind); - /// Called on well-formed '#pragma omp threadprivate'. - DeclGroupPtrTy ActOnOpenMPThreadprivateDirective( - SourceLocation Loc, - ArrayRef VarList); - /// Builds a new OpenMPThreadPrivateDecl and checks its correctness. - OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc, - ArrayRef VarList); - /// Called on well-formed '#pragma omp allocate'. - DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, - ArrayRef VarList, - ArrayRef Clauses, - DeclContext *Owner = nullptr); + /// Extra modules inspected when performing a lookup during a template + /// instantiation. Computed lazily. + SmallVector CodeSynthesisContextLookupModules; - /// Called on well-formed '#pragma omp [begin] assume[s]'. - void ActOnOpenMPAssumesDirective(SourceLocation Loc, - OpenMPDirectiveKind DKind, - ArrayRef Assumptions, - bool SkippedClauses); + /// Cache of additional modules that should be used for name lookup + /// within the current template instantiation. Computed lazily; use + /// getLookupModules() to get a complete set. + llvm::DenseSet LookupModulesCache; - /// Check if there is an active global `omp begin assumes` directive. - bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); } + /// Map from the most recent declaration of a namespace to the most + /// recent visible declaration of that namespace. + llvm::DenseMap VisibleNamespaceCache; - /// Check if there is an active global `omp assumes` directive. - bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); } + /// Whether we are in a SFINAE context that is not associated with + /// template instantiation. + /// + /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside + /// of a template instantiation or template argument deduction. + bool InNonInstantiationSFINAEContext; - /// Called on well-formed '#pragma omp end assumes'. - void ActOnOpenMPEndAssumesDirective(); + /// The number of \p CodeSynthesisContexts that are not template + /// instantiations and, therefore, should not be counted as part of the + /// instantiation depth. + /// + /// When the instantiation depth reaches the user-configurable limit + /// \p LangOptions::InstantiationDepth we will abort instantiation. + // FIXME: Should we have a similar limit for other forms of synthesis? + unsigned NonInstantiationEntries; - /// Called on well-formed '#pragma omp requires'. - DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, - ArrayRef ClauseList); - /// Check restrictions on Requires directive - OMPRequiresDecl *CheckOMPRequiresDecl(SourceLocation Loc, - ArrayRef Clauses); - /// Check if the specified type is allowed to be used in 'omp declare - /// reduction' construct. - QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, - TypeResult ParsedType); - /// Called on start of '#pragma omp declare reduction'. - DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart( - Scope *S, DeclContext *DC, DeclarationName Name, - ArrayRef> ReductionTypes, - AccessSpecifier AS, Decl *PrevDeclInScope = nullptr); - /// Initialize declare reduction construct initializer. - void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D); - /// Finish current declare reduction construct initializer. - void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner); - /// Initialize declare reduction construct initializer. - /// \return omp_priv variable. - VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); - /// Finish current declare reduction construct initializer. - void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, - VarDecl *OmpPrivParm); - /// Called at the end of '#pragma omp declare reduction'. - DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd( - Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid); + /// The depth of the context stack at the point when the most recent + /// error or warning was produced. + /// + /// This value is used to suppress printing of redundant context stacks + /// when there are multiple errors or warnings in the same instantiation. + // FIXME: Does this belong in Sema? It's tough to implement it anywhere else. + unsigned LastEmittedCodeSynthesisContextDepth = 0; - /// Check variable declaration in 'omp declare mapper' construct. - TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D); - /// Check if the specified type is allowed to be used in 'omp declare - /// mapper' construct. - QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, - TypeResult ParsedType); - /// Called on start of '#pragma omp declare mapper'. - DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective( - Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, - SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, - Expr *MapperVarRef, ArrayRef Clauses, - Decl *PrevDeclInScope = nullptr); - /// Build the mapper variable of '#pragma omp declare mapper'. - ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, - QualType MapperType, - SourceLocation StartLoc, - DeclarationName VN); - void ActOnOpenMPIteratorVarDecl(VarDecl *VD); - bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const; - const ValueDecl *getOpenMPDeclareMapperVarName() const; + /// The template instantiation callbacks to trace or track + /// instantiations (objects can be chained). + /// + /// This callbacks is used to print, trace or track template + /// instantiations as they are being constructed. + std::vector> + TemplateInstCallbacks; - /// Called on the start of target region i.e. '#pragma omp declare target'. - bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI); + /// The current index into pack expansion arguments that will be + /// used for substitution of parameter packs. + /// + /// The pack expansion index will be -1 to indicate that parameter packs + /// should be instantiated as themselves. Otherwise, the index specifies + /// which argument within the parameter pack will be used for substitution. + int ArgumentPackSubstitutionIndex; - /// Called at the end of target region i.e. '#pragma omp end declare target'. - const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective(); + /// RAII object used to change the argument pack substitution index + /// within a \c Sema object. + /// + /// See \c ArgumentPackSubstitutionIndex for more information. + class ArgumentPackSubstitutionIndexRAII { + Sema &Self; + int OldSubstitutionIndex; - /// Called once a target context is completed, that can be when a - /// '#pragma omp end declare target' was encountered or when a - /// '#pragma omp declare target' without declaration-definition-seq was - /// encountered. - void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI); + public: + ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex) + : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) { + Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex; + } - /// Report unterminated 'omp declare target' or 'omp begin declare target' at - /// the end of a compilation unit. - void DiagnoseUnterminatedOpenMPDeclareTarget(); + ~ArgumentPackSubstitutionIndexRAII() { + Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex; + } + }; - /// Searches for the provided declaration name for OpenMP declare target - /// directive. - NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope, - CXXScopeSpec &ScopeSpec, - const DeclarationNameInfo &Id); + friend class ArgumentPackSubstitutionRAII; - /// Called on correct id-expression from the '#pragma omp declare target'. - void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, - OMPDeclareTargetDeclAttr::MapTypeTy MT, - DeclareTargetContextInfo &DTCI); + void pushCodeSynthesisContext(CodeSynthesisContext Ctx); + void popCodeSynthesisContext(); - /// Check declaration inside target region. - void - checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, - SourceLocation IdLoc = SourceLocation()); + void PrintContextStack() { + if (!CodeSynthesisContexts.empty() && + CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) { + PrintInstantiationStack(); + LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size(); + } + if (PragmaAttributeCurrentTargetDecl) + PrintPragmaAttributeInstantiationPoint(); + } + void PrintInstantiationStack(); - /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target - /// directive. - void ActOnOpenMPDeclareTargetInitializer(Decl *D); + /// Determines whether we are currently in a context where + /// template argument substitution failures are not considered + /// errors. + /// + /// \returns An empty \c Optional if we're not in a SFINAE context. + /// Otherwise, contains a pointer that, if non-NULL, contains the nearest + /// template-deduction context object, which can be used to capture + /// diagnostics that will be suppressed. + std::optional isSFINAEContext() const; - /// Finishes analysis of the deferred functions calls that may be declared as - /// host/nohost during device/host compilation. - void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, - const FunctionDecl *Callee, - SourceLocation Loc); + TypeSourceInfo *SubstType(TypeSourceInfo *T, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, DeclarationName Entity, + bool AllowDeducedTST = false); - /// Return true if currently in OpenMP task with untied clause context. - bool isInOpenMPTaskUntiedContext() const; + QualType SubstType(QualType T, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, DeclarationName Entity); - /// Return true inside OpenMP declare target region. - bool isInOpenMPDeclareTargetContext() const { - return !DeclareTargetNesting.empty(); - } - /// Return true inside OpenMP target region. - bool isInOpenMPTargetExecutionDirective() const; + TypeSourceInfo *SubstType(TypeLoc TL, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, DeclarationName Entity); - /// Return the number of captured regions created for an OpenMP directive. - static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind); + TypeSourceInfo *SubstFunctionDeclType( + TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext, + Qualifiers ThisTypeQuals, bool EvaluateConstraints = true); + void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, + const MultiLevelTemplateArgumentList &Args); + bool SubstExceptionSpec(SourceLocation Loc, + FunctionProtoType::ExceptionSpecInfo &ESI, + SmallVectorImpl &ExceptionStorage, + const MultiLevelTemplateArgumentList &Args); + ParmVarDecl * + SubstParmVarDecl(ParmVarDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs, + int indexAdjustment, std::optional NumExpansions, + bool ExpectParameterPack, bool EvaluateConstraints = true); + bool SubstParmTypes(SourceLocation Loc, ArrayRef Params, + const FunctionProtoType::ExtParameterInfo *ExtParamInfos, + const MultiLevelTemplateArgumentList &TemplateArgs, + SmallVectorImpl &ParamTypes, + SmallVectorImpl *OutParams, + ExtParameterInfoBuilder &ParamInfos); + bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool ForCallExpr = false); + ExprResult SubstExpr(Expr *E, + const MultiLevelTemplateArgumentList &TemplateArgs); - /// Initialization of captured region for OpenMP region. - void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope); + // A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator + // to disable constraint evaluation, then restore the state. + template struct ConstraintEvalRAII { + InstTy &TI; + bool OldValue; - /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to - /// an OpenMP loop directive. - StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt); + ConstraintEvalRAII(InstTy &TI) + : TI(TI), OldValue(TI.getEvaluateConstraints()) { + TI.setEvaluateConstraints(false); + } + ~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); } + }; - /// Process a canonical OpenMP loop nest that can either be a canonical - /// literal loop (ForStmt or CXXForRangeStmt), or the generated loop of an - /// OpenMP loop transformation construct. - StmtResult ActOnOpenMPLoopnest(Stmt *AStmt); + // Must be used instead of SubstExpr at 'constraint checking' time. + ExprResult + SubstConstraintExpr(Expr *E, + const MultiLevelTemplateArgumentList &TemplateArgs); + // Unlike the above, this does not evaluates constraints. + ExprResult SubstConstraintExprWithoutSatisfaction( + Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); - /// End of OpenMP region. + /// Substitute the given template arguments into a list of + /// expressions, expanding pack expansions if required. /// - /// \param S Statement associated with the current OpenMP region. - /// \param Clauses List of clauses for the current OpenMP region. + /// \param Exprs The list of expressions to substitute into. /// - /// \returns Statement for finished OpenMP region. - StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef Clauses); - StmtResult ActOnOpenMPExecutableDirective( - OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, - OpenMPDirectiveKind CancelRegion, ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, - OpenMPDirectiveKind PrevMappedDirective = llvm::omp::OMPD_unknown); - /// Called on well-formed '\#pragma omp parallel' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPParallelDirective(ArrayRef Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - using VarsWithInheritedDSAType = - llvm::SmallDenseMap; - /// Called on well-formed '\#pragma omp simd' after parsing - /// of the associated statement. - StmtResult - ActOnOpenMPSimdDirective(ArrayRef Clauses, Stmt *AStmt, - SourceLocation StartLoc, SourceLocation EndLoc, - VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '#pragma omp tile' after parsing of its clauses and - /// the associated statement. - StmtResult ActOnOpenMPTileDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '#pragma omp unroll' after parsing of its clauses - /// and the associated statement. - StmtResult ActOnOpenMPUnrollDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp for' after parsing - /// of the associated statement. - StmtResult - ActOnOpenMPForDirective(ArrayRef Clauses, Stmt *AStmt, - SourceLocation StartLoc, SourceLocation EndLoc, - VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp for simd' after parsing - /// of the associated statement. - StmtResult - ActOnOpenMPForSimdDirective(ArrayRef Clauses, Stmt *AStmt, - SourceLocation StartLoc, SourceLocation EndLoc, - VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp sections' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPSectionsDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp section' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp scope' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPScopeDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp single' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPSingleDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp master' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp critical' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, - ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp parallel for' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPParallelForDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp parallel for simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelForSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp parallel master' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp parallel masked' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp parallel sections' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp task' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPTaskDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp taskyield'. - StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp error'. - /// Error direcitive is allowed in both declared and excutable contexts. - /// Adding InExContext to identify which context is called from. - StmtResult ActOnOpenMPErrorDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc, - bool InExContext = true); - /// Called on well-formed '\#pragma omp barrier'. - StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp taskwait'. - StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp taskgroup'. - StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp flush'. - StmtResult ActOnOpenMPFlushDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp depobj'. - StmtResult ActOnOpenMPDepobjDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp scan'. - StmtResult ActOnOpenMPScanDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp ordered' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPOrderedDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp atomic' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPAtomicDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp target' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPTargetDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp target data' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPTargetDataDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp target enter data' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AStmt); - /// Called on well-formed '\#pragma omp target exit data' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AStmt); - /// Called on well-formed '\#pragma omp target parallel' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp target parallel for' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetParallelForDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPTeamsDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp teams loop' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPTeamsGenericLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams loop' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp parallel loop' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPParallelGenericLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target parallel loop' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPTargetParallelGenericLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp cancellation point'. - StmtResult - ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, - SourceLocation EndLoc, - OpenMPDirectiveKind CancelRegion); - /// Called on well-formed '\#pragma omp cancel'. - StmtResult ActOnOpenMPCancelDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc, - OpenMPDirectiveKind CancelRegion); - /// Called on well-formed '\#pragma omp taskloop' after parsing of the - /// associated statement. - StmtResult - ActOnOpenMPTaskLoopDirective(ArrayRef Clauses, Stmt *AStmt, - SourceLocation StartLoc, SourceLocation EndLoc, - VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp taskloop simd' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPTaskLoopSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp master taskloop' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPMasterTaskLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp master taskloop simd' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPMasterTaskLoopSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp parallel master taskloop' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelMasterTaskLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp parallel master taskloop simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp masked taskloop' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPMaskedTaskLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp masked taskloop simd' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp parallel masked taskloop' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp parallel masked taskloop simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp distribute' after parsing - /// of the associated statement. - StmtResult - ActOnOpenMPDistributeDirective(ArrayRef Clauses, Stmt *AStmt, - SourceLocation StartLoc, SourceLocation EndLoc, - VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target update'. - StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc, - Stmt *AStmt); - /// Called on well-formed '\#pragma omp distribute parallel for' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPDistributeParallelForDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp distribute parallel for simd' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPDistributeParallelForSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp distribute simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPDistributeSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target parallel for simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetParallelForSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target simd' after parsing of - /// the associated statement. - StmtResult - ActOnOpenMPTargetSimdDirective(ArrayRef Clauses, Stmt *AStmt, - SourceLocation StartLoc, SourceLocation EndLoc, - VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute' after parsing of - /// the associated statement. - StmtResult ActOnOpenMPTeamsDistributeDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute simd' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPTeamsDistributeSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute parallel for simd' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp teams distribute parallel for' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPTeamsDistributeParallelForDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef Clauses, - Stmt *AStmt, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp target teams distribute' after parsing - /// of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams distribute parallel for' - /// after parsing of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams distribute parallel for - /// simd' after parsing of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp target teams distribute simd' after - /// parsing of the associated statement. - StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - /// Called on well-formed '\#pragma omp interop'. - StmtResult ActOnOpenMPInteropDirective(ArrayRef Clauses, - SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp dispatch' after parsing of the - // /associated statement. - StmtResult ActOnOpenMPDispatchDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed '\#pragma omp masked' after parsing of the - // /associated statement. - StmtResult ActOnOpenMPMaskedDirective(ArrayRef Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc); + /// \param IsCall Whether this is some form of call, in which case + /// default arguments will be dropped. + /// + /// \param TemplateArgs The set of template arguments to substitute. + /// + /// \param Outputs Will receive all of the substituted arguments. + /// + /// \returns true if an error occurred, false otherwise. + bool SubstExprs(ArrayRef Exprs, bool IsCall, + const MultiLevelTemplateArgumentList &TemplateArgs, + SmallVectorImpl &Outputs); + + StmtResult SubstStmt(Stmt *S, + const MultiLevelTemplateArgumentList &TemplateArgs); + + ExprResult + SubstInitializer(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs, + bool CXXDirectInit); + + bool SubstBaseSpecifiers(CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs); + + bool InstantiateClass(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK, bool Complain = true); + + bool InstantiateEnum(SourceLocation PointOfInstantiation, + EnumDecl *Instantiation, EnumDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK); + + bool InstantiateInClassInitializer( + SourceLocation PointOfInstantiation, FieldDecl *Instantiation, + FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs); + + bool usesPartialOrExplicitSpecialization( + SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec); + + bool InstantiateClassTemplateSpecialization( + SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK, bool Complain = true); + + void + InstantiateClassMembers(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK); + + void InstantiateClassTemplateSpecializationMembers( + SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK); + + NestedNameSpecifierLoc SubstNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs); + + DeclarationNameInfo + SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, + const MultiLevelTemplateArgumentList &TemplateArgs); + TemplateName + SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, + SourceLocation Loc, + const MultiLevelTemplateArgumentList &TemplateArgs); + + bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EvaluateConstraint); + + /// Determine whether we are currently performing template instantiation. + bool inTemplateInstantiation() const { + return CodeSynthesisContexts.size() > NonInstantiationEntries; + } + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name C++ Template Declaration Instantiation + /// Implementations are in SemaTemplateInstantiateDecl.cpp + ///@{ + +public: + /// An entity for which implicit template instantiation is required. + /// + /// The source location associated with the declaration is the first place in + /// the source code where the declaration was "used". It is not necessarily + /// the point of instantiation (which will be either before or after the + /// namespace-scope declaration that triggered this implicit instantiation), + /// However, it is the location that diagnostics should generally refer to, + /// because users will need to know what code triggered the instantiation. + typedef std::pair PendingImplicitInstantiation; + + /// The queue of implicit template instantiations that are required + /// but have not yet been performed. + std::deque PendingInstantiations; + + /// Queue of implicit template instantiations that cannot be performed + /// eagerly. + SmallVector LateParsedInstantiations; + + SmallVector, 8> SavedVTableUses; + SmallVector, 8> + SavedPendingInstantiations; + + /// The queue of implicit template instantiations that are required + /// and must be performed within the current local scope. + /// + /// This queue is only used for member functions of local classes in + /// templates, which must be instantiated in the same scope as their + /// enclosing function, so that they can reference function-local + /// types, static variables, enumerators, etc. + std::deque PendingLocalImplicitInstantiations; + + class LocalEagerInstantiationScope { + public: + LocalEagerInstantiationScope(Sema &S) : S(S) { + SavedPendingLocalImplicitInstantiations.swap( + S.PendingLocalImplicitInstantiations); + } + + void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); } + + ~LocalEagerInstantiationScope() { + assert(S.PendingLocalImplicitInstantiations.empty() && + "there shouldn't be any pending local implicit instantiations"); + SavedPendingLocalImplicitInstantiations.swap( + S.PendingLocalImplicitInstantiations); + } + + private: + Sema &S; + std::deque + SavedPendingLocalImplicitInstantiations; + }; + + /// Records and restores the CurFPFeatures state on entry/exit of compound + /// statements. + class FPFeaturesStateRAII { + public: + FPFeaturesStateRAII(Sema &S); + ~FPFeaturesStateRAII(); + FPOptionsOverride getOverrides() { return OldOverrides; } + + private: + Sema &S; + FPOptions OldFPFeaturesState; + FPOptionsOverride OldOverrides; + LangOptions::FPEvalMethodKind OldEvalMethod; + SourceLocation OldFPPragmaLocation; + }; + + class GlobalEagerInstantiationScope { + public: + GlobalEagerInstantiationScope(Sema &S, bool Enabled) + : S(S), Enabled(Enabled) { + if (!Enabled) + return; + + S.SavedPendingInstantiations.emplace_back(); + S.SavedPendingInstantiations.back().swap(S.PendingInstantiations); + + S.SavedVTableUses.emplace_back(); + S.SavedVTableUses.back().swap(S.VTableUses); + } + + void perform() { + if (Enabled) { + S.DefineUsedVTables(); + S.PerformPendingInstantiations(); + } + } + + ~GlobalEagerInstantiationScope() { + if (!Enabled) + return; + + // Restore the set of pending vtables. + assert(S.VTableUses.empty() && + "VTableUses should be empty before it is discarded."); + S.VTableUses.swap(S.SavedVTableUses.back()); + S.SavedVTableUses.pop_back(); + + // Restore the set of pending implicit instantiations. + if (S.TUKind != TU_Prefix || !S.LangOpts.PCHInstantiateTemplates) { + assert(S.PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded."); + S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); + S.SavedPendingInstantiations.pop_back(); + } else { + // Template instantiations in the PCH may be delayed until the TU. + S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); + S.PendingInstantiations.insert( + S.PendingInstantiations.end(), + S.SavedPendingInstantiations.back().begin(), + S.SavedPendingInstantiations.back().end()); + S.SavedPendingInstantiations.pop_back(); + } + } + + private: + Sema &S; + bool Enabled; + }; + + ExplicitSpecifier instantiateExplicitSpecifier( + const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES); + + struct LateInstantiatedAttribute { + const Attr *TmplAttr; + LocalInstantiationScope *Scope; + Decl *NewDecl; + + LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S, + Decl *D) + : TmplAttr(A), Scope(S), NewDecl(D) {} + }; + typedef SmallVector LateInstantiatedAttrVec; + + void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, + const Decl *Pattern, Decl *Inst, + LateInstantiatedAttrVec *LateAttrs = nullptr, + LocalInstantiationScope *OuterMostScope = nullptr); + void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst); + + void + InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs, + const Decl *Pattern, Decl *Inst, + LateInstantiatedAttrVec *LateAttrs = nullptr, + LocalInstantiationScope *OuterMostScope = nullptr); + + void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor); + + bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, + ParmVarDecl *Param); + void InstantiateExceptionSpec(SourceLocation PointOfInstantiation, + FunctionDecl *Function); + FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, + const TemplateArgumentList *Args, + SourceLocation Loc); + void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, + FunctionDecl *Function, + bool Recursive = false, + bool DefinitionRequired = false, + bool AtEndOfTU = false); + VarTemplateSpecializationDecl *BuildVarTemplateInstantiation( + VarTemplateDecl *VarTemplate, VarDecl *FromVar, + const TemplateArgumentList *PartialSpecArgs, + const TemplateArgumentListInfo &TemplateArgsInfo, + SmallVectorImpl &Converted, + SourceLocation PointOfInstantiation, + LateInstantiatedAttrVec *LateAttrs = nullptr, + LocalInstantiationScope *StartingScope = nullptr); + VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, + const MultiLevelTemplateArgumentList &TemplateArgs); + void + BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar, + const MultiLevelTemplateArgumentList &TemplateArgs, + LateInstantiatedAttrVec *LateAttrs, + DeclContext *Owner, + LocalInstantiationScope *StartingScope, + bool InstantiatingVarTemplate = false, + VarTemplateSpecializationDecl *PrevVTSD = nullptr); + + void InstantiateVariableInitializer( + VarDecl *Var, VarDecl *OldVar, + const MultiLevelTemplateArgumentList &TemplateArgs); + void InstantiateVariableDefinition(SourceLocation PointOfInstantiation, + VarDecl *Var, bool Recursive = false, + bool DefinitionRequired = false, + bool AtEndOfTU = false); + + void InstantiateMemInitializers( + CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, + const MultiLevelTemplateArgumentList &TemplateArgs); + + NamedDecl * + FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool FindingInstantiatedContext = false); + DeclContext * + FindInstantiatedContext(SourceLocation Loc, DeclContext *DC, + const MultiLevelTemplateArgumentList &TemplateArgs); + + Decl *SubstDecl(Decl *D, DeclContext *Owner, + const MultiLevelTemplateArgumentList &TemplateArgs); + + /// Substitute the name and return type of a defaulted 'operator<=>' to form + /// an implicit 'operator=='. + FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD, + FunctionDecl *Spaceship); + + void PerformPendingInstantiations(bool LocalOnly = false); + + TemplateParameterList * + SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EvaluateConstraints = true); + + void PerformDependentDiagnostics( + const DeclContext *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs); + +private: + /// Introduce the instantiated local variables into the local + /// instantiation scope. + void addInstantiatedLocalVarsToScope(FunctionDecl *Function, + const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope); + /// Introduce the instantiated function parameters into the local + /// instantiation scope, and set the parameter names to those used + /// in the template. + bool addInstantiatedParametersToScope( + FunctionDecl *Function, const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope, + const MultiLevelTemplateArgumentList &TemplateArgs); + + int ParsingClassDepth = 0; + + class SavePendingParsedClassStateRAII { + public: + SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); } + + ~SavePendingParsedClassStateRAII() { + assert(S.DelayedOverridingExceptionSpecChecks.empty() && + "there shouldn't be any pending delayed exception spec checks"); + assert(S.DelayedEquivalentExceptionSpecChecks.empty() && + "there shouldn't be any pending delayed exception spec checks"); + swapSavedState(); + } + + private: + Sema &S; + decltype(DelayedOverridingExceptionSpecChecks) + SavedOverridingExceptionSpecChecks; + decltype(DelayedEquivalentExceptionSpecChecks) + SavedEquivalentExceptionSpecChecks; + + void swapSavedState() { + SavedOverridingExceptionSpecChecks.swap( + S.DelayedOverridingExceptionSpecChecks); + SavedEquivalentExceptionSpecChecks.swap( + S.DelayedEquivalentExceptionSpecChecks); + } + }; + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name C++ Variadic Templates + /// Implementations are in SemaTemplateVariadic.cpp + ///@{ + +public: + /// Determine whether an unexpanded parameter pack might be permitted in this + /// location. Useful for error recovery. + bool isUnexpandedParameterPackPermitted(); + + /// The context in which an unexpanded parameter pack is + /// being diagnosed. + /// + /// Note that the values of this enumeration line up with the first + /// argument to the \c err_unexpanded_parameter_pack diagnostic. + enum UnexpandedParameterPackContext { + /// An arbitrary expression. + UPPC_Expression = 0, + + /// The base type of a class type. + UPPC_BaseType, + + /// The type of an arbitrary declaration. + UPPC_DeclarationType, + + /// The type of a data member. + UPPC_DataMemberType, + + /// The size of a bit-field. + UPPC_BitFieldWidth, + + /// The expression in a static assertion. + UPPC_StaticAssertExpression, + + /// The fixed underlying type of an enumeration. + UPPC_FixedUnderlyingType, + + /// The enumerator value. + UPPC_EnumeratorValue, + + /// A using declaration. + UPPC_UsingDeclaration, + + /// A friend declaration. + UPPC_FriendDeclaration, + + /// A declaration qualifier. + UPPC_DeclarationQualifier, + + /// An initializer. + UPPC_Initializer, + + /// A default argument. + UPPC_DefaultArgument, + + /// The type of a non-type template parameter. + UPPC_NonTypeTemplateParameterType, + + /// The type of an exception. + UPPC_ExceptionType, + + /// Explicit specialization. + UPPC_ExplicitSpecialization, + + /// Partial specialization. + UPPC_PartialSpecialization, + + /// Microsoft __if_exists. + UPPC_IfExists, + + /// Microsoft __if_not_exists. + UPPC_IfNotExists, + + /// Lambda expression. + UPPC_Lambda, + + /// Block expression. + UPPC_Block, + + /// A type constraint. + UPPC_TypeConstraint, + + // A requirement in a requires-expression. + UPPC_Requirement, + + // A requires-clause. + UPPC_RequiresClause, + }; + + /// Diagnose unexpanded parameter packs. + /// + /// \param Loc The location at which we should emit the diagnostic. + /// + /// \param UPPC The context in which we are diagnosing unexpanded + /// parameter packs. + /// + /// \param Unexpanded the set of unexpanded parameter packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPacks( + SourceLocation Loc, UnexpandedParameterPackContext UPPC, + ArrayRef Unexpanded); + + /// If the given type contains an unexpanded parameter pack, + /// diagnose the error. + /// + /// \param Loc The source location where a diagnostc should be emitted. + /// + /// \param T The type that is being checked for unexpanded parameter + /// packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, + UnexpandedParameterPackContext UPPC); + + /// If the given expression contains an unexpanded parameter + /// pack, diagnose the error. + /// + /// \param E The expression that is being checked for unexpanded + /// parameter packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPack( + Expr *E, UnexpandedParameterPackContext UPPC = UPPC_Expression); + + /// If the given requirees-expression contains an unexpanded reference to one + /// of its own parameter packs, diagnose the error. + /// + /// \param RE The requiress-expression that is being checked for unexpanded + /// parameter packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE); + + /// If the given nested-name-specifier contains an unexpanded + /// parameter pack, diagnose the error. + /// + /// \param SS The nested-name-specifier that is being checked for + /// unexpanded parameter packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, + UnexpandedParameterPackContext UPPC); + + /// If the given name contains an unexpanded parameter pack, + /// diagnose the error. + /// + /// \param NameInfo The name (with source location information) that + /// is being checked for unexpanded parameter packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, + UnexpandedParameterPackContext UPPC); + + /// If the given template name contains an unexpanded parameter pack, + /// diagnose the error. + /// + /// \param Loc The location of the template name. + /// + /// \param Template The template name that is being checked for unexpanded + /// parameter packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, + TemplateName Template, + UnexpandedParameterPackContext UPPC); + + /// If the given template argument contains an unexpanded parameter + /// pack, diagnose the error. + /// + /// \param Arg The template argument that is being checked for unexpanded + /// parameter packs. + /// + /// \returns true if an error occurred, false otherwise. + bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, + UnexpandedParameterPackContext UPPC); + + /// Collect the set of unexpanded parameter packs within the given + /// template argument. + /// + /// \param Arg The template argument that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks( + TemplateArgument Arg, + SmallVectorImpl &Unexpanded); + + /// Collect the set of unexpanded parameter packs within the given + /// template argument. + /// + /// \param Arg The template argument that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks( + TemplateArgumentLoc Arg, + SmallVectorImpl &Unexpanded); + + /// Collect the set of unexpanded parameter packs within the given + /// type. + /// + /// \param T The type that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks( + QualType T, SmallVectorImpl &Unexpanded); + + /// Collect the set of unexpanded parameter packs within the given + /// type. + /// + /// \param TL The type that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks( + TypeLoc TL, SmallVectorImpl &Unexpanded); + + /// Collect the set of unexpanded parameter packs within the given + /// nested-name-specifier. + /// + /// \param NNS The nested-name-specifier that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks( + NestedNameSpecifierLoc NNS, + SmallVectorImpl &Unexpanded); + + /// Collect the set of unexpanded parameter packs within the given + /// name. + /// + /// \param NameInfo The name that will be traversed to find + /// unexpanded parameter packs. + void collectUnexpandedParameterPacks( + const DeclarationNameInfo &NameInfo, + SmallVectorImpl &Unexpanded); + + /// Invoked when parsing a template argument followed by an + /// ellipsis, which creates a pack expansion. + /// + /// \param Arg The template argument preceding the ellipsis, which + /// may already be invalid. + /// + /// \param EllipsisLoc The location of the ellipsis. + ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg, + SourceLocation EllipsisLoc); + + /// Invoked when parsing a type followed by an ellipsis, which + /// creates a pack expansion. + /// + /// \param Type The type preceding the ellipsis, which will become + /// the pattern of the pack expansion. + /// + /// \param EllipsisLoc The location of the ellipsis. + TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc); + + /// Construct a pack expansion type from the pattern of the pack + /// expansion. + TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern, + SourceLocation EllipsisLoc, + std::optional NumExpansions); + + /// Construct a pack expansion type from the pattern of the pack + /// expansion. + QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange, + SourceLocation EllipsisLoc, + std::optional NumExpansions); + + /// Invoked when parsing an expression followed by an ellipsis, which + /// creates a pack expansion. + /// + /// \param Pattern The expression preceding the ellipsis, which will become + /// the pattern of the pack expansion. + /// + /// \param EllipsisLoc The location of the ellipsis. + ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc); + + /// Invoked when parsing an expression followed by an ellipsis, which + /// creates a pack expansion. + /// + /// \param Pattern The expression preceding the ellipsis, which will become + /// the pattern of the pack expansion. + /// + /// \param EllipsisLoc The location of the ellipsis. + ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, + std::optional NumExpansions); + + /// Determine whether we could expand a pack expansion with the + /// given set of parameter packs into separate arguments by repeatedly + /// transforming the pattern. + /// + /// \param EllipsisLoc The location of the ellipsis that identifies the + /// pack expansion. + /// + /// \param PatternRange The source range that covers the entire pattern of + /// the pack expansion. + /// + /// \param Unexpanded The set of unexpanded parameter packs within the + /// pattern. + /// + /// \param ShouldExpand Will be set to \c true if the transformer should + /// expand the corresponding pack expansions into separate arguments. When + /// set, \c NumExpansions must also be set. + /// + /// \param RetainExpansion Whether the caller should add an unexpanded + /// pack expansion after all of the expanded arguments. This is used + /// when extending explicitly-specified template argument packs per + /// C++0x [temp.arg.explicit]p9. + /// + /// \param NumExpansions The number of separate arguments that will be in + /// the expanded form of the corresponding pack expansion. This is both an + /// input and an output parameter, which can be set by the caller if the + /// number of expansions is known a priori (e.g., due to a prior substitution) + /// and will be set by the callee when the number of expansions is known. + /// The callee must set this value when \c ShouldExpand is \c true; it may + /// set this value in other cases. + /// + /// \returns true if an error occurred (e.g., because the parameter packs + /// are to be instantiated with arguments of different lengths), false + /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions) + /// must be set. + bool CheckParameterPacksForExpansion( + SourceLocation EllipsisLoc, SourceRange PatternRange, + ArrayRef Unexpanded, + const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, + bool &RetainExpansion, std::optional &NumExpansions); + + /// Determine the number of arguments in the given pack expansion + /// type. + /// + /// This routine assumes that the number of arguments in the expansion is + /// consistent across all of the unexpanded parameter packs in its pattern. + /// + /// Returns an empty Optional if the type can't be expanded. + std::optional getNumArgumentsInExpansion( + QualType T, const MultiLevelTemplateArgumentList &TemplateArgs); + + /// Determine whether the given declarator contains any unexpanded + /// parameter packs. + /// + /// This routine is used by the parser to disambiguate function declarators + /// with an ellipsis prior to the ')', e.g., + /// + /// \code + /// void f(T...); + /// \endcode + /// + /// To determine whether we have an (unnamed) function parameter pack or + /// a variadic function. + /// + /// \returns true if the declarator contains any unexpanded parameter packs, + /// false otherwise. + bool containsUnexpandedParameterPacks(Declarator &D); + + /// Returns the pattern of the pack expansion for a template argument. + /// + /// \param OrigLoc The template argument to expand. + /// + /// \param Ellipsis Will be set to the location of the ellipsis. + /// + /// \param NumExpansions Will be set to the number of expansions that will + /// be generated from this pack expansion, if known a priori. + TemplateArgumentLoc getTemplateArgumentPackExpansionPattern( + TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis, + std::optional &NumExpansions) const; + + /// Given a template argument that contains an unexpanded parameter pack, but + /// which has already been substituted, attempt to determine the number of + /// elements that will be produced once this argument is fully-expanded. + /// + /// This is intended for use when transforming 'sizeof...(Arg)' in order to + /// avoid actually expanding the pack where possible. + std::optional getFullyPackExpandedSize(TemplateArgument Arg); + + ExprResult ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc, + IdentifierInfo &Name, + SourceLocation NameLoc, + SourceLocation RParenLoc); + + ExprResult ActOnPackIndexingExpr(Scope *S, Expr *PackExpression, + SourceLocation EllipsisLoc, + SourceLocation LSquareLoc, Expr *IndexExpr, + SourceLocation RSquareLoc); + + ExprResult BuildPackIndexingExpr(Expr *PackExpression, + SourceLocation EllipsisLoc, Expr *IndexExpr, + SourceLocation RSquareLoc, + ArrayRef ExpandedExprs = {}, + bool EmptyPack = false); + + /// Handle a C++1z fold-expression: ( expr op ... op expr ). + ExprResult ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS, + tok::TokenKind Operator, + SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc); + ExprResult BuildCXXFoldExpr(UnresolvedLookupExpr *Callee, + SourceLocation LParenLoc, Expr *LHS, + BinaryOperatorKind Operator, + SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc, + std::optional NumExpansions); + ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, + BinaryOperatorKind Operator); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name Constraints and Concepts + /// Implementations are in SemaConcept.cpp + ///@{ + +public: + void PushSatisfactionStackEntry(const NamedDecl *D, + const llvm::FoldingSetNodeID &ID) { + const NamedDecl *Can = cast(D->getCanonicalDecl()); + SatisfactionStack.emplace_back(Can, ID); + } + + void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); } + + bool SatisfactionStackContains(const NamedDecl *D, + const llvm::FoldingSetNodeID &ID) const { + const NamedDecl *Can = cast(D->getCanonicalDecl()); + return llvm::find(SatisfactionStack, SatisfactionStackEntryTy{Can, ID}) != + SatisfactionStack.end(); + } + + using SatisfactionStackEntryTy = + std::pair; + + // Resets the current SatisfactionStack for cases where we are instantiating + // constraints as a 'side effect' of normal instantiation in a way that is not + // indicative of recursive definition. + class SatisfactionStackResetRAII { + llvm::SmallVector BackupSatisfactionStack; + Sema &SemaRef; + + public: + SatisfactionStackResetRAII(Sema &S) : SemaRef(S) { + SemaRef.SwapSatisfactionStack(BackupSatisfactionStack); + } + + ~SatisfactionStackResetRAII() { + SemaRef.SwapSatisfactionStack(BackupSatisfactionStack); + } + }; + + void SwapSatisfactionStack( + llvm::SmallVectorImpl &NewSS) { + SatisfactionStack.swap(NewSS); + } + + /// Check whether the given expression is a valid constraint expression. + /// A diagnostic is emitted if it is not, false is returned, and + /// PossibleNonPrimary will be set to true if the failure might be due to a + /// non-primary expression being used as an atomic constraint. + bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(), + bool *PossibleNonPrimary = nullptr, + bool IsTrailingRequiresClause = false); + + /// \brief Check whether the given list of constraint expressions are + /// satisfied (as if in a 'conjunction') given template arguments. + /// \param Template the template-like entity that triggered the constraints + /// check (either a concept or a constrained entity). + /// \param ConstraintExprs a list of constraint expressions, treated as if + /// they were 'AND'ed together. + /// \param TemplateArgLists the list of template arguments to substitute into + /// the constraint expression. + /// \param TemplateIDRange The source range of the template id that + /// caused the constraints check. + /// \param Satisfaction if true is returned, will contain details of the + /// satisfaction, with enough information to diagnose an unsatisfied + /// expression. + /// \returns true if an error occurred and satisfaction could not be checked, + /// false otherwise. + bool CheckConstraintSatisfaction( + const NamedDecl *Template, ArrayRef ConstraintExprs, + const MultiLevelTemplateArgumentList &TemplateArgLists, + SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { + llvm::SmallVector Converted; + return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted, + TemplateArgLists, TemplateIDRange, + Satisfaction); + } + + /// \brief Check whether the given list of constraint expressions are + /// satisfied (as if in a 'conjunction') given template arguments. + /// Additionally, takes an empty list of Expressions which is populated with + /// the instantiated versions of the ConstraintExprs. + /// \param Template the template-like entity that triggered the constraints + /// check (either a concept or a constrained entity). + /// \param ConstraintExprs a list of constraint expressions, treated as if + /// they were 'AND'ed together. + /// \param ConvertedConstraints a out parameter that will get populated with + /// the instantiated version of the ConstraintExprs if we successfully checked + /// satisfaction. + /// \param TemplateArgList the multi-level list of template arguments to + /// substitute into the constraint expression. This should be relative to the + /// top-level (hence multi-level), since we need to instantiate fully at the + /// time of checking. + /// \param TemplateIDRange The source range of the template id that + /// caused the constraints check. + /// \param Satisfaction if true is returned, will contain details of the + /// satisfaction, with enough information to diagnose an unsatisfied + /// expression. + /// \returns true if an error occurred and satisfaction could not be checked, + /// false otherwise. + bool CheckConstraintSatisfaction( + const NamedDecl *Template, ArrayRef ConstraintExprs, + llvm::SmallVectorImpl &ConvertedConstraints, + const MultiLevelTemplateArgumentList &TemplateArgList, + SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction); + + /// \brief Check whether the given non-dependent constraint expression is + /// satisfied. Returns false and updates Satisfaction with the satisfaction + /// verdict if successful, emits a diagnostic and returns true if an error + /// occurred and satisfaction could not be determined. + /// + /// \returns true if an error occurred, false otherwise. + bool CheckConstraintSatisfaction(const Expr *ConstraintExpr, + ConstraintSatisfaction &Satisfaction); + + /// Check whether the given function decl's trailing requires clause is + /// satisfied, if any. Returns false and updates Satisfaction with the + /// satisfaction verdict if successful, emits a diagnostic and returns true if + /// an error occurred and satisfaction could not be determined. + /// + /// \returns true if an error occurred, false otherwise. + bool CheckFunctionConstraints(const FunctionDecl *FD, + ConstraintSatisfaction &Satisfaction, + SourceLocation UsageLoc = SourceLocation(), + bool ForOverloadResolution = false); + + // Calculates whether two constraint expressions are equal irrespective of a + // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and + // 'New', which are the "source" of the constraint, since this is necessary + // for figuring out the relative 'depth' of the constraint. The depth of the + // 'primary template' and the 'instantiated from' templates aren't necessarily + // the same, such as a case when one is a 'friend' defined in a class. + bool AreConstraintExpressionsEqual(const NamedDecl *Old, + const Expr *OldConstr, + const TemplateCompareNewDeclInfo &New, + const Expr *NewConstr); + + // Calculates whether the friend function depends on an enclosing template for + // the purposes of [temp.friend] p9. + bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD); + + /// \brief Ensure that the given template arguments satisfy the constraints + /// associated with the given template, emitting a diagnostic if they do not. + /// + /// \param Template The template to which the template arguments are being + /// provided. + /// + /// \param TemplateArgs The converted, canonicalized template arguments. + /// + /// \param TemplateIDRange The source range of the template id that + /// caused the constraints check. + /// + /// \returns true if the constrains are not satisfied or could not be checked + /// for satisfaction, false if the constraints are satisfied. + bool EnsureTemplateArgumentListConstraints( + TemplateDecl *Template, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceRange TemplateIDRange); + + bool CheckInstantiatedFunctionTemplateConstraints( + SourceLocation PointOfInstantiation, FunctionDecl *Decl, + ArrayRef TemplateArgs, + ConstraintSatisfaction &Satisfaction); + + /// \brief Emit diagnostics explaining why a constraint expression was deemed + /// unsatisfied. + /// \param First whether this is the first time an unsatisfied constraint is + /// diagnosed for this error. + void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, + bool First = true); + + /// \brief Emit diagnostics explaining why a constraint expression was deemed + /// unsatisfied. + void + DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction, + bool First = true); + + const NormalizedConstraint *getNormalizedAssociatedConstraints( + NamedDecl *ConstrainedDecl, ArrayRef AssociatedConstraints); + + /// \brief Check whether the given declaration's associated constraints are + /// at least as constrained than another declaration's according to the + /// partial ordering of constraints. + /// + /// \param Result If no error occurred, receives the result of true if D1 is + /// at least constrained than D2, and false otherwise. + /// + /// \returns true if an error occurred, false otherwise. + bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef AC1, + NamedDecl *D2, MutableArrayRef AC2, + bool &Result); + + /// If D1 was not at least as constrained as D2, but would've been if a pair + /// of atomic constraints involved had been declared in a concept and not + /// repeated in two separate places in code. + /// \returns true if such a diagnostic was emitted, false otherwise. + bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic( + NamedDecl *D1, ArrayRef AC1, NamedDecl *D2, + ArrayRef AC2); + +private: + /// Caches pairs of template-like decls whose associated constraints were + /// checked for subsumption and whether or not the first's constraints did in + /// fact subsume the second's. + llvm::DenseMap, bool> SubsumptionCache; + /// Caches the normalized associated constraints of declarations (concepts or + /// constrained declarations). If an error occurred while normalizing the + /// associated constraints of the template or concept, nullptr will be cached + /// here. + llvm::DenseMap NormalizationCache; + + llvm::ContextualFoldingSet + SatisfactionCache; + + // The current stack of constraint satisfactions, so we can exit-early. + llvm::SmallVector SatisfactionStack; + + /// Introduce the instantiated captures of the lambda into the local + /// instantiation scope. + bool addInstantiatedCapturesToScope( + FunctionDecl *Function, const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope, + const MultiLevelTemplateArgumentList &TemplateArgs); + + /// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in + /// the case of lambdas) set up the LocalInstantiationScope of the current + /// function. + bool SetupConstraintScope( + FunctionDecl *FD, std::optional> TemplateArgs, + MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope); + + /// Used during constraint checking, sets up the constraint template argument + /// lists, and calls SetupConstraintScope to set up the + /// LocalInstantiationScope to have the proper set of ParVarDecls configured. + std::optional + SetupConstraintCheckingTemplateArgumentsAndScope( + FunctionDecl *FD, std::optional> TemplateArgs, + LocalInstantiationScope &Scope); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name Types + /// Implementations are in SemaType.cpp + ///@{ + +public: + /// A mapping that describes the nullability we've seen in each header file. + FileNullabilityMap NullabilityMap; + + static int getPrintable(int I) { return I; } + static unsigned getPrintable(unsigned I) { return I; } + static bool getPrintable(bool B) { return B; } + static const char *getPrintable(const char *S) { return S; } + static StringRef getPrintable(StringRef S) { return S; } + static const std::string &getPrintable(const std::string &S) { return S; } + static const IdentifierInfo *getPrintable(const IdentifierInfo *II) { + return II; + } + static DeclarationName getPrintable(DeclarationName N) { return N; } + static QualType getPrintable(QualType T) { return T; } + static SourceRange getPrintable(SourceRange R) { return R; } + static SourceRange getPrintable(SourceLocation L) { return L; } + static SourceRange getPrintable(const Expr *E) { return E->getSourceRange(); } + static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange(); } + + enum class CompleteTypeKind { + /// Apply the normal rules for complete types. In particular, + /// treat all sizeless types as incomplete. + Normal, + + /// Relax the normal rules for complete types so that they include + /// sizeless built-in types. + AcceptSizeless, + + // FIXME: Eventually we should flip the default to Normal and opt in + // to AcceptSizeless rather than opt out of it. + Default = AcceptSizeless + }; + + /// Build a an Objective-C protocol-qualified 'id' type where no + /// base type was specified. + TypeResult actOnObjCProtocolQualifierType( + SourceLocation lAngleLoc, ArrayRef protocols, + ArrayRef protocolLocs, SourceLocation rAngleLoc); + + /// Build a specialized and/or protocol-qualified Objective-C type. + TypeResult actOnObjCTypeArgsAndProtocolQualifiers( + Scope *S, SourceLocation Loc, ParsedType BaseType, + SourceLocation TypeArgsLAngleLoc, ArrayRef TypeArgs, + SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc); - /// Called on well-formed '\#pragma omp loop' after parsing of the - /// associated statement. - StmtResult ActOnOpenMPGenericLoopDirective( - ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Build an Objective-C type parameter type. + QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl, + SourceLocation ProtocolLAngleLoc, + ArrayRef Protocols, + ArrayRef ProtocolLocs, + SourceLocation ProtocolRAngleLoc, + bool FailOnError = false); - /// Checks correctness of linear modifiers. - bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, - SourceLocation LinLoc); - /// Checks that the specified declaration matches requirements for the linear - /// decls. - bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, - OpenMPLinearClauseKind LinKind, QualType Type, - bool IsDeclareSimd = false); + /// Build an Objective-C object pointer type. + QualType BuildObjCObjectType( + QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc, + ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc, + SourceLocation ProtocolLAngleLoc, ArrayRef Protocols, + ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc, + bool FailOnError, bool Rebuilding); - /// Called on well-formed '\#pragma omp declare simd' after parsing of - /// the associated method/function. - DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective( - DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, - Expr *Simdlen, ArrayRef Uniforms, ArrayRef Aligneds, - ArrayRef Alignments, ArrayRef Linears, - ArrayRef LinModifiers, ArrayRef Steps, SourceRange SR); + QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs, + const DeclSpec *DS = nullptr); + QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, + const DeclSpec *DS = nullptr); + QualType BuildPointerType(QualType T, SourceLocation Loc, + DeclarationName Entity); + QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, + DeclarationName Entity); + QualType BuildArrayType(QualType T, ArraySizeModifier ASM, Expr *ArraySize, + unsigned Quals, SourceRange Brackets, + DeclarationName Entity); + QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc); + QualType BuildExtVectorType(QualType T, Expr *ArraySize, + SourceLocation AttrLoc); + QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns, + SourceLocation AttrLoc); - /// Checks '\#pragma omp declare variant' variant function and original - /// functions after parsing of the associated method/function. - /// \param DG Function declaration to which declare variant directive is - /// applied to. - /// \param VariantRef Expression that references the variant function, which - /// must be used instead of the original one, specified in \p DG. - /// \param TI The trait info object representing the match clause. - /// \param NumAppendArgs The number of omp_interop_t arguments to account for - /// in checking. - /// \returns std::nullopt, if the function/variant function are not compatible - /// with the pragma, pair of original function/variant ref expression - /// otherwise. - std::optional> - checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, - OMPTraitInfo &TI, unsigned NumAppendArgs, - SourceRange SR); + QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, + SourceLocation AttrLoc); - /// Called on well-formed '\#pragma omp declare variant' after parsing of - /// the associated method/function. - /// \param FD Function declaration to which declare variant directive is - /// applied to. - /// \param VariantRef Expression that references the variant function, which - /// must be used instead of the original one, specified in \p DG. - /// \param TI The context traits associated with the function variant. - /// \param AdjustArgsNothing The list of 'nothing' arguments. - /// \param AdjustArgsNeedDevicePtr The list of 'need_device_ptr' arguments. - /// \param AppendArgs The list of 'append_args' arguments. - /// \param AdjustArgsLoc The Location of an 'adjust_args' clause. - /// \param AppendArgsLoc The Location of an 'append_args' clause. - /// \param SR The SourceRange of the 'declare variant' directive. - void ActOnOpenMPDeclareVariantDirective( - FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, - ArrayRef AdjustArgsNothing, - ArrayRef AdjustArgsNeedDevicePtr, - ArrayRef AppendArgs, SourceLocation AdjustArgsLoc, - SourceLocation AppendArgsLoc, SourceRange SR); + /// Same as above, but constructs the AddressSpace index if not provided. + QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, + SourceLocation AttrLoc); - OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, - Expr *Expr, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'allocator' clause. - OMPClause *ActOnOpenMPAllocatorClause(Expr *Allocator, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'if' clause. - OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, - Expr *Condition, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation NameModifierLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc); - /// Called on well-formed 'final' clause. - OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'num_threads' clause. - OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'align' clause. - OMPClause *ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'safelen' clause. - OMPClause *ActOnOpenMPSafelenClause(Expr *Length, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'simdlen' clause. - OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-form 'sizes' clause. - OMPClause *ActOnOpenMPSizesClause(ArrayRef SizeExprs, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-form 'full' clauses. - OMPClause *ActOnOpenMPFullClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-form 'partial' clauses. - OMPClause *ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'collapse' clause. - OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'ordered' clause. - OMPClause * - ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, - SourceLocation LParenLoc = SourceLocation(), - Expr *NumForLoops = nullptr); - /// Called on well-formed 'grainsize' clause. - OMPClause *ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, - Expr *Size, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ModifierLoc, - SourceLocation EndLoc); - /// Called on well-formed 'num_tasks' clause. - OMPClause *ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, - Expr *NumTasks, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ModifierLoc, - SourceLocation EndLoc); - /// Called on well-formed 'hint' clause. - OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'detach' clause. - OMPClause *ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc); + + bool CheckFunctionReturnType(QualType T, SourceLocation Loc); + + /// Build a function type. + /// + /// This routine checks the function type according to C++ rules and + /// under the assumption that the result type and parameter types have + /// just been instantiated from a template. It therefore duplicates + /// some of the behavior of GetTypeForDeclarator, but in a much + /// simpler form that is only suitable for this narrow use case. + /// + /// \param T The return type of the function. + /// + /// \param ParamTypes The parameter types of the function. This array + /// will be modified to account for adjustments to the types of the + /// function parameters. + /// + /// \param Loc The location of the entity whose type involves this + /// function type or, if there is no such entity, the location of the + /// type that will have function type. + /// + /// \param Entity The name of the entity that involves the function + /// type, if known. + /// + /// \param EPI Extra information about the function type. Usually this will + /// be taken from an existing function with the same prototype. + /// + /// \returns A suitable function type, if there are no errors. The + /// unqualified type will always be a FunctionProtoType. + /// Otherwise, returns a NULL type. + QualType BuildFunctionType(QualType T, MutableArrayRef ParamTypes, + SourceLocation Loc, DeclarationName Entity, + const FunctionProtoType::ExtProtoInfo &EPI); + + QualType BuildMemberPointerType(QualType T, QualType Class, + SourceLocation Loc, DeclarationName Entity); + QualType BuildBlockPointerType(QualType T, SourceLocation Loc, + DeclarationName Entity); + QualType BuildParenType(QualType T); + QualType BuildAtomicType(QualType T, SourceLocation Loc); + QualType BuildReadPipeType(QualType T, SourceLocation Loc); + QualType BuildWritePipeType(QualType T, SourceLocation Loc); + QualType BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc); + + TypeSourceInfo *GetTypeForDeclarator(Declarator &D); + TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); + + /// Package the given type and TSI into a ParsedType. + ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); + static QualType GetTypeFromParser(ParsedType Ty, + TypeSourceInfo **TInfo = nullptr); + + TypeResult ActOnTypeName(Declarator &D); + + /// The parser has parsed the context-sensitive type 'instancetype' + /// in an Objective-C message declaration. Return the appropriate type. + ParsedType ActOnObjCInstanceType(SourceLocation Loc); + + // Check whether the size of array element of type \p EltTy is a multiple of + // its alignment and return false if it isn't. + bool checkArrayElementAlignment(QualType EltTy, SourceLocation Loc); + + void + diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, + SourceLocation FallbackLoc, + SourceLocation ConstQualLoc = SourceLocation(), + SourceLocation VolatileQualLoc = SourceLocation(), + SourceLocation RestrictQualLoc = SourceLocation(), + SourceLocation AtomicQualLoc = SourceLocation(), + SourceLocation UnalignedQualLoc = SourceLocation()); + + /// Retrieve the keyword associated + IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability); + + /// The struct behind the CFErrorRef pointer. + RecordDecl *CFError = nullptr; + bool isCFError(RecordDecl *D); + + /// Retrieve the identifier "NSError". + IdentifierInfo *getNSErrorIdent(); + + /// Adjust the calling convention of a method to be the ABI default if it + /// wasn't specified explicitly. This handles method types formed from + /// function type typedefs and typename template arguments. + void adjustMemberFunctionCC(QualType &T, bool HasThisPointer, + bool IsCtorOrDtor, SourceLocation Loc); + + // Check if there is an explicit attribute, but only look through parens. + // The intent is to look for an attribute on the current declarator, but not + // one that came from a typedef. + bool hasExplicitCallingConv(QualType T); + + /// Check whether a nullability type specifier can be added to the given + /// type through some means not written in source (e.g. API notes). + /// + /// \param Type The type to which the nullability specifier will be + /// added. On success, this type will be updated appropriately. + /// + /// \param Nullability The nullability specifier to add. + /// + /// \param DiagLoc The location to use for diagnostics. + /// + /// \param AllowArrayTypes Whether to accept nullability specifiers on an + /// array type (e.g., because it will decay to a pointer). + /// + /// \param OverrideExisting Whether to override an existing, locally-specified + /// nullability specifier rather than complaining about the conflict. + /// + /// \returns true if nullability cannot be applied, false otherwise. + bool CheckImplicitNullabilityTypeSpecifier(QualType &Type, + NullabilityKind Nullability, + SourceLocation DiagLoc, + bool AllowArrayTypes, + bool OverrideExisting); - OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, - unsigned Argument, - SourceLocation ArgumentLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'when' clause. - OMPClause *ActOnOpenMPWhenClause(OMPTraitInfo &TI, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'default' clause. - OMPClause *ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, - SourceLocation KindLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'proc_bind' clause. - OMPClause *ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, - SourceLocation KindLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'order' clause. - OMPClause *ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, - OpenMPOrderClauseKind Kind, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation MLoc, SourceLocation KindLoc, - SourceLocation EndLoc); - /// Called on well-formed 'update' clause. - OMPClause *ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, - SourceLocation KindLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + /// Get the type of expression E, triggering instantiation to complete the + /// type if necessary -- that is, if the expression refers to a templated + /// static data member of incomplete array type. + /// + /// May still return an incomplete type if instantiation was not possible or + /// if the type is incomplete for a different reason. Use + /// RequireCompleteExprType instead if a diagnostic is expected for an + /// incomplete expression type. + QualType getCompletedType(Expr *E); - OMPClause *ActOnOpenMPSingleExprWithArgClause( - OpenMPClauseKind Kind, ArrayRef Arguments, Expr *Expr, - SourceLocation StartLoc, SourceLocation LParenLoc, - ArrayRef ArgumentsLoc, SourceLocation DelimLoc, - SourceLocation EndLoc); - /// Called on well-formed 'schedule' clause. - OMPClause *ActOnOpenMPScheduleClause( - OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, - OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, - SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc); + void completeExprArrayBound(Expr *E); + bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind, + TypeDiagnoser &Diagnoser); + bool RequireCompleteExprType(Expr *E, unsigned DiagID); - OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'nowait' clause. - OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'untied' clause. - OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'mergeable' clause. - OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'read' clause. - OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'write' clause. - OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'update' clause. - OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'capture' clause. - OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'compare' clause. - OMPClause *ActOnOpenMPCompareClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'fail' clause. - OMPClause *ActOnOpenMPFailClause(SourceLocation StartLoc, - SourceLocation EndLoc); - OMPClause *ActOnOpenMPFailClause( - OpenMPClauseKind Kind, SourceLocation KindLoc, - SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + template + bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) { + BoundTypeDiagnoser Diagnoser(DiagID, Args...); + return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser); + } - /// Called on well-formed 'seq_cst' clause. - OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'acq_rel' clause. - OMPClause *ActOnOpenMPAcqRelClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'acquire' clause. - OMPClause *ActOnOpenMPAcquireClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'release' clause. - OMPClause *ActOnOpenMPReleaseClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'relaxed' clause. - OMPClause *ActOnOpenMPRelaxedClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'weak' clause. - OMPClause *ActOnOpenMPWeakClause(SourceLocation StartLoc, - SourceLocation EndLoc); + QualType getElaboratedType(ElaboratedTypeKeyword Keyword, + const CXXScopeSpec &SS, QualType T, + TagDecl *OwnedTagDecl = nullptr); - /// Called on well-formed 'init' clause. - OMPClause * - ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation VarLoc, SourceLocation EndLoc); + // Returns the underlying type of a decltype with the given expression. + QualType getDecltypeForExpr(Expr *E); - /// Called on well-formed 'use' clause. - OMPClause *ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation VarLoc, SourceLocation EndLoc); + QualType BuildTypeofExprType(Expr *E, TypeOfKind Kind); + /// If AsUnevaluated is false, E is treated as though it were an evaluated + /// context, such as when building a type for decltype(auto). + QualType BuildDecltypeType(Expr *E, bool AsUnevaluated = true); - /// Called on well-formed 'destroy' clause. - OMPClause *ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation VarLoc, - SourceLocation EndLoc); - /// Called on well-formed 'novariants' clause. - OMPClause *ActOnOpenMPNovariantsClause(Expr *Condition, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'nocontext' clause. - OMPClause *ActOnOpenMPNocontextClause(Expr *Condition, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'filter' clause. - OMPClause *ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'threads' clause. - OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'simd' clause. - OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'nogroup' clause. - OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc, - SourceLocation EndLoc); - /// Called on well-formed 'unified_address' clause. - OMPClause *ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, - SourceLocation EndLoc); + QualType ActOnPackIndexingType(QualType Pattern, Expr *IndexExpr, + SourceLocation Loc, + SourceLocation EllipsisLoc); + QualType BuildPackIndexingType(QualType Pattern, Expr *IndexExpr, + SourceLocation Loc, SourceLocation EllipsisLoc, + bool FullySubstituted = false, + ArrayRef Expansions = {}); - /// Called on well-formed 'unified_address' clause. - OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, - SourceLocation EndLoc); + using UTTKind = UnaryTransformType::UTTKind; + QualType BuildUnaryTransformType(QualType BaseType, UTTKind UKind, + SourceLocation Loc); + QualType BuiltinEnumUnderlyingType(QualType BaseType, SourceLocation Loc); + QualType BuiltinAddPointer(QualType BaseType, SourceLocation Loc); + QualType BuiltinRemovePointer(QualType BaseType, SourceLocation Loc); + QualType BuiltinDecay(QualType BaseType, SourceLocation Loc); + QualType BuiltinAddReference(QualType BaseType, UTTKind UKind, + SourceLocation Loc); + QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind, + SourceLocation Loc); + QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind, + SourceLocation Loc); + QualType BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind, + SourceLocation Loc); + QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind, + SourceLocation Loc); + + bool RequireLiteralType(SourceLocation Loc, QualType T, + TypeDiagnoser &Diagnoser); + bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID); + + template + bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID, + const Ts &...Args) { + BoundTypeDiagnoser Diagnoser(DiagID, Args...); + return RequireLiteralType(Loc, T, Diagnoser); + } + + bool isCompleteType(SourceLocation Loc, QualType T, + CompleteTypeKind Kind = CompleteTypeKind::Default) { + return !RequireCompleteTypeImpl(Loc, T, Kind, nullptr); + } + bool RequireCompleteType(SourceLocation Loc, QualType T, + CompleteTypeKind Kind, TypeDiagnoser &Diagnoser); + bool RequireCompleteType(SourceLocation Loc, QualType T, + CompleteTypeKind Kind, unsigned DiagID); + + bool RequireCompleteType(SourceLocation Loc, QualType T, + TypeDiagnoser &Diagnoser) { + return RequireCompleteType(Loc, T, CompleteTypeKind::Default, Diagnoser); + } + bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID) { + return RequireCompleteType(Loc, T, CompleteTypeKind::Default, DiagID); + } + + template + bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID, + const Ts &...Args) { + BoundTypeDiagnoser Diagnoser(DiagID, Args...); + return RequireCompleteType(Loc, T, Diagnoser); + } + + /// Determine whether a declaration is visible to name lookup. + bool isVisible(const NamedDecl *D) { + return D->isUnconditionallyVisible() || + isAcceptableSlow(D, AcceptableKind::Visible); + } + + /// Determine whether a declaration is reachable. + bool isReachable(const NamedDecl *D) { + // All visible declarations are reachable. + return D->isUnconditionallyVisible() || + isAcceptableSlow(D, AcceptableKind::Reachable); + } + + /// Determine whether a declaration is acceptable (visible/reachable). + bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) { + return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D); + } - /// Called on well-formed 'reverse_offload' clause. - OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, - SourceLocation EndLoc); + /// Determine if \p D and \p Suggested have a structurally compatible + /// layout as described in C11 6.2.7/1. + bool hasStructuralCompatLayout(Decl *D, Decl *Suggested); - /// Called on well-formed 'dynamic_allocators' clause. - OMPClause *ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, - SourceLocation EndLoc); + /// Determine if \p D has a visible definition. If not, suggest a declaration + /// that should be made visible to expose the definition. + bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, + bool OnlyNeedComplete = false); + bool hasVisibleDefinition(const NamedDecl *D) { + NamedDecl *Hidden; + return hasVisibleDefinition(const_cast(D), &Hidden); + } - /// Called on well-formed 'atomic_default_mem_order' clause. - OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause( - OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, - SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Determine if \p D has a reachable definition. If not, suggest a + /// declaration that should be made reachable to expose the definition. + bool hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested, + bool OnlyNeedComplete = false); + bool hasReachableDefinition(NamedDecl *D) { + NamedDecl *Hidden; + return hasReachableDefinition(D, &Hidden); + } - /// Called on well-formed 'at' clause. - OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, - SourceLocation KindLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested, + AcceptableKind Kind, + bool OnlyNeedComplete = false); + bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) { + NamedDecl *Hidden; + return hasAcceptableDefinition(D, &Hidden, Kind); + } - /// Called on well-formed 'severity' clause. - OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, - SourceLocation KindLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); +private: + bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, + CompleteTypeKind Kind, TypeDiagnoser *Diagnoser); - /// Called on well-formed 'message' clause. - /// passing string for message. - OMPClause *ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + /// Nullability type specifiers. + IdentifierInfo *Ident__Nonnull = nullptr; + IdentifierInfo *Ident__Nullable = nullptr; + IdentifierInfo *Ident__Nullable_result = nullptr; + IdentifierInfo *Ident__Null_unspecified = nullptr; - /// Data used for processing a list of variables in OpenMP clauses. - struct OpenMPVarListDataTy final { - Expr *DepModOrTailExpr = nullptr; - Expr *IteratorExpr = nullptr; - SourceLocation ColonLoc; - SourceLocation RLoc; - CXXScopeSpec ReductionOrMapperIdScopeSpec; - DeclarationNameInfo ReductionOrMapperId; - int ExtraModifier = -1; ///< Additional modifier for linear, map, depend or - ///< lastprivate clause. - SmallVector - MapTypeModifiers; - SmallVector - MapTypeModifiersLoc; - SmallVector - MotionModifiers; - SmallVector MotionModifiersLoc; - bool IsMapTypeImplicit = false; - SourceLocation ExtraModifierLoc; - SourceLocation OmpAllMemoryLoc; - SourceLocation - StepModifierLoc; /// 'step' modifier location for linear clause - }; + IdentifierInfo *Ident_NSError = nullptr; - OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind, - ArrayRef Vars, - const OMPVarListLocTy &Locs, - OpenMPVarListDataTy &Data); - /// Called on well-formed 'inclusive' clause. - OMPClause *ActOnOpenMPInclusiveClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'exclusive' clause. - OMPClause *ActOnOpenMPExclusiveClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'allocate' clause. - OMPClause * - ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef VarList, - SourceLocation StartLoc, SourceLocation ColonLoc, - SourceLocation LParenLoc, SourceLocation EndLoc); - /// Called on well-formed 'private' clause. - OMPClause *ActOnOpenMPPrivateClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'firstprivate' clause. - OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'lastprivate' clause. - OMPClause *ActOnOpenMPLastprivateClause( - ArrayRef VarList, OpenMPLastprivateModifier LPKind, - SourceLocation LPKindLoc, SourceLocation ColonLoc, - SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// Called on well-formed 'shared' clause. - OMPClause *ActOnOpenMPSharedClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'reduction' clause. - OMPClause *ActOnOpenMPReductionClause( - ArrayRef VarList, OpenMPReductionClauseModifier Modifier, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation ModifierLoc, SourceLocation ColonLoc, - SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, - const DeclarationNameInfo &ReductionId, - ArrayRef UnresolvedReductions = std::nullopt); - /// Called on well-formed 'task_reduction' clause. - OMPClause *ActOnOpenMPTaskReductionClause( - ArrayRef VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, - CXXScopeSpec &ReductionIdScopeSpec, - const DeclarationNameInfo &ReductionId, - ArrayRef UnresolvedReductions = std::nullopt); - /// Called on well-formed 'in_reduction' clause. - OMPClause *ActOnOpenMPInReductionClause( - ArrayRef VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, - CXXScopeSpec &ReductionIdScopeSpec, - const DeclarationNameInfo &ReductionId, - ArrayRef UnresolvedReductions = std::nullopt); - /// Called on well-formed 'linear' clause. - OMPClause *ActOnOpenMPLinearClause( - ArrayRef VarList, Expr *Step, SourceLocation StartLoc, - SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, - SourceLocation LinLoc, SourceLocation ColonLoc, - SourceLocation StepModifierLoc, SourceLocation EndLoc); - /// Called on well-formed 'aligned' clause. - OMPClause *ActOnOpenMPAlignedClause(ArrayRef VarList, - Expr *Alignment, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc); - /// Called on well-formed 'copyin' clause. - OMPClause *ActOnOpenMPCopyinClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'copyprivate' clause. - OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'flush' pseudo clause. - OMPClause *ActOnOpenMPFlushClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'depobj' pseudo clause. - OMPClause *ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'depend' clause. - OMPClause *ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, - Expr *DepModifier, - ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'device' clause. - OMPClause *ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, - Expr *Device, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ModifierLoc, - SourceLocation EndLoc); - /// Called on well-formed 'map' clause. - OMPClause *ActOnOpenMPMapClause( - Expr *IteratorModifier, ArrayRef MapTypeModifiers, - ArrayRef MapTypeModifiersLoc, - CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, - OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, - SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef VarList, - const OMPVarListLocTy &Locs, bool NoDiagnose = false, - ArrayRef UnresolvedMappers = std::nullopt); - /// Called on well-formed 'num_teams' clause. - OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'thread_limit' clause. - OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'priority' clause. - OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on well-formed 'dist_schedule' clause. - OMPClause *ActOnOpenMPDistScheduleClause( - OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, - SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, - SourceLocation CommaLoc, SourceLocation EndLoc); - /// Called on well-formed 'defaultmap' clause. - OMPClause *ActOnOpenMPDefaultmapClause( - OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, - SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, - SourceLocation KindLoc, SourceLocation EndLoc); - /// Called on well-formed 'to' clause. - OMPClause * - ActOnOpenMPToClause(ArrayRef MotionModifiers, - ArrayRef MotionModifiersLoc, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, SourceLocation ColonLoc, - ArrayRef VarList, const OMPVarListLocTy &Locs, - ArrayRef UnresolvedMappers = std::nullopt); - /// Called on well-formed 'from' clause. - OMPClause * - ActOnOpenMPFromClause(ArrayRef MotionModifiers, - ArrayRef MotionModifiersLoc, - CXXScopeSpec &MapperIdScopeSpec, - DeclarationNameInfo &MapperId, SourceLocation ColonLoc, - ArrayRef VarList, const OMPVarListLocTy &Locs, - ArrayRef UnresolvedMappers = std::nullopt); - /// Called on well-formed 'use_device_ptr' clause. - OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef VarList, - const OMPVarListLocTy &Locs); - /// Called on well-formed 'use_device_addr' clause. - OMPClause *ActOnOpenMPUseDeviceAddrClause(ArrayRef VarList, - const OMPVarListLocTy &Locs); - /// Called on well-formed 'is_device_ptr' clause. - OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef VarList, - const OMPVarListLocTy &Locs); - /// Called on well-formed 'has_device_addr' clause. - OMPClause *ActOnOpenMPHasDeviceAddrClause(ArrayRef VarList, - const OMPVarListLocTy &Locs); - /// Called on well-formed 'nontemporal' clause. - OMPClause *ActOnOpenMPNontemporalClause(ArrayRef VarList, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // - /// Data for list of allocators. - struct UsesAllocatorsData { - /// Allocator. - Expr *Allocator = nullptr; - /// Allocator traits. - Expr *AllocatorTraits = nullptr; - /// Locations of '(' and ')' symbols. - SourceLocation LParenLoc, RParenLoc; + /// \name ObjC Declarations + /// Implementations are in SemaDeclObjC.cpp + ///@{ + +public: + enum ObjCSpecialMethodKind { + OSMK_None, + OSMK_Alloc, + OSMK_New, + OSMK_Copy, + OSMK_RetainingInit, + OSMK_NonRetainingInit }; - /// Called on well-formed 'uses_allocators' clause. - OMPClause *ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, - ArrayRef Data); - /// Called on well-formed 'affinity' clause. - OMPClause *ActOnOpenMPAffinityClause(SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation ColonLoc, - SourceLocation EndLoc, Expr *Modifier, - ArrayRef Locators); - /// Called on a well-formed 'bind' clause. - OMPClause *ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, - SourceLocation KindLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); - /// Called on a well-formed 'ompx_dyn_cgroup_mem' clause. - OMPClause *ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + /// Method selectors used in a \@selector expression. Used for implementation + /// of -Wselector. + llvm::MapVector ReferencedSelectors; - /// Called on well-formed 'doacross' clause. - OMPClause * - ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, - SourceLocation DepLoc, SourceLocation ColonLoc, - ArrayRef VarList, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc); + class GlobalMethodPool { + public: + using Lists = std::pair; + using iterator = llvm::DenseMap::iterator; + iterator begin() { return Methods.begin(); } + iterator end() { return Methods.end(); } + iterator find(Selector Sel) { return Methods.find(Sel); } + std::pair insert(std::pair &&Val) { + return Methods.insert(Val); + } + int count(Selector Sel) const { return Methods.count(Sel); } + bool empty() const { return Methods.empty(); } - /// Called on a well-formed 'ompx_attribute' clause. - OMPClause *ActOnOpenMPXAttributeClause(ArrayRef Attrs, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + private: + llvm::DenseMap Methods; + }; - /// Called on a well-formed 'ompx_bare' clause. - OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc, - SourceLocation EndLoc); + /// Method Pool - allows efficient lookup when typechecking messages to "id". + /// We need to maintain a list, since selectors can have differing signatures + /// across classes. In Cocoa, this happens to be extremely uncommon (only 1% + /// of selectors are "overloaded"). + /// At the head of the list it is recorded whether there were 0, 1, or >= 2 + /// methods inside categories with a particular selector. + GlobalMethodPool MethodPool; - //===--------------------------------------------------------------------===// - // OpenACC directives and clauses. + /// Check ODR hashes for C/ObjC when merging types from modules. + /// Differently from C++, actually parse the body and reject in case + /// of a mismatch. + template ::value>> + bool ActOnDuplicateODRHashDefinition(T *Duplicate, T *Previous) { + if (Duplicate->getODRHash() != Previous->getODRHash()) + return false; - /// Called after parsing an OpenACC Clause so that it can be checked. - bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind, - SourceLocation StartLoc); + // Make the previous decl visible. + makeMergedDefinitionVisible(Previous); + return true; + } - /// Called after the construct has been parsed, but clauses haven't been - /// parsed. This allows us to diagnose not-implemented, as well as set up any - /// state required for parsing the clauses. - void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); + typedef llvm::SmallPtrSet SelectorSet; - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'statement' context. - bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); + enum MethodMatchStrategy { MMS_loose, MMS_strict }; - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'Decl' context. - bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); - /// Called when we encounter an associated statement for our construct, this - /// should check legality of the statement as it appertains to this Construct. - StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, - StmtResult AssocStmt); + enum ObjCContainerKind { + OCK_None = -1, + OCK_Interface = 0, + OCK_Protocol, + OCK_Category, + OCK_ClassExtension, + OCK_Implementation, + OCK_CategoryImplementation + }; + ObjCContainerKind getObjCContainerKind() const; - /// Called after the directive has been completely parsed, including the - /// declaration group or associated statement. - StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc, - SourceLocation EndLoc, - StmtResult AssocStmt); - /// Called after the directive has been completely parsed, including the - /// declaration group or associated statement. - DeclGroupRef ActOnEndOpenACCDeclDirective(); + DeclResult actOnObjCTypeParam(Scope *S, ObjCTypeParamVariance variance, + SourceLocation varianceLoc, unsigned index, + IdentifierInfo *paramName, + SourceLocation paramLoc, + SourceLocation colonLoc, ParsedType typeBound); - /// The kind of conversion being performed. - enum CheckedConversionKind { - /// An implicit conversion. - CCK_ImplicitConversion, - /// A C-style cast. - CCK_CStyleCast, - /// A functional-style cast. - CCK_FunctionalCast, - /// A cast other than a C-style cast. - CCK_OtherCast, - /// A conversion for an operand of a builtin overloaded operator. - CCK_ForBuiltinOverloadedOp + ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc, + ArrayRef typeParams, + SourceLocation rAngleLoc); + void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); + + ObjCInterfaceDecl *ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody); + + void ActOnSuperClassOfClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange); + + void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs, + SmallVectorImpl &ProtocolLocs, + IdentifierInfo *SuperName, + SourceLocation SuperLoc); + + Decl *ActOnCompatibilityAlias(SourceLocation AtCompatibilityAliasLoc, + IdentifierInfo *AliasName, + SourceLocation AliasLocation, + IdentifierInfo *ClassName, + SourceLocation ClassLocation); + + bool CheckForwardProtocolDeclarationForCircularDependency( + IdentifierInfo *PName, SourceLocation &PLoc, SourceLocation PrevLoc, + const ObjCList &PList); + + ObjCProtocolDecl *ActOnStartProtocolInterface( + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefNames, + unsigned NumProtoRefs, const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList, + SkipBodyInfo *SkipBody); + + ObjCCategoryDecl *ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); + + ObjCImplementationDecl *ActOnStartClassImplementation( + SourceLocation AtClassImplLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, IdentifierInfo *SuperClassname, + SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList); + + ObjCCategoryImplDecl *ActOnStartCategoryImplementation( + SourceLocation AtCatImplLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc, + const ParsedAttributesView &AttrList); + + DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl, + ArrayRef Decls); + + DeclGroupPtrTy + ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + ArrayRef IdentList, + const ParsedAttributesView &attrList); + + void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, + ArrayRef ProtocolId, + SmallVectorImpl &Protocols); + + void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, + SourceLocation ProtocolLoc, + IdentifierInfo *TypeArgId, + SourceLocation TypeArgLoc, + bool SelectProtocolFirst = false); + + /// Given a list of identifiers (and their locations), resolve the + /// names to either Objective-C protocol qualifiers or type + /// arguments, as appropriate. + void actOnObjCTypeArgsOrProtocolQualifiers( + Scope *S, ParsedType baseType, SourceLocation lAngleLoc, + ArrayRef identifiers, + ArrayRef identifierLocs, SourceLocation rAngleLoc, + SourceLocation &typeArgsLAngleLoc, SmallVectorImpl &typeArgs, + SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc, + SmallVectorImpl &protocols, SourceLocation &protocolRAngleLoc, + bool warnOnIncompleteProtocols); + + void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID); + + Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd, + ArrayRef allMethods = std::nullopt, + ArrayRef allTUVars = std::nullopt); + + struct ObjCArgInfo { + IdentifierInfo *Name; + SourceLocation NameLoc; + // The Type is null if no type was specified, and the DeclSpec is invalid + // in this case. + ParsedType Type; + ObjCDeclSpec DeclSpec; + + /// ArgAttrs - Attribute list for this argument. + ParsedAttributesView ArgAttrs; + }; + + Decl *ActOnMethodDeclaration( + Scope *S, + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef SelectorLocs, Selector Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind, + bool isVariadic, bool MethodDefinition); + + bool CheckARCMethodDecl(ObjCMethodDecl *method); + + bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); + + /// Check whether the given new method is a valid override of the + /// given overridden method, and set any properties that should be inherited. + void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, + const ObjCMethodDecl *Overridden); + + /// Describes the compatibility of a result type with its method. + enum ResultTypeCompatibilityKind { + RTC_Compatible, + RTC_Incompatible, + RTC_Unknown }; - static bool isCast(CheckedConversionKind CCK) { - return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast || - CCK == CCK_OtherCast; - } + void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, + ObjCMethodDecl *overridden); - /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit - /// cast. If there is already an implicit cast, merge into the existing one. - /// If isLvalue, the result of the cast is an lvalue. - ExprResult - ImpCastExprToType(Expr *E, QualType Type, CastKind CK, - ExprValueKind VK = VK_PRValue, - const CXXCastPath *BasePath = nullptr, - CheckedConversionKind CCK = CCK_ImplicitConversion); + void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, + ObjCInterfaceDecl *CurrentClass, + ResultTypeCompatibilityKind RTC); - /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding - /// to the conversion from scalar type ScalarTy to the Boolean type. - static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy); + /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global + /// pool. + void AddAnyMethodToGlobalPool(Decl *D); - /// IgnoredValueConversions - Given that an expression's result is - /// syntactically ignored, perform any conversions that are - /// required. - ExprResult IgnoredValueConversions(Expr *E); + void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); + bool isObjCMethodDecl(Decl *D) { return D && isa(D); } - // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts - // functions and arrays to their respective pointers (C99 6.3.2.1). - ExprResult UsualUnaryConversions(Expr *E); + /// CheckImplementationIvars - This routine checks if the instance variables + /// listed in the implelementation match those listed in the interface. + void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, + ObjCIvarDecl **Fields, unsigned nIvars, + SourceLocation Loc); - /// CallExprUnaryConversions - a special case of an unary conversion - /// performed on a function designator of a call expression. - ExprResult CallExprUnaryConversions(Expr *E); + void WarnConflictingTypedMethods(ObjCMethodDecl *Method, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl); - // DefaultFunctionArrayConversion - converts functions and arrays - // to their respective pointers (C99 6.3.2.1). - ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true); + void CheckConflictingOverridingMethod(ObjCMethodDecl *Method, + ObjCMethodDecl *Overridden, + bool IsProtocolMethodDecl); - // DefaultFunctionArrayLvalueConversion - converts functions and - // arrays to their respective pointers and performs the - // lvalue-to-rvalue conversion. - ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, - bool Diagnose = true); + /// WarnExactTypedMethods - This routine issues a warning if method + /// implementation declaration matches exactly that of its declaration. + void WarnExactTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl); - // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on - // the operand. This function is a no-op if the operand has a function type - // or an array type. - ExprResult DefaultLvalueConversion(Expr *E); + /// MatchAllMethodDeclarations - Check methods declaraed in interface or + /// or protocol against those declared in their implementations. + void MatchAllMethodDeclarations( + const SelectorSet &InsMap, const SelectorSet &ClsMap, + SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *IDecl, bool &IncompleteImpl, bool ImmediateClass, + bool WarnCategoryMethodImpl = false); - // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that - // do not have a prototype. Integer promotions are performed on each - // argument, and arguments that have type float are promoted to double. - ExprResult DefaultArgumentPromotion(Expr *E); + /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in + /// category matches with those implemented in its primary class and + /// warns each time an exact match is found. + void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); - /// If \p E is a prvalue denoting an unmaterialized temporary, materialize - /// it as an xvalue. In C++98, the result will still be a prvalue, because - /// we don't have xvalues there. - ExprResult TemporaryMaterializationConversion(Expr *E); + /// ImplMethodsVsClassMethods - This is main routine to warn if any method + /// remains unimplemented in the class or category \@implementation. + void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *IDecl, + bool IncompleteImpl = false); - // Used for emitting the right warning by DefaultVariadicArgumentPromotion - enum VariadicCallType { - VariadicFunction, - VariadicBlock, - VariadicMethod, - VariadicConstructor, - VariadicDoesNotApply - }; + DeclGroupPtrTy ActOnForwardClassDeclaration( + SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs, + ArrayRef TypeParamLists, unsigned NumElts); - VariadicCallType getVariadicCallType(FunctionDecl *FDecl, - const FunctionProtoType *Proto, - Expr *Fn); + /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns + /// true, or false, accordingly. + bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, + const ObjCMethodDecl *PrevMethod, + MethodMatchStrategy strategy = MMS_strict); - // Used for determining in which context a type is allowed to be passed to a - // vararg function. - enum VarArgKind { - VAK_Valid, - VAK_ValidInCXX11, - VAK_Undefined, - VAK_MSVCUndefined, - VAK_Invalid - }; + /// Add the given method to the list of globally-known methods. + void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); - // Determines which VarArgKind fits an expression. - VarArgKind isValidVarArgType(const QualType &Ty); + void ReadMethodPool(Selector Sel); + void updateOutOfDateSelector(Selector Sel); - /// Check to see if the given expression is a valid argument to a variadic - /// function, issuing a diagnostic if not. - void checkVariadicArgument(const Expr *E, VariadicCallType CT); + /// - Returns instance or factory methods in global method pool for + /// given selector. It checks the desired kind first, if none is found, and + /// parameter checkTheOther is set, it then checks the other kind. If no such + /// method or only one method is found, function returns false; otherwise, it + /// returns true. + bool + CollectMultipleMethodsInGlobalPool(Selector Sel, + SmallVectorImpl &Methods, + bool InstanceFirst, bool CheckTheOther, + const ObjCObjectType *TypeBound = nullptr); - /// Check whether the given statement can have musttail applied to it, - /// issuing a diagnostic and returning false if not. In the success case, - /// the statement is rewritten to remove implicit nodes from the return - /// value. - bool checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA); + bool + AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, + SourceRange R, bool receiverIdOrClass, + SmallVectorImpl &Methods); -private: - /// Check whether the given statement can have musttail applied to it, - /// issuing a diagnostic and returning false if not. - bool checkMustTailAttr(const Stmt *St, const Attr &MTA); + void + DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods, + Selector Sel, SourceRange R, + bool receiverIdOrClass); -public: - /// Check to see if a given expression could have '.c_str()' called on it. - bool hasCStrMethod(const Expr *E); + const ObjCMethodDecl * + SelectorsForTypoCorrection(Selector Sel, QualType ObjectType = QualType()); + /// LookupImplementedMethodInGlobalPool - Returns the method which has an + /// implementation. + ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel); - /// GatherArgumentsForCall - Collector argument expressions for various - /// form of call prototypes. - bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl, - const FunctionProtoType *Proto, - unsigned FirstParam, ArrayRef Args, - SmallVectorImpl &AllArgs, - VariadicCallType CallType = VariadicDoesNotApply, - bool AllowExplicit = false, - bool IsListInitialization = false); + void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); - // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but - // will create a runtime trap if the resulting type is not a POD type. - ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, - FunctionDecl *FDecl); + /// Checks that the Objective-C declaration is declared in the global scope. + /// Emits an error and marks the declaration as invalid if it's not declared + /// in the global scope. + bool CheckObjCDeclScope(Decl *D); - /// Context in which we're performing a usual arithmetic conversion. - enum ArithConvKind { - /// An arithmetic operation. - ACK_Arithmetic, - /// A bitwise operation. - ACK_BitwiseOp, - /// A comparison. - ACK_Comparison, - /// A conditional (?:) operator. - ACK_Conditional, - /// A compound assignment expression. - ACK_CompAssign, - }; + void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, + IdentifierInfo *ClassName, SmallVectorImpl &Decls); - // UsualArithmeticConversions - performs the UsualUnaryConversions on it's - // operands and then handles various conversions that are common to binary - // operators (C99 6.3.1.8). If both operands aren't arithmetic, this - // routine returns the first non-arithmetic type found. The client is - // responsible for emitting appropriate error diagnostics. - QualType UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, ArithConvKind ACK); + VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, bool Invalid = false); - /// AssignConvertType - All of the 'assignment' semantic checks return this - /// enum to indicate whether the assignment was allowed. These checks are - /// done for simple assignments, as well as initialization, return from - /// function, argument passing, etc. The query is phrased in terms of a - /// source and destination type. - enum AssignConvertType { - /// Compatible - the types are compatible according to the standard. - Compatible, + Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D); - /// PointerToInt - The assignment converts a pointer to an int, which we - /// accept as an extension. - PointerToInt, + /// CollectIvarsToConstructOrDestruct - Collect those ivars which require + /// initialization. + void + CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, + SmallVectorImpl &Ivars); - /// IntToPointer - The assignment converts an int to a pointer, which we - /// accept as an extension. - IntToPointer, + void DiagnoseUseOfUnimplementedSelectors(); - /// FunctionVoidPointer - The assignment is between a function pointer and - /// void*, which the standard doesn't allow, but we accept as an extension. - FunctionVoidPointer, + /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar + /// which backs the property is not used in the property's accessor. + void DiagnoseUnusedBackingIvarInAccessor(Scope *S, + const ObjCImplementationDecl *ImplD); - /// IncompatiblePointer - The assignment is between two pointers types that - /// are not compatible, but we accept them as an extension. - IncompatiblePointer, + /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and + /// it property has a backing ivar, returns this ivar; otherwise, returns + /// NULL. It also returns ivar's property on success. + ObjCIvarDecl * + GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, + const ObjCPropertyDecl *&PDecl) const; - /// IncompatibleFunctionPointer - The assignment is between two function - /// pointers types that are not compatible, but we accept them as an - /// extension. - IncompatibleFunctionPointer, + /// AddInstanceMethodToGlobalPool - All instance methods in a translation + /// unit are added to a global pool. This allows us to efficiently associate + /// a selector with a method declaraation for purposes of typechecking + /// messages sent to "id" (where the class of the object is unknown). + void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, + bool impl = false) { + AddMethodToGlobalPool(Method, impl, /*instance*/ true); + } - /// IncompatibleFunctionPointerStrict - The assignment is between two - /// function pointer types that are not identical, but are compatible, - /// unless compiled with -fsanitize=cfi, in which case the type mismatch - /// may trip an indirect call runtime check. - IncompatibleFunctionPointerStrict, + /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods. + void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl = false) { + AddMethodToGlobalPool(Method, impl, /*instance*/ false); + } - /// IncompatiblePointerSign - The assignment is between two pointers types - /// which point to integers which have a different sign, but are otherwise - /// identical. This is a subset of the above, but broken out because it's by - /// far the most common case of incompatible pointers. - IncompatiblePointerSign, +private: + /// AddMethodToGlobalPool - Add an instance or factory method to the global + /// pool. See descriptoin of AddInstanceMethodToGlobalPool. + void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance); - /// CompatiblePointerDiscardsQualifiers - The assignment discards - /// c/v/r qualifiers, which we accept as an extension. - CompatiblePointerDiscardsQualifiers, + /// LookupMethodInGlobalPool - Returns the instance or factory method and + /// optionally warns if there are multiple signatures. + ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass, + bool instance); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // - /// IncompatiblePointerDiscardsQualifiers - The assignment - /// discards qualifiers that we don't permit to be discarded, - /// like address spaces. - IncompatiblePointerDiscardsQualifiers, + /// \name ObjC Expressions + /// Implementations are in SemaExprObjC.cpp + ///@{ - /// IncompatibleNestedPointerAddressSpaceMismatch - The assignment - /// changes address spaces in nested pointer types which is not allowed. - /// For instance, converting __private int ** to __generic int ** is - /// illegal even though __private could be converted to __generic. - IncompatibleNestedPointerAddressSpaceMismatch, +public: + /// Caches identifiers/selectors for NSFoundation APIs. + std::unique_ptr NSAPIObj; - /// IncompatibleNestedPointerQualifiers - The assignment is between two - /// nested pointer types, and the qualifiers other than the first two - /// levels differ e.g. char ** -> const char **, but we accept them as an - /// extension. - IncompatibleNestedPointerQualifiers, + /// The declaration of the Objective-C NSNumber class. + ObjCInterfaceDecl *NSNumberDecl; - /// IncompatibleVectors - The assignment is between two vector types that - /// have the same size, which we accept as an extension. - IncompatibleVectors, + /// The declaration of the Objective-C NSValue class. + ObjCInterfaceDecl *NSValueDecl; - /// IntToBlockPointer - The assignment converts an int to a block - /// pointer. We disallow this. - IntToBlockPointer, + /// Pointer to NSNumber type (NSNumber *). + QualType NSNumberPointer; - /// IncompatibleBlockPointer - The assignment is between two block - /// pointers types that are not compatible. - IncompatibleBlockPointer, + /// Pointer to NSValue type (NSValue *). + QualType NSValuePointer; - /// IncompatibleObjCQualifiedId - The assignment is between a qualified - /// id type and something else (that is incompatible with it). For example, - /// "id " = "Foo *", where "Foo *" doesn't implement the XXX protocol. - IncompatibleObjCQualifiedId, + /// The Objective-C NSNumber methods used to create NSNumber literals. + ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; - /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an - /// object with __weak qualifier. - IncompatibleObjCWeakRef, + /// The declaration of the Objective-C NSString class. + ObjCInterfaceDecl *NSStringDecl; - /// Incompatible - We reject this conversion outright, it is invalid to - /// represent it in the AST. - Incompatible - }; + /// Pointer to NSString type (NSString *). + QualType NSStringPointer; - /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the - /// assignment conversion type specified by ConvTy. This returns true if the - /// conversion was invalid or false if the conversion was accepted. - bool DiagnoseAssignmentResult(AssignConvertType ConvTy, - SourceLocation Loc, - QualType DstType, QualType SrcType, - Expr *SrcExpr, AssignmentAction Action, - bool *Complained = nullptr); + /// The declaration of the stringWithUTF8String: method. + ObjCMethodDecl *StringWithUTF8StringMethod; - /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag - /// enum. If AllowMask is true, then we also allow the complement of a valid - /// value, to be used as a mask. - bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, - bool AllowMask) const; + /// The declaration of the valueWithBytes:objCType: method. + ObjCMethodDecl *ValueWithBytesObjCTypeMethod; - /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant - /// integer not in the range of enum values. - void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, - Expr *SrcExpr); + /// The declaration of the Objective-C NSArray class. + ObjCInterfaceDecl *NSArrayDecl; - /// CheckAssignmentConstraints - Perform type checking for assignment, - /// argument passing, variable initialization, and function return values. - /// C99 6.5.16. - AssignConvertType CheckAssignmentConstraints(SourceLocation Loc, - QualType LHSType, - QualType RHSType); + /// The declaration of the arrayWithObjects:count: method. + ObjCMethodDecl *ArrayWithObjectsMethod; - /// Check assignment constraints and optionally prepare for a conversion of - /// the RHS to the LHS type. The conversion is prepared for if ConvertRHS - /// is true. - AssignConvertType CheckAssignmentConstraints(QualType LHSType, - ExprResult &RHS, - CastKind &Kind, - bool ConvertRHS = true); + /// The declaration of the Objective-C NSDictionary class. + ObjCInterfaceDecl *NSDictionaryDecl; - /// Check assignment constraints for an assignment of RHS to LHSType. - /// - /// \param LHSType The destination type for the assignment. - /// \param RHS The source expression for the assignment. - /// \param Diagnose If \c true, diagnostics may be produced when checking - /// for assignability. If a diagnostic is produced, \p RHS will be - /// set to ExprError(). Note that this function may still return - /// without producing a diagnostic, even for an invalid assignment. - /// \param DiagnoseCFAudited If \c true, the target is a function parameter - /// in an audited Core Foundation API and does not need to be checked - /// for ARC retain issues. - /// \param ConvertRHS If \c true, \p RHS will be updated to model the - /// conversions necessary to perform the assignment. If \c false, - /// \p Diagnose must also be \c false. - AssignConvertType CheckSingleAssignmentConstraints( - QualType LHSType, ExprResult &RHS, bool Diagnose = true, - bool DiagnoseCFAudited = false, bool ConvertRHS = true); + /// The declaration of the dictionaryWithObjects:forKeys:count: method. + ObjCMethodDecl *DictionaryWithObjectsMethod; - // If the lhs type is a transparent union, check whether we - // can initialize the transparent union with the given expression. - AssignConvertType CheckTransparentUnionArgumentConstraints(QualType ArgType, - ExprResult &RHS); + /// id type. + QualType QIDNSCopying; - bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType); + /// will hold 'respondsToSelector:' + Selector RespondsToSelectorSel; - bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); + ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, + Expr *BaseExpr, SourceLocation OpLoc, + DeclarationName MemberName, + SourceLocation MemberLoc, + SourceLocation SuperLoc, + QualType SuperType, bool Super); - ExprResult PerformImplicitConversion(Expr *From, QualType ToType, - AssignmentAction Action, - bool AllowExplicit = false); - ExprResult PerformImplicitConversion(Expr *From, QualType ToType, - const ImplicitConversionSequence& ICS, - AssignmentAction Action, - CheckedConversionKind CCK - = CCK_ImplicitConversion); - ExprResult PerformImplicitConversion(Expr *From, QualType ToType, - const StandardConversionSequence& SCS, - AssignmentAction Action, - CheckedConversionKind CCK); + ExprResult ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc); - ExprResult PerformQualificationConversion( - Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue, - CheckedConversionKind CCK = CCK_ImplicitConversion); + // ParseObjCStringLiteral - Parse Objective-C string literals. + ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, + ArrayRef Strings); - /// the following "Check" methods will return a valid/converted QualType - /// or a null QualType (indicating an error diagnostic was issued). + ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S); - /// type checking binary operators (subroutines of CreateBuiltinBinOp). - QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS, - ExprResult &RHS); - QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, - ExprResult &RHS); - QualType CheckPointerToMemberOperands( // C++ 5.5 - ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, - SourceLocation OpLoc, bool isIndirect); - QualType CheckMultiplyDivideOperands( // C99 6.5.5 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign, - bool IsDivide); - QualType CheckRemainderOperands( // C99 6.5.5 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - bool IsCompAssign = false); - QualType CheckAdditionOperands( // C99 6.5.6 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - BinaryOperatorKind Opc, QualType* CompLHSTy = nullptr); - QualType CheckSubtractionOperands( // C99 6.5.6 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - QualType* CompLHSTy = nullptr); - QualType CheckShiftOperands( // C99 6.5.7 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - BinaryOperatorKind Opc, bool IsCompAssign = false); - void CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE); - QualType CheckCompareOperands( // C99 6.5.8/9 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - BinaryOperatorKind Opc); - QualType CheckBitwiseOperands( // C99 6.5.[10...12] - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - BinaryOperatorKind Opc); - QualType CheckLogicalOperands( // C99 6.5.[13,14] - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - BinaryOperatorKind Opc); - // CheckAssignmentOperands is used for both simple and compound assignment. - // For simple assignment, pass both expressions and a null converted type. - // For compound assignment, pass both expressions and the converted type. - QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] - Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType, - BinaryOperatorKind Opc); + /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the + /// numeric literal expression. Type of the expression will be "NSNumber *" + /// or "id" if NSNumber is unavailable. + ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number); + ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc, + bool Value); + ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements); - ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc, - UnaryOperatorKind Opcode, Expr *Op); - ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc, - BinaryOperatorKind Opcode, - Expr *LHS, Expr *RHS); - ExprResult checkPseudoObjectRValue(Expr *E); - Expr *recreateSyntacticForm(PseudoObjectExpr *E); + /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the + /// '@' prefixed parenthesized expression. The type of the expression will + /// either be "NSNumber *", "NSString *" or "NSValue *" depending on the type + /// of ValueType, which is allowed to be a built-in numeric type, "char *", + /// "const char *" or C structure with attribute 'objc_boxable'. + ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr); - QualType CheckConditionalOperands( // C99 6.5.15 - ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, - ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc); - QualType CXXCheckConditionalOperands( // C++ 5.16 - ExprResult &cond, ExprResult &lhs, ExprResult &rhs, - ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); - QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS, - ExprResult &RHS, - SourceLocation QuestionLoc); + ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr, + Expr *IndexExpr, + ObjCMethodDecl *getterMethod, + ObjCMethodDecl *setterMethod); - QualType CheckSizelessVectorConditionalTypes(ExprResult &Cond, - ExprResult &LHS, ExprResult &RHS, - SourceLocation QuestionLoc); - QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, - bool ConvertArgs = true); - QualType FindCompositePointerType(SourceLocation Loc, - ExprResult &E1, ExprResult &E2, - bool ConvertArgs = true) { - Expr *E1Tmp = E1.get(), *E2Tmp = E2.get(); - QualType Composite = - FindCompositePointerType(Loc, E1Tmp, E2Tmp, ConvertArgs); - E1 = E1Tmp; - E2 = E2Tmp; - return Composite; - } + ExprResult + BuildObjCDictionaryLiteral(SourceRange SR, + MutableArrayRef Elements); - QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, - SourceLocation QuestionLoc); + ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc, + TypeSourceInfo *EncodedTypeInfo, + SourceLocation RParenLoc); - bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, - SourceLocation QuestionLoc); + ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncodeLoc, + SourceLocation LParenLoc, ParsedType Ty, + SourceLocation RParenLoc); - void DiagnoseAlwaysNonNullPointer(Expr *E, - Expr::NullPointerConstantKind NullType, - bool IsEqual, SourceRange Range); + /// ParseObjCSelectorExpression - Build selector expression for \@selector + ExprResult ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + bool WarnMultipleSelectors); - /// type checking for vector binary operators. - QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, bool IsCompAssign, - bool AllowBothBool, bool AllowBoolConversion, - bool AllowBoolOperation, bool ReportInvalid); - QualType GetSignedVectorType(QualType V); - QualType GetSignedSizelessVectorType(QualType V); - QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, - BinaryOperatorKind Opc); - QualType CheckSizelessVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, - BinaryOperatorKind Opc); - QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc); + /// ParseObjCProtocolExpression - Build protocol expression for \@protocol + ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolName, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation ProtoIdLoc, + SourceLocation RParenLoc); - // type checking for sizeless vector binary operators. - QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, bool IsCompAssign, - ArithConvKind OperationKind); + ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc); - /// Type checking for matrix binary operators. - QualType CheckMatrixElementwiseOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, - bool IsCompAssign); - QualType CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, bool IsCompAssign); + /// Describes the kind of message expression indicated by a message + /// send that starts with an identifier. + enum ObjCMessageKind { + /// The message is sent to 'super'. + ObjCSuperMessage, + /// The message is an instance message. + ObjCInstanceMessage, + /// The message is a class message, and the identifier is a type + /// name. + ObjCClassMessage + }; - bool isValidSveBitcast(QualType srcType, QualType destType); - bool isValidRVVBitcast(QualType srcType, QualType destType); + ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name, + SourceLocation NameLoc, bool IsSuper, + bool HasTrailingDot, + ParsedType &ReceiverType); - bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy); + ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args); - bool areVectorTypesSameSize(QualType srcType, QualType destType); - bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType); - bool isLaxVectorConversion(QualType srcType, QualType destType); - bool anyAltivecTypes(QualType srcType, QualType destType); + ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, + QualType ReceiverType, SourceLocation SuperLoc, + Selector Sel, ObjCMethodDecl *Method, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args, + bool isImplicit = false); - /// type checking declaration initializers (C99 6.7.8) - bool CheckForConstantInitializer(Expr *e, QualType t); + ExprResult BuildClassMessageImplicit(QualType ReceiverType, + bool isSuperReceiver, SourceLocation Loc, + Selector Sel, ObjCMethodDecl *Method, + MultiExprArg Args); - // type checking C++ declaration initializers (C++ [dcl.init]). + ExprResult ActOnClassMessage(Scope *S, ParsedType Receiver, Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args); - /// ReferenceCompareResult - Expresses the result of comparing two - /// types (cv1 T1 and cv2 T2) to determine their compatibility for the - /// purposes of initialization by reference (C++ [dcl.init.ref]p4). - enum ReferenceCompareResult { - /// Ref_Incompatible - The two types are incompatible, so direct - /// reference binding is not possible. - Ref_Incompatible = 0, - /// Ref_Related - The two types are reference-related, which means - /// that their unqualified forms (T1 and T2) are either the same - /// or T1 is a base class of T2. - Ref_Related, - /// Ref_Compatible - The two types are reference-compatible. - Ref_Compatible - }; + ExprResult BuildInstanceMessage(Expr *Receiver, QualType ReceiverType, + SourceLocation SuperLoc, Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args, + bool isImplicit = false); - // Fake up a scoped enumeration that still contextually converts to bool. - struct ReferenceConversionsScope { - /// The conversions that would be performed on an lvalue of type T2 when - /// binding a reference of type T1 to it, as determined when evaluating - /// whether T1 is reference-compatible with T2. - enum ReferenceConversions { - Qualification = 0x1, - NestedQualification = 0x2, - Function = 0x4, - DerivedToBase = 0x8, - ObjC = 0x10, - ObjCLifetime = 0x20, + ExprResult BuildInstanceMessageImplicit(Expr *Receiver, QualType ReceiverType, + SourceLocation Loc, Selector Sel, + ObjCMethodDecl *Method, + MultiExprArg Args); - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime) - }; - }; - using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions; + ExprResult ActOnInstanceMessage(Scope *S, Expr *Receiver, Selector Sel, + SourceLocation LBracLoc, + ArrayRef SelectorLocs, + SourceLocation RBracLoc, MultiExprArg Args); - ReferenceCompareResult - CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2, - ReferenceConversions *Conv = nullptr); + ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + TypeSourceInfo *TSInfo, Expr *SubExpr); - ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, - Expr *CastExpr, CastKind &CastKind, - ExprValueKind &VK, CXXCastPath &Path); + ExprResult ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc, + ObjCBridgeCastKind Kind, + SourceLocation BridgeKeywordLoc, + ParsedType Type, SourceLocation RParenLoc, + Expr *SubExpr); - /// Force an expression with unknown-type to an expression of the - /// given type. - ExprResult forceUnknownAnyToType(Expr *E, QualType ToType); + void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr); - /// Type-check an expression that's being passed to an - /// __unknown_anytype parameter. - ExprResult checkUnknownAnyArg(SourceLocation callLoc, - Expr *result, QualType ¶mType); + void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr); - // CheckMatrixCast - Check type constraints for matrix casts. - // We allow casting between matrixes of the same dimensions i.e. when they - // have the same number of rows and column. Returns true if the cast is - // invalid. - bool CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy, - CastKind &Kind); + bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr, + CastKind &Kind); - // CheckVectorCast - check type constraints for vectors. - // Since vectors are an extension, there are no C standard reference for this. - // We allow casting between vectors and integer datatypes of the same size. - // returns true if the cast is invalid - bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, - CastKind &Kind); + bool checkObjCBridgeRelatedComponents(SourceLocation Loc, QualType DestType, + QualType SrcType, + ObjCInterfaceDecl *&RelatedClass, + ObjCMethodDecl *&ClassMethod, + ObjCMethodDecl *&InstanceMethod, + TypedefNameDecl *&TDNDecl, bool CfToNs, + bool Diagnose = true); - /// Prepare `SplattedExpr` for a vector splat operation, adding - /// implicit casts if necessary. - ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr); + bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType, + QualType SrcType, Expr *&SrcExpr, + bool Diagnose = true); - // CheckExtVectorCast - check type constraints for extended vectors. - // Since vectors are an extension, there are no C standard reference for this. - // We allow casting between vectors and integer datatypes of the same size, - // or vectors and the element type of that vector. - // returns the cast expr - ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr, - CastKind &Kind); + /// Private Helper predicate to check for 'self'. + bool isSelfExpr(Expr *RExpr); + bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method); - ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type, - SourceLocation LParenLoc, - Expr *CastExpr, - SourceLocation RParenLoc); + ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool IsInstance); + ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty, + bool IsInstance); + + bool isKnownName(StringRef name); enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error }; @@ -13305,8 +12608,7 @@ class Sema final { CheckedConversionKind CCK, bool Diagnose = true, bool DiagnoseCFAudited = false, - BinaryOperatorKind Opc = BO_PtrMemD - ); + BinaryOperatorKind Opc = BO_PtrMemD); Expr *stripARCUnbridgedCast(Expr *e); void diagnoseARCUnbridgedCast(Expr *e); @@ -13314,20 +12616,6 @@ class Sema final { bool CheckObjCARCUnavailableWeakConversion(QualType castType, QualType ExprType); - /// checkRetainCycles - Check whether an Objective-C message send - /// might create an obvious retain cycle. - void checkRetainCycles(ObjCMessageExpr *msg); - void checkRetainCycles(Expr *receiver, Expr *argument); - void checkRetainCycles(VarDecl *Var, Expr *Init); - - /// checkUnsafeAssigns - Check whether +1 expr is being assigned - /// to weak/__unsafe_unretained type. - bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS); - - /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned - /// to weak/__unsafe_unretained expression. - void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS); - /// CheckMessageArgumentTypes - Check types in an Obj-C message send. /// \param Method - May be null. /// \param [out] ReturnType - The return type of the send. @@ -13356,142 +12644,398 @@ class Sema final { /// type, and if so, emit a note describing what happened. void EmitRelatedResultTypeNoteForReturn(QualType destType); - class ConditionResult { - Decl *ConditionVar; - FullExprArg Condition; - bool Invalid; - std::optional KnownValue; + /// LookupInstanceMethodInGlobalPool - Returns the method and warns if + /// there are multiple signatures. + ObjCMethodDecl * + LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass = false) { + return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, + /*instance*/ true); + } - friend class Sema; - ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition, - bool IsConstexpr) - : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) { - if (IsConstexpr && Condition.get()) { - if (std::optional Val = - Condition.get()->getIntegerConstantExpr(S.Context)) { - KnownValue = !!(*Val); - } - } - } - explicit ConditionResult(bool Invalid) - : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid), - KnownValue(std::nullopt) {} + /// LookupFactoryMethodInGlobalPool - Returns the method and warns if + /// there are multiple signatures. + ObjCMethodDecl * + LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass = false) { + return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass, + /*instance*/ false); + } - public: - ConditionResult() : ConditionResult(false) {} - bool isInvalid() const { return Invalid; } - std::pair get() const { - return std::make_pair(cast_or_null(ConditionVar), - Condition.get()); - } - std::optional getKnownValue() const { return KnownValue; } - }; - static ConditionResult ConditionError() { return ConditionResult(true); } + ///@} - enum class ConditionKind { - Boolean, ///< A boolean condition, from 'if', 'while', 'for', or 'do'. - ConstexprIf, ///< A constant boolean condition from 'if constexpr'. - Switch ///< An integral condition for a 'switch' statement. - }; - QualType PreferredConditionType(ConditionKind K) const { - return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy; - } + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name ObjC @property and @synthesize + /// Implementations are in SemaObjCProperty.cpp + ///@{ + +public: + /// Ensure attributes are consistent with type. + /// \param [in, out] Attributes The attributes to check; they will + /// be modified to be consistent with \p PropertyTy. + void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc, + unsigned &Attributes, + bool propertyInPrimaryClass); + + /// Process the specified property declaration and create decls for the + /// setters and getters as needed. + /// \param property The property declaration being processed + void ProcessPropertyDecl(ObjCPropertyDecl *property); + + Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, + FieldDeclarator &FD, ObjCDeclSpec &ODS, + Selector GetterSel, Selector SetterSel, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC = nullptr); + + Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, + SourceLocation PropertyLoc, bool ImplKind, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar, + SourceLocation PropertyIvarLoc, + ObjCPropertyQueryKind QueryKind); + + /// Called by ActOnProperty to handle \@property declarations in + /// class extensions. + ObjCPropertyDecl *HandlePropertyInClassExtension( + Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, + FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc, + Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite, + unsigned &Attributes, const unsigned AttributesAsWritten, QualType T, + TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind); + + /// Called by ActOnProperty and HandlePropertyInClassExtension to + /// handle creating the ObjcPropertyDecl for a category or \@interface. + ObjCPropertyDecl * + CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, + SourceLocation LParenLoc, FieldDeclarator &FD, + Selector GetterSel, SourceLocation GetterNameLoc, + Selector SetterSel, SourceLocation SetterNameLoc, + const bool isReadWrite, const unsigned Attributes, + const unsigned AttributesAsWritten, QualType T, + TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC = nullptr); + + void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, + ObjCPropertyDecl *SuperProperty, + const IdentifierInfo *Name, + bool OverridingProtocolProperty); + + bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, + ObjCMethodDecl *Getter, + SourceLocation Loc); + + /// DiagnoseUnimplementedProperties - This routine warns on those properties + /// which must be implemented by this implementation. + void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl, + ObjCContainerDecl *CDecl, + bool SynthesizeProperties); + + /// Diagnose any null-resettable synthesized setters. + void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl); + + /// DefaultSynthesizeProperties - This routine default synthesizes all + /// properties which must be synthesized in the class's \@implementation. + void DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, + ObjCInterfaceDecl *IDecl, + SourceLocation AtEnd); + void DefaultSynthesizeProperties(Scope *S, Decl *D, SourceLocation AtEnd); + + /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is + /// an ivar synthesized for 'Method' and 'Method' is a property accessor + /// declared in class 'IFace'. + bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, + ObjCMethodDecl *Method, ObjCIvarDecl *IV); + + void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D); + + void + DiagnoseMissingDesignatedInitOverrides(const ObjCImplementationDecl *ImplD, + const ObjCInterfaceDecl *IFD); + + /// AtomicPropertySetterGetterRules - This routine enforces the rule (via + /// warning) when atomic property has one but not the other user-declared + /// setter or getter. + void AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl, + ObjCInterfaceDecl *IDecl); + + ///@} - ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr, - ConditionKind CK, bool MissingOK = false); + // + // + // ------------------------------------------------------------------------- + // + // - ConditionResult ActOnConditionVariable(Decl *ConditionVar, - SourceLocation StmtLoc, - ConditionKind CK); + /// \name Code Completion + /// Implementations are in SemaCodeComplete.cpp + ///@{ - DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); +public: + /// Code-completion consumer. + CodeCompleteConsumer *CodeCompleter; - ExprResult CheckConditionVariable(VarDecl *ConditionVar, - SourceLocation StmtLoc, - ConditionKind CK); - ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond); + /// Describes the context in which code completion occurs. + enum ParserCompletionContext { + /// Code completion occurs at top-level or namespace context. + PCC_Namespace, + /// Code completion occurs within a class, struct, or union. + PCC_Class, + /// Code completion occurs within an Objective-C interface, protocol, + /// or category. + PCC_ObjCInterface, + /// Code completion occurs within an Objective-C implementation or + /// category implementation + PCC_ObjCImplementation, + /// Code completion occurs within the list of instance variables + /// in an Objective-C interface, protocol, category, or implementation. + PCC_ObjCInstanceVariableList, + /// Code completion occurs following one or more template + /// headers. + PCC_Template, + /// Code completion occurs following one or more template + /// headers within a class. + PCC_MemberTemplate, + /// Code completion occurs within an expression. + PCC_Expression, + /// Code completion occurs within a statement, which may + /// also be an expression or a declaration. + PCC_Statement, + /// Code completion occurs at the beginning of the + /// initialization statement (or expression) in a for loop. + PCC_ForInit, + /// Code completion occurs within the condition of an if, + /// while, switch, or for statement. + PCC_Condition, + /// Code completion occurs within the body of a function on a + /// recovery path, where we do not have a specific handle on our position + /// in the grammar. + PCC_RecoveryInFunction, + /// Code completion occurs where only a type is permitted. + PCC_Type, + /// Code completion occurs in a parenthesized expression, which + /// might also be a type cast. + PCC_ParenthesizedExpression, + /// Code completion occurs within a sequence of declaration + /// specifiers within a function, method, or block. + PCC_LocalDeclarationSpecifiers, + /// Code completion occurs at top-level in a REPL session + PCC_TopLevelOrExpression, + }; - /// CheckBooleanCondition - Diagnose problems involving the use of - /// the given expression as a boolean condition (e.g. in an if - /// statement). Also performs the standard function and array - /// decays, possibly changing the input variable. + void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); + void CodeCompleteOrdinaryName(Scope *S, + ParserCompletionContext CompletionContext); + void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers); + + struct CodeCompleteExpressionData; + void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); + void CodeCompleteExpression(Scope *S, QualType PreferredType, + bool IsParenthesized = false); + void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, + SourceLocation OpLoc, bool IsArrow, + bool IsBaseExprStatement, + QualType PreferredType); + void CodeCompletePostfixExpression(Scope *S, ExprResult LHS, + QualType PreferredType); + void CodeCompleteTag(Scope *S, unsigned TagSpec); + void CodeCompleteTypeQualifiers(DeclSpec &DS); + void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, + const VirtSpecifiers *VS = nullptr); + void CodeCompleteBracketDeclarator(Scope *S); + void CodeCompleteCase(Scope *S); + enum class AttributeCompletion { + Attribute, + Scope, + None, + }; + void CodeCompleteAttribute( + AttributeCommonInfo::Syntax Syntax, + AttributeCompletion Completion = AttributeCompletion::Attribute, + const IdentifierInfo *Scope = nullptr); + /// Determines the preferred type of the current function argument, by + /// examining the signatures of all possible overloads. + /// Returns null if unknown or ambiguous, or if code completion is off. /// - /// \param Loc - A location associated with the condition, e.g. the - /// 'if' keyword. - /// \return true iff there were any errors - ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, - bool IsConstexpr = false); + /// If the code completion point has been reached, also reports the function + /// signatures that were considered. + /// + /// FIXME: rename to GuessCallArgumentType to reduce confusion. + QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, + SourceLocation OpenParLoc); + QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, + ArrayRef Args, + SourceLocation OpenParLoc, + bool Braced); + QualType ProduceCtorInitMemberSignatureHelp( + Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, + ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc, + bool Braced); + QualType ProduceTemplateArgumentSignatureHelp( + TemplateTy, ArrayRef, SourceLocation LAngleLoc); + void CodeCompleteInitializer(Scope *S, Decl *D); + /// Trigger code completion for a record of \p BaseType. \p InitExprs are + /// expressions in the initializer list seen so far and \p D is the current + /// Designation being parsed. + void CodeCompleteDesignator(const QualType BaseType, + llvm::ArrayRef InitExprs, + const Designation &D); + void CodeCompleteAfterIf(Scope *S, bool IsBracedThen); - /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression - /// found in an explicit(bool) specifier. - ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E); + void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext, + bool IsUsingDeclaration, QualType BaseType, + QualType PreferredType); + void CodeCompleteUsing(Scope *S); + void CodeCompleteUsingDirective(Scope *S); + void CodeCompleteNamespaceDecl(Scope *S); + void CodeCompleteNamespaceAliasDecl(Scope *S); + void CodeCompleteOperatorName(Scope *S); + void CodeCompleteConstructorInitializer( + Decl *Constructor, ArrayRef Initializers); - /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier. - /// Returns true if the explicit specifier is now resolved. - bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec); + void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, + bool AfterAmpersand); + void CodeCompleteAfterFunctionEquals(Declarator &D); - /// DiagnoseAssignmentAsCondition - Given that an expression is - /// being used as a boolean condition, warn if it's an assignment. - void DiagnoseAssignmentAsCondition(Expr *E); + void CodeCompleteObjCAtDirective(Scope *S); + void CodeCompleteObjCAtVisibility(Scope *S); + void CodeCompleteObjCAtStatement(Scope *S); + void CodeCompleteObjCAtExpression(Scope *S); + void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); + void CodeCompleteObjCPropertyGetter(Scope *S); + void CodeCompleteObjCPropertySetter(Scope *S); + void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, + bool IsParameter); + void CodeCompleteObjCMessageReceiver(Scope *S); + void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + ArrayRef SelIdents, + bool AtArgumentExpression); + void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, + ArrayRef SelIdents, + bool AtArgumentExpression, + bool IsSuper = false); + void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, + ArrayRef SelIdents, + bool AtArgumentExpression, + ObjCInterfaceDecl *Super = nullptr); + void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar); + void CodeCompleteObjCSelector(Scope *S, ArrayRef SelIdents); + void + CodeCompleteObjCProtocolReferences(ArrayRef Protocols); + void CodeCompleteObjCProtocolDecl(Scope *S); + void CodeCompleteObjCInterfaceDecl(Scope *S); + void CodeCompleteObjCClassForwardDecl(Scope *S); + void CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCImplementationDecl(Scope *S); + void CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc); + void CodeCompleteObjCPropertyDefinition(Scope *S); + void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName); + void CodeCompleteObjCMethodDecl(Scope *S, + std::optional IsInstanceMethod, + ParsedType ReturnType); + void CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, + bool AtParameterName, + ParsedType ReturnType, + ArrayRef SelIdents); + void CodeCompleteObjCClassPropertyRefExpr(Scope *S, IdentifierInfo &ClassName, + SourceLocation ClassNameLoc, + bool IsBaseExprStatement); + void CodeCompletePreprocessorDirective(bool InConditional); + void CodeCompleteInPreprocessorConditionalExclusion(Scope *S); + void CodeCompletePreprocessorMacroName(bool IsDefinition); + void CodeCompletePreprocessorExpression(); + void CodeCompletePreprocessorMacroArgument(Scope *S, IdentifierInfo *Macro, + MacroInfo *MacroInfo, + unsigned Argument); + void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled); + void CodeCompleteNaturalLanguage(); + void CodeCompleteAvailabilityPlatformName(); + void + GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + SmallVectorImpl &Results); - /// Redundant parentheses over an equality comparison can indicate - /// that the user intended an assignment used as condition. - void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE); + ///@} - /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. - ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false); + // + // + // ------------------------------------------------------------------------- + // + // - /// Checks that the Objective-C declaration is declared in the global scope. - /// Emits an error and marks the declaration as invalid if it's not declared - /// in the global scope. - bool CheckObjCDeclScope(Decl *D); + /// \name FixIt Helpers + /// Implementations are in SemaFixItUtils.cpp + ///@{ - /// Abstract base class used for diagnosing integer constant - /// expression violations. - class VerifyICEDiagnoser { - public: - bool Suppress; +public: + /// Get a string to suggest for zero-initialization of a type. + std::string getFixItZeroInitializerForType(QualType T, + SourceLocation Loc) const; + std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const; - VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { } + ///@} - virtual SemaDiagnosticBuilder - diagnoseNotICEType(Sema &S, SourceLocation Loc, QualType T); - virtual SemaDiagnosticBuilder diagnoseNotICE(Sema &S, - SourceLocation Loc) = 0; - virtual SemaDiagnosticBuilder diagnoseFold(Sema &S, SourceLocation Loc); - virtual ~VerifyICEDiagnoser() {} - }; + // + // + // ------------------------------------------------------------------------- + // + // - enum AllowFoldKind { - NoFold, - AllowFold, - }; + /// \name API Notes + /// Implementations are in SemaAPINotes.cpp + ///@{ - /// VerifyIntegerConstantExpression - Verifies that an expression is an ICE, - /// and reports the appropriate diagnostics. Returns false on success. - /// Can optionally return the value of the expression. - ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, - VerifyICEDiagnoser &Diagnoser, - AllowFoldKind CanFold = NoFold); - ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, - unsigned DiagID, - AllowFoldKind CanFold = NoFold); - ExprResult VerifyIntegerConstantExpression(Expr *E, - llvm::APSInt *Result = nullptr, - AllowFoldKind CanFold = NoFold); - ExprResult VerifyIntegerConstantExpression(Expr *E, - AllowFoldKind CanFold = NoFold) { - return VerifyIntegerConstantExpression(E, nullptr, CanFold); - } +public: + /// Map any API notes provided for this declaration to attributes on the + /// declaration. + /// + /// Triggered by declaration-attribute processing. + void ProcessAPINotes(Decl *D); - /// VerifyBitField - verifies that a bit field expression is an ICE and has - /// the correct width, and that the field type is valid. - /// Returns false on success. - ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, bool IsMsStruct, Expr *BitWidth); + ///@} + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name Name Lookup for RISC-V Vector Intrinsic + /// Implementations are in SemaRISCVVectorLookup.cpp + ///@{ + +public: + /// Indicate RISC-V vector builtin functions enabled or not. + bool DeclareRISCVVBuiltins = false; + + /// Indicate RISC-V SiFive vector builtin functions enabled or not. + bool DeclareRISCVSiFiveVectorBuiltins = false; private: - unsigned ForceCUDAHostDeviceDepth = 0; + std::unique_ptr RVIntrinsicManager; + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name CUDA + /// Implementations are in SemaCUDA.cpp + ///@{ public: /// Increments our count of the number of times we've seen a pragma forcing @@ -13504,6 +13048,10 @@ class Sema final { /// before incrementing, so you can emit an error. bool PopForceCUDAHostDevice(); + ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, + MultiExprArg ExecConfig, + SourceLocation GGGLoc); + /// Diagnostics that are emitted only if we discover that the given function /// must be codegen'ed. Because handling these correctly adds overhead to /// compilation, this is currently only enabled for CUDA compilations. @@ -13558,54 +13106,6 @@ class Sema final { /// Same as CUDADiagIfDeviceCode, with "host" and "device" switched. SemaDiagnosticBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID); - /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current - /// context is "used as device code". - /// - /// - If CurContext is a `declare target` function or it is known that the - /// function is emitted for the device, emits the diagnostics immediately. - /// - If CurContext is a non-`declare target` function and we are compiling - /// for the device, creates a diagnostic which is emitted if and when we - /// realize that the function will be codegen'ed. - /// - /// Example usage: - /// - /// // Variable-length arrays are not allowed in NVPTX device code. - /// if (diagIfOpenMPDeviceCode(Loc, diag::err_vla_unsupported)) - /// return ExprError(); - /// // Otherwise, continue parsing as normal. - SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, - unsigned DiagID, - const FunctionDecl *FD); - - /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current - /// context is "used as host code". - /// - /// - If CurContext is a `declare target` function or it is known that the - /// function is emitted for the host, emits the diagnostics immediately. - /// - If CurContext is a non-host function, just ignore it. - /// - /// Example usage: - /// - /// // Variable-length arrays are not allowed in NVPTX device code. - /// if (diagIfOpenMPHostode(Loc, diag::err_vla_unsupported)) - /// return ExprError(); - /// // Otherwise, continue parsing as normal. - SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID, - const FunctionDecl *FD); - - SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, - const FunctionDecl *FD = nullptr); - SemaDiagnosticBuilder targetDiag(SourceLocation Loc, - const PartialDiagnostic &PD, - const FunctionDecl *FD = nullptr) { - return targetDiag(Loc, PD.getDiagID(), FD) << PD; - } - - /// Check if the type is allowed to be used for the current target. - void checkTypeSupport(QualType Ty, SourceLocation Loc, - ValueDecl *D = nullptr); - /// Determines whether the given function is a CUDA device/host/kernel/etc. /// function. /// @@ -13696,7 +13196,6 @@ class Sema final { /// and current compilation settings. void MaybeAddCUDAConstantAttr(VarDecl *VD); -public: /// Check whether we're allowed to call Callee from the current context. /// /// - If the call is never allowed in a semantically-correct program @@ -13747,743 +13246,1491 @@ class Sema final { bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CXXSpecialMember CSM, CXXMethodDecl *MemberDecl, - bool ConstRHS, - bool Diagnose); + bool ConstRHS, bool Diagnose); + + /// \return true if \p CD can be considered empty according to CUDA + /// (E.2.3.1 in CUDA 7.5 Programming guide). + bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD); + bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD); + + // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In + // case of error emits appropriate diagnostic and invalidates \p Var. + // + // \details CUDA allows only empty constructors as initializers for global + // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all + // __shared__ variables whether they are local or not (they all are implicitly + // static in CUDA). One exception is that CUDA allows constant initializers + // for __constant__ and __device__ variables. + void checkAllowedCUDAInitializer(VarDecl *VD); + + /// Check whether NewFD is a valid overload for CUDA. Emits + /// diagnostics and invalidates NewFD if not. + void checkCUDATargetOverload(FunctionDecl *NewFD, + const LookupResult &Previous); + /// Copies target attributes from the template TD to the function FD. + void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); + + /// Returns the name of the launch configuration function. This is the name + /// of the function that will be called to configure kernel call, with the + /// parameters specified via <<<>>>. + std::string getCudaConfigureFuncName() const; + +private: + unsigned ForceCUDAHostDeviceDepth = 0; + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name HLSL Constructs + /// Implementations are in SemaHLSL.cpp + ///@{ + +public: + Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer, + SourceLocation KwLoc, IdentifierInfo *Ident, + SourceLocation IdentLoc, SourceLocation LBrace); + void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace); + + bool CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + + bool SemaBuiltinVectorMath(CallExpr *TheCall, QualType &Res); + bool SemaBuiltinVectorToScalarMath(CallExpr *TheCall); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name OpenACC Constructs + /// Implementations are in SemaOpenACC.cpp + ///@{ + +public: + /// Called after parsing an OpenACC Clause so that it can be checked. + bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind, + SourceLocation StartLoc); + + /// Called after the construct has been parsed, but clauses haven't been + /// parsed. This allows us to diagnose not-implemented, as well as set up any + /// state required for parsing the clauses. + void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); + + /// Called after the directive, including its clauses, have been parsed and + /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'statement' context. + bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc); + + /// Called after the directive, including its clauses, have been parsed and + /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'Decl' context. + bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc); + /// Called when we encounter an associated statement for our construct, this + /// should check legality of the statement as it appertains to this Construct. + StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, + StmtResult AssocStmt); + + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc, + SourceLocation EndLoc, + StmtResult AssocStmt); + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + DeclGroupRef ActOnEndOpenACCDeclDirective(); + + ///@} + + // + // + // ------------------------------------------------------------------------- + // + // + + /// \name OpenMP Directives and Clauses + /// Implementations are in SemaOpenMP.cpp + ///@{ + +public: + /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current + /// context is "used as device code". + /// + /// - If CurContext is a `declare target` function or it is known that the + /// function is emitted for the device, emits the diagnostics immediately. + /// - If CurContext is a non-`declare target` function and we are compiling + /// for the device, creates a diagnostic which is emitted if and when we + /// realize that the function will be codegen'ed. + /// + /// Example usage: + /// + /// // Variable-length arrays are not allowed in NVPTX device code. + /// if (diagIfOpenMPDeviceCode(Loc, diag::err_vla_unsupported)) + /// return ExprError(); + /// // Otherwise, continue parsing as normal. + SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, + unsigned DiagID, + const FunctionDecl *FD); + + /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current + /// context is "used as host code". + /// + /// - If CurContext is a `declare target` function or it is known that the + /// function is emitted for the host, emits the diagnostics immediately. + /// - If CurContext is a non-host function, just ignore it. + /// + /// Example usage: + /// + /// // Variable-length arrays are not allowed in NVPTX device code. + /// if (diagIfOpenMPHostode(Loc, diag::err_vla_unsupported)) + /// return ExprError(); + /// // Otherwise, continue parsing as normal. + SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, + unsigned DiagID, + const FunctionDecl *FD); + + /// Register \p D as specialization of all base functions in \p Bases in the + /// current `omp begin/end declare variant` scope. + void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope( + Decl *D, SmallVectorImpl &Bases); + + /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`. + void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D); + + /// Can we exit an OpenMP declare variant scope at the moment. + bool isInOpenMPDeclareVariantScope() const { + return !OMPDeclareVariantScopes.empty(); + } + + ExprResult + VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, + bool StrictlyPositive = true, + bool SuppressExprDiags = false); + + /// Given the potential call expression \p Call, determine if there is a + /// specialization via the OpenMP declare variant mechanism available. If + /// there is, return the specialized call expression, otherwise return the + /// original \p Call. + ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, + SourceLocation LParenLoc, MultiExprArg ArgExprs, + SourceLocation RParenLoc, Expr *ExecConfig); + + /// Handle a `omp begin declare variant`. + void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI); + + /// Handle a `omp end declare variant`. + void ActOnOpenMPEndDeclareVariant(); + + /// Function tries to capture lambda's captured variables in the OpenMP region + /// before the original lambda is captured. + void tryCaptureOpenMPLambdas(ValueDecl *V); + + /// Return true if the provided declaration \a VD should be captured by + /// reference. + /// \param Level Relative level of nested OpenMP construct for that the check + /// is performed. + /// \param OpenMPCaptureLevel Capture level within an OpenMP construct. + bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, + unsigned OpenMPCaptureLevel) const; - /// \return true if \p CD can be considered empty according to CUDA - /// (E.2.3.1 in CUDA 7.5 Programming guide). - bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD); - bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD); + /// Check if the specified variable is used in one of the private + /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP + /// constructs. + VarDecl *isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo = false, + unsigned StopAt = 0); - // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In - // case of error emits appropriate diagnostic and invalidates \p Var. - // - // \details CUDA allows only empty constructors as initializers for global - // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all - // __shared__ variables whether they are local or not (they all are implicitly - // static in CUDA). One exception is that CUDA allows constant initializers - // for __constant__ and __device__ variables. - void checkAllowedCUDAInitializer(VarDecl *VD); + /// The member expression(this->fd) needs to be rebuilt in the template + /// instantiation to generate private copy for OpenMP when default + /// clause is used. The function will return true if default + /// cluse is used. + bool isOpenMPRebuildMemberExpr(ValueDecl *D); - /// Check whether NewFD is a valid overload for CUDA. Emits - /// diagnostics and invalidates NewFD if not. - void checkCUDATargetOverload(FunctionDecl *NewFD, - const LookupResult &Previous); - /// Copies target attributes from the template TD to the function FD. - void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD); + ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, + ExprObjectKind OK, SourceLocation Loc); - /// Returns the name of the launch configuration function. This is the name - /// of the function that will be called to configure kernel call, with the - /// parameters specified via <<<>>>. - std::string getCudaConfigureFuncName() const; + /// If the current region is a loop-based region, mark the start of the loop + /// construct. + void startOpenMPLoop(); - /// \name Code completion - //@{ - /// Describes the context in which code completion occurs. - enum ParserCompletionContext { - /// Code completion occurs at top-level or namespace context. - PCC_Namespace, - /// Code completion occurs within a class, struct, or union. - PCC_Class, - /// Code completion occurs within an Objective-C interface, protocol, - /// or category. - PCC_ObjCInterface, - /// Code completion occurs within an Objective-C implementation or - /// category implementation - PCC_ObjCImplementation, - /// Code completion occurs within the list of instance variables - /// in an Objective-C interface, protocol, category, or implementation. - PCC_ObjCInstanceVariableList, - /// Code completion occurs following one or more template - /// headers. - PCC_Template, - /// Code completion occurs following one or more template - /// headers within a class. - PCC_MemberTemplate, - /// Code completion occurs within an expression. - PCC_Expression, - /// Code completion occurs within a statement, which may - /// also be an expression or a declaration. - PCC_Statement, - /// Code completion occurs at the beginning of the - /// initialization statement (or expression) in a for loop. - PCC_ForInit, - /// Code completion occurs within the condition of an if, - /// while, switch, or for statement. - PCC_Condition, - /// Code completion occurs within the body of a function on a - /// recovery path, where we do not have a specific handle on our position - /// in the grammar. - PCC_RecoveryInFunction, - /// Code completion occurs where only a type is permitted. - PCC_Type, - /// Code completion occurs in a parenthesized expression, which - /// might also be a type cast. - PCC_ParenthesizedExpression, - /// Code completion occurs within a sequence of declaration - /// specifiers within a function, method, or block. - PCC_LocalDeclarationSpecifiers, - /// Code completion occurs at top-level in a REPL session - PCC_TopLevelOrExpression, - }; + /// If the current region is a range loop-based region, mark the start of the + /// loop construct. + void startOpenMPCXXRangeFor(); - void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path); - void CodeCompleteOrdinaryName(Scope *S, - ParserCompletionContext CompletionContext); - void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, - bool AllowNonIdentifiers, - bool AllowNestedNameSpecifiers); + /// Check if the specified variable is used in 'private' clause. + /// \param Level Relative level of nested OpenMP construct for that the check + /// is performed. + OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, + unsigned CapLevel) const; - struct CodeCompleteExpressionData; - void CodeCompleteExpression(Scope *S, - const CodeCompleteExpressionData &Data); - void CodeCompleteExpression(Scope *S, QualType PreferredType, - bool IsParenthesized = false); - void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, - SourceLocation OpLoc, bool IsArrow, - bool IsBaseExprStatement, - QualType PreferredType); - void CodeCompletePostfixExpression(Scope *S, ExprResult LHS, - QualType PreferredType); - void CodeCompleteTag(Scope *S, unsigned TagSpec); - void CodeCompleteTypeQualifiers(DeclSpec &DS); - void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, - const VirtSpecifiers *VS = nullptr); - void CodeCompleteBracketDeclarator(Scope *S); - void CodeCompleteCase(Scope *S); - enum class AttributeCompletion { - Attribute, - Scope, - None, - }; - void CodeCompleteAttribute( - AttributeCommonInfo::Syntax Syntax, - AttributeCompletion Completion = AttributeCompletion::Attribute, - const IdentifierInfo *Scope = nullptr); - /// Determines the preferred type of the current function argument, by - /// examining the signatures of all possible overloads. - /// Returns null if unknown or ambiguous, or if code completion is off. - /// - /// If the code completion point has been reached, also reports the function - /// signatures that were considered. - /// - /// FIXME: rename to GuessCallArgumentType to reduce confusion. - QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args, - SourceLocation OpenParLoc); - QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, - ArrayRef Args, - SourceLocation OpenParLoc, - bool Braced); - QualType ProduceCtorInitMemberSignatureHelp( - Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, - ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc, - bool Braced); - QualType ProduceTemplateArgumentSignatureHelp( - TemplateTy, ArrayRef, SourceLocation LAngleLoc); - void CodeCompleteInitializer(Scope *S, Decl *D); - /// Trigger code completion for a record of \p BaseType. \p InitExprs are - /// expressions in the initializer list seen so far and \p D is the current - /// Designation being parsed. - void CodeCompleteDesignator(const QualType BaseType, - llvm::ArrayRef InitExprs, - const Designation &D); - void CodeCompleteAfterIf(Scope *S, bool IsBracedThen); + /// Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) + /// for \p FD based on DSA for the provided corresponding captured declaration + /// \p D. + void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level); - void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext, - bool IsUsingDeclaration, QualType BaseType, - QualType PreferredType); - void CodeCompleteUsing(Scope *S); - void CodeCompleteUsingDirective(Scope *S); - void CodeCompleteNamespaceDecl(Scope *S); - void CodeCompleteNamespaceAliasDecl(Scope *S); - void CodeCompleteOperatorName(Scope *S); - void CodeCompleteConstructorInitializer( - Decl *Constructor, - ArrayRef Initializers); + /// Check if the specified variable is captured by 'target' directive. + /// \param Level Relative level of nested OpenMP construct for that the check + /// is performed. + bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, + unsigned CaptureLevel) const; - void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, - bool AfterAmpersand); - void CodeCompleteAfterFunctionEquals(Declarator &D); + /// Check if the specified global variable must be captured by outer capture + /// regions. + /// \param Level Relative level of nested OpenMP construct for that + /// the check is performed. + bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, + unsigned CaptureLevel) const; - void CodeCompleteObjCAtDirective(Scope *S); - void CodeCompleteObjCAtVisibility(Scope *S); - void CodeCompleteObjCAtStatement(Scope *S); - void CodeCompleteObjCAtExpression(Scope *S); - void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS); - void CodeCompleteObjCPropertyGetter(Scope *S); - void CodeCompleteObjCPropertySetter(Scope *S); - void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, - bool IsParameter); - void CodeCompleteObjCMessageReceiver(Scope *S); - void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, - ArrayRef SelIdents, - bool AtArgumentExpression); - void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, - ArrayRef SelIdents, - bool AtArgumentExpression, - bool IsSuper = false); - void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, - ArrayRef SelIdents, - bool AtArgumentExpression, - ObjCInterfaceDecl *Super = nullptr); - void CodeCompleteObjCForCollection(Scope *S, - DeclGroupPtrTy IterationVar); - void CodeCompleteObjCSelector(Scope *S, - ArrayRef SelIdents); - void CodeCompleteObjCProtocolReferences( - ArrayRef Protocols); - void CodeCompleteObjCProtocolDecl(Scope *S); - void CodeCompleteObjCInterfaceDecl(Scope *S); - void CodeCompleteObjCClassForwardDecl(Scope *S); - void CodeCompleteObjCSuperclass(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCImplementationDecl(Scope *S); - void CodeCompleteObjCInterfaceCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCImplementationCategory(Scope *S, - IdentifierInfo *ClassName, - SourceLocation ClassNameLoc); - void CodeCompleteObjCPropertyDefinition(Scope *S); - void CodeCompleteObjCPropertySynthesizeIvar(Scope *S, - IdentifierInfo *PropertyName); - void CodeCompleteObjCMethodDecl(Scope *S, - std::optional IsInstanceMethod, - ParsedType ReturnType); - void CodeCompleteObjCMethodDeclSelector(Scope *S, - bool IsInstanceMethod, - bool AtParameterName, - ParsedType ReturnType, - ArrayRef SelIdents); - void CodeCompleteObjCClassPropertyRefExpr(Scope *S, IdentifierInfo &ClassName, - SourceLocation ClassNameLoc, - bool IsBaseExprStatement); - void CodeCompletePreprocessorDirective(bool InConditional); - void CodeCompleteInPreprocessorConditionalExclusion(Scope *S); - void CodeCompletePreprocessorMacroName(bool IsDefinition); - void CodeCompletePreprocessorExpression(); - void CodeCompletePreprocessorMacroArgument(Scope *S, - IdentifierInfo *Macro, - MacroInfo *MacroInfo, - unsigned Argument); - void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled); - void CodeCompleteNaturalLanguage(); - void CodeCompleteAvailabilityPlatformName(); - void GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo, - SmallVectorImpl &Results); - //@} + ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, + Expr *Op); + /// Called on start of new data sharing attribute block. + void StartOpenMPDSABlock(OpenMPDirectiveKind K, + const DeclarationNameInfo &DirName, Scope *CurScope, + SourceLocation Loc); + /// Start analysis of clauses. + void StartOpenMPClause(OpenMPClauseKind K); + /// End analysis of clauses. + void EndOpenMPClause(); + /// Called on end of data sharing attribute block. + void EndOpenMPDSABlock(Stmt *CurDirective); - //===--------------------------------------------------------------------===// - // Extra semantic analysis beyond the C type system + /// Check if the current region is an OpenMP loop region and if it is, + /// mark loop control variable, used in \p Init for loop initialization, as + /// private by default. + /// \param Init First part of the for loop. + void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init); -public: - SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL, - unsigned ByteNo) const; + /// Called on well-formed '\#pragma omp metadirective' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPMetaDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); - enum FormatArgumentPassingKind { - FAPK_Fixed, // values to format are fixed (no C-style variadic arguments) - FAPK_Variadic, // values to format are passed as variadic arguments - FAPK_VAList, // values to format are passed in a va_list - }; + // OpenMP directives and clauses. + /// Called on correct id-expression from the '#pragma omp + /// threadprivate'. + ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, + const DeclarationNameInfo &Id, + OpenMPDirectiveKind Kind); + /// Called on well-formed '#pragma omp threadprivate'. + DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, + ArrayRef VarList); + /// Builds a new OpenMPThreadPrivateDecl and checks its correctness. + OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc, + ArrayRef VarList); + /// Called on well-formed '#pragma omp allocate'. + DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, + ArrayRef VarList, + ArrayRef Clauses, + DeclContext *Owner = nullptr); - // Used to grab the relevant information from a FormatAttr and a - // FunctionDeclaration. - struct FormatStringInfo { - unsigned FormatIdx; - unsigned FirstDataArg; - FormatArgumentPassingKind ArgPassingKind; - }; + /// Called on well-formed '#pragma omp [begin] assume[s]'. + void ActOnOpenMPAssumesDirective(SourceLocation Loc, + OpenMPDirectiveKind DKind, + ArrayRef Assumptions, + bool SkippedClauses); - static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, - bool IsVariadic, FormatStringInfo *FSI); + /// Check if there is an active global `omp begin assumes` directive. + bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); } -private: - void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, - const ArraySubscriptExpr *ASE = nullptr, - bool AllowOnePastEnd = true, bool IndexNegated = false); - void CheckArrayAccess(const Expr *E); + /// Check if there is an active global `omp assumes` directive. + bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); } - bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, - const FunctionProtoType *Proto); - bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, - ArrayRef Args); - bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, - const FunctionProtoType *Proto); - bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto); - void CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, - ArrayRef Args, - const FunctionProtoType *Proto, SourceLocation Loc); + /// Called on well-formed '#pragma omp end assumes'. + void ActOnOpenMPEndAssumesDirective(); - void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg); + /// Called on well-formed '#pragma omp requires'. + DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, + ArrayRef ClauseList); + /// Check restrictions on Requires directive + OMPRequiresDecl *CheckOMPRequiresDecl(SourceLocation Loc, + ArrayRef Clauses); + /// Check if the specified type is allowed to be used in 'omp declare + /// reduction' construct. + QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, + TypeResult ParsedType); + /// Called on start of '#pragma omp declare reduction'. + DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart( + Scope *S, DeclContext *DC, DeclarationName Name, + ArrayRef> ReductionTypes, + AccessSpecifier AS, Decl *PrevDeclInScope = nullptr); + /// Initialize declare reduction construct initializer. + void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D); + /// Finish current declare reduction construct initializer. + void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner); + /// Initialize declare reduction construct initializer. + /// \return omp_priv variable. + VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); + /// Finish current declare reduction construct initializer. + void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, + VarDecl *OmpPrivParm); + /// Called at the end of '#pragma omp declare reduction'. + DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd( + Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid); - void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl, - StringRef ParamName, QualType ArgTy, QualType ParamTy); + /// Check variable declaration in 'omp declare mapper' construct. + TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D); + /// Check if the specified type is allowed to be used in 'omp declare + /// mapper' construct. + QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, + TypeResult ParsedType); + /// Called on start of '#pragma omp declare mapper'. + DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective( + Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, + SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, + Expr *MapperVarRef, ArrayRef Clauses, + Decl *PrevDeclInScope = nullptr); + /// Build the mapper variable of '#pragma omp declare mapper'. + ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, + QualType MapperType, + SourceLocation StartLoc, + DeclarationName VN); + void ActOnOpenMPIteratorVarDecl(VarDecl *VD); + bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const; + const ValueDecl *getOpenMPDeclareMapperVarName() const; - void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, - const Expr *ThisArg, ArrayRef Args, - bool IsMemberFunction, SourceLocation Loc, SourceRange Range, - VariadicCallType CallType); + struct DeclareTargetContextInfo { + struct MapInfo { + OMPDeclareTargetDeclAttr::MapTypeTy MT; + SourceLocation Loc; + }; + /// Explicitly listed variables and functions in a 'to' or 'link' clause. + llvm::DenseMap ExplicitlyMapped; - bool CheckObjCString(Expr *Arg); - ExprResult CheckOSLogFormatStringArg(Expr *Arg); + /// The 'device_type' as parsed from the clause. + OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; - ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, - unsigned BuiltinID, CallExpr *TheCall); + /// The directive kind, `begin declare target` or `declare target`. + OpenMPDirectiveKind Kind; - bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); + /// The directive with indirect clause. + std::optional Indirect; - void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall); + /// The directive location. + SourceLocation Loc; - bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, - unsigned MaxWidth); - bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool ParseSVEImmChecks(CallExpr *TheCall, - SmallVector, 3> &ImmChecks); - bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg, - bool WantCDE); - bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); + DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc) + : Kind(Kind), Loc(Loc) {} + }; - bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall); - bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall); - bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall); - bool CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, CallExpr *TheCall); - bool CheckX86BuiltinTileArguments(unsigned BuiltinID, CallExpr *TheCall); - bool CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall, - ArrayRef ArgNums); - bool CheckX86BuiltinTileDuplicate(CallExpr *TheCall, ArrayRef ArgNums); - bool CheckX86BuiltinTileRangeAndDuplicate(CallExpr *TheCall, - ArrayRef ArgNums); - bool CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); - bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); - bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); - void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D); - bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, - unsigned BuiltinID, CallExpr *TheCall); - bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, - unsigned BuiltinID, - CallExpr *TheCall); - bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, - CallExpr *TheCall); + /// Called on the start of target region i.e. '#pragma omp declare target'. + bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI); - bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall); - bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call); - bool SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID); - bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, - unsigned BuiltinID); - bool SemaBuiltinComplex(CallExpr *TheCall); - bool SemaBuiltinVSX(CallExpr *TheCall); - bool SemaBuiltinOSLogFormat(CallExpr *TheCall); - bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum); + /// Called at the end of target region i.e. '#pragma omp end declare target'. + const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective(); -public: - bool IsLayoutCompatible(QualType T1, QualType T2) const; + /// Called once a target context is completed, that can be when a + /// '#pragma omp end declare target' was encountered or when a + /// '#pragma omp declare target' without declaration-definition-seq was + /// encountered. + void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI); - // Used by C++ template instantiation. - ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall); - ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, - SourceLocation BuiltinLoc, - SourceLocation RParenLoc); + /// Report unterminated 'omp declare target' or 'omp begin declare target' at + /// the end of a compilation unit. + void DiagnoseUnterminatedOpenMPDeclareTarget(); -private: - bool SemaBuiltinPrefetch(CallExpr *TheCall); - bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall); - bool SemaBuiltinArithmeticFence(CallExpr *TheCall); - bool SemaBuiltinAssume(CallExpr *TheCall); - bool SemaBuiltinAssumeAligned(CallExpr *TheCall); - bool SemaBuiltinLongjmp(CallExpr *TheCall); - bool SemaBuiltinSetjmp(CallExpr *TheCall); - ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult); - ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult); - ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult, - AtomicExpr::AtomicOp Op); - ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, - bool IsDelete); - bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, - llvm::APSInt &Result); - bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, - int High, bool RangeIsError = true); - bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, - unsigned Multiple); - bool SemaBuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum); - bool SemaBuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum, - unsigned ArgBits); - bool SemaBuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, - unsigned ArgBits); - bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, - int ArgNum, unsigned ExpectedFieldNum, - bool AllowName); - bool SemaBuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall); - bool SemaBuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID, - const char *TypeDesc); + /// Searches for the provided declaration name for OpenMP declare target + /// directive. + NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope, + CXXScopeSpec &ScopeSpec, + const DeclarationNameInfo &Id); - bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc); + /// Called on correct id-expression from the '#pragma omp declare target'. + void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, + OMPDeclareTargetDeclAttr::MapTypeTy MT, + DeclareTargetContextInfo &DTCI); - bool SemaBuiltinVectorMath(CallExpr *TheCall, QualType &Res); - bool SemaBuiltinVectorToScalarMath(CallExpr *TheCall); - bool SemaBuiltinElementwiseMath(CallExpr *TheCall); - bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall, - bool CheckForFloatArgs = true); - bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall); - bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall); + /// Check declaration inside target region. + void + checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, + SourceLocation IdLoc = SourceLocation()); - bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall); + /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target + /// directive. + void ActOnOpenMPDeclareTargetInitializer(Decl *D); - // Matrix builtin handling. - ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall, - ExprResult CallResult); - ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall, - ExprResult CallResult); - ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall, - ExprResult CallResult); + /// Finishes analysis of the deferred functions calls that may be declared as + /// host/nohost during device/host compilation. + void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, + const FunctionDecl *Callee, + SourceLocation Loc); - // WebAssembly builtin handling. - bool BuiltinWasmRefNullExtern(CallExpr *TheCall); - bool BuiltinWasmRefNullFunc(CallExpr *TheCall); - bool BuiltinWasmTableGet(CallExpr *TheCall); - bool BuiltinWasmTableSet(CallExpr *TheCall); - bool BuiltinWasmTableSize(CallExpr *TheCall); - bool BuiltinWasmTableGrow(CallExpr *TheCall); - bool BuiltinWasmTableFill(CallExpr *TheCall); - bool BuiltinWasmTableCopy(CallExpr *TheCall); + /// Return true if currently in OpenMP task with untied clause context. + bool isInOpenMPTaskUntiedContext() const; -public: - enum FormatStringType { - FST_Scanf, - FST_Printf, - FST_NSString, - FST_Strftime, - FST_Strfmon, - FST_Kprintf, - FST_FreeBSDKPrintf, - FST_OSTrace, - FST_OSLog, - FST_Unknown - }; - static FormatStringType GetFormatStringType(const FormatAttr *Format); + /// Return true inside OpenMP declare target region. + bool isInOpenMPDeclareTargetContext() const { + return !DeclareTargetNesting.empty(); + } + /// Return true inside OpenMP target region. + bool isInOpenMPTargetExecutionDirective() const; - bool FormatStringHasSArg(const StringLiteral *FExpr); + /// Return the number of captured regions created for an OpenMP directive. + static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind); - static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx); + /// Initialization of captured region for OpenMP region. + void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope); -private: - bool CheckFormatArguments(const FormatAttr *Format, - ArrayRef Args, bool IsCXXMember, - VariadicCallType CallType, SourceLocation Loc, - SourceRange Range, - llvm::SmallBitVector &CheckedVarArgs); - bool CheckFormatArguments(ArrayRef Args, - FormatArgumentPassingKind FAPK, unsigned format_idx, - unsigned firstDataArg, FormatStringType Type, - VariadicCallType CallType, SourceLocation Loc, - SourceRange range, - llvm::SmallBitVector &CheckedVarArgs); + /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to + /// an OpenMP loop directive. + StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt); - void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl); + /// Process a canonical OpenMP loop nest that can either be a canonical + /// literal loop (ForStmt or CXXForRangeStmt), or the generated loop of an + /// OpenMP loop transformation construct. + StmtResult ActOnOpenMPLoopnest(Stmt *AStmt); - void CheckAbsoluteValueFunction(const CallExpr *Call, - const FunctionDecl *FDecl); + /// End of OpenMP region. + /// + /// \param S Statement associated with the current OpenMP region. + /// \param Clauses List of clauses for the current OpenMP region. + /// + /// \returns Statement for finished OpenMP region. + StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef Clauses); + StmtResult ActOnOpenMPExecutableDirective( + OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, + OpenMPDirectiveKind CancelRegion, ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, + OpenMPDirectiveKind PrevMappedDirective = llvm::omp::OMPD_unknown); + /// Called on well-formed '\#pragma omp parallel' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPParallelDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + using VarsWithInheritedDSAType = + llvm::SmallDenseMap; + /// Called on well-formed '\#pragma omp simd' after parsing + /// of the associated statement. + StmtResult + ActOnOpenMPSimdDirective(ArrayRef Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '#pragma omp tile' after parsing of its clauses and + /// the associated statement. + StmtResult ActOnOpenMPTileDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '#pragma omp unroll' after parsing of its clauses + /// and the associated statement. + StmtResult ActOnOpenMPUnrollDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp for' after parsing + /// of the associated statement. + StmtResult + ActOnOpenMPForDirective(ArrayRef Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp for simd' after parsing + /// of the associated statement. + StmtResult + ActOnOpenMPForSimdDirective(ArrayRef Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp sections' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPSectionsDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp section' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp scope' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPScopeDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp single' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPSingleDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp master' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp critical' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, + ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp parallel for' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPParallelForDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel for simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelForSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel master' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp parallel masked' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp parallel sections' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp task' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTaskDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp taskyield'. + StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp error'. + /// Error direcitive is allowed in both declared and excutable contexts. + /// Adding InExContext to identify which context is called from. + StmtResult ActOnOpenMPErrorDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc, + bool InExContext = true); + /// Called on well-formed '\#pragma omp barrier'. + StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp taskwait'. + StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp taskgroup'. + StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp flush'. + StmtResult ActOnOpenMPFlushDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp depobj'. + StmtResult ActOnOpenMPDepobjDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp scan'. + StmtResult ActOnOpenMPScanDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp ordered' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPOrderedDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp atomic' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPAtomicDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp target' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTargetDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp target data' after parsing of + /// the associated statement. + StmtResult ActOnOpenMPTargetDataDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp target enter data' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AStmt); + /// Called on well-formed '\#pragma omp target exit data' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AStmt); + /// Called on well-formed '\#pragma omp target parallel' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp target parallel for' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetParallelForDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp teams' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTeamsDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp teams loop' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTeamsGenericLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target teams loop' after parsing of + /// the associated statement. + StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel loop' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPParallelGenericLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target parallel loop' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPTargetParallelGenericLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp cancellation point'. + StmtResult + ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + OpenMPDirectiveKind CancelRegion); + /// Called on well-formed '\#pragma omp cancel'. + StmtResult ActOnOpenMPCancelDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc, + OpenMPDirectiveKind CancelRegion); + /// Called on well-formed '\#pragma omp taskloop' after parsing of the + /// associated statement. + StmtResult + ActOnOpenMPTaskLoopDirective(ArrayRef Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp taskloop simd' after parsing of + /// the associated statement. + StmtResult ActOnOpenMPTaskLoopSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp master taskloop' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPMasterTaskLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp master taskloop simd' after parsing of + /// the associated statement. + StmtResult ActOnOpenMPMasterTaskLoopSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel master taskloop' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelMasterTaskLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel master taskloop simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp masked taskloop' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPMaskedTaskLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp masked taskloop simd' after parsing of + /// the associated statement. + StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel masked taskloop' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel masked taskloop simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp distribute' after parsing + /// of the associated statement. + StmtResult + ActOnOpenMPDistributeDirective(ArrayRef Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target update'. + StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AStmt); + /// Called on well-formed '\#pragma omp distribute parallel for' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPDistributeParallelForDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp distribute parallel for simd' + /// after parsing of the associated statement. + StmtResult ActOnOpenMPDistributeParallelForSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp distribute simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPDistributeSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target parallel for simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetParallelForSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target simd' after parsing of + /// the associated statement. + StmtResult + ActOnOpenMPTargetSimdDirective(ArrayRef Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp teams distribute' after parsing of + /// the associated statement. + StmtResult ActOnOpenMPTeamsDistributeDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp teams distribute simd' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPTeamsDistributeSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp teams distribute parallel for simd' + /// after parsing of the associated statement. + StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp teams distribute parallel for' + /// after parsing of the associated statement. + StmtResult ActOnOpenMPTeamsDistributeParallelForDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target teams' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef Clauses, + Stmt *AStmt, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp target teams distribute' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPTargetTeamsDistributeDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target teams distribute parallel for' + /// after parsing of the associated statement. + StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target teams distribute parallel for + /// simd' after parsing of the associated statement. + StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target teams distribute simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp interop'. + StmtResult ActOnOpenMPInteropDirective(ArrayRef Clauses, + SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp dispatch' after parsing of the + // /associated statement. + StmtResult ActOnOpenMPDispatchDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed '\#pragma omp masked' after parsing of the + // /associated statement. + StmtResult ActOnOpenMPMaskedDirective(ArrayRef Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); - void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl); + /// Called on well-formed '\#pragma omp loop' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPGenericLoopDirective( + ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); - void CheckMemaccessArguments(const CallExpr *Call, - unsigned BId, - IdentifierInfo *FnName); + /// Checks correctness of linear modifiers. + bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, + SourceLocation LinLoc); + /// Checks that the specified declaration matches requirements for the linear + /// decls. + bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, + OpenMPLinearClauseKind LinKind, QualType Type, + bool IsDeclareSimd = false); - void CheckStrlcpycatArguments(const CallExpr *Call, - IdentifierInfo *FnName); + /// Called on well-formed '\#pragma omp declare simd' after parsing of + /// the associated method/function. + DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective( + DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, + Expr *Simdlen, ArrayRef Uniforms, ArrayRef Aligneds, + ArrayRef Alignments, ArrayRef Linears, + ArrayRef LinModifiers, ArrayRef Steps, SourceRange SR); - void CheckStrncatArguments(const CallExpr *Call, - IdentifierInfo *FnName); + /// Checks '\#pragma omp declare variant' variant function and original + /// functions after parsing of the associated method/function. + /// \param DG Function declaration to which declare variant directive is + /// applied to. + /// \param VariantRef Expression that references the variant function, which + /// must be used instead of the original one, specified in \p DG. + /// \param TI The trait info object representing the match clause. + /// \param NumAppendArgs The number of omp_interop_t arguments to account for + /// in checking. + /// \returns std::nullopt, if the function/variant function are not compatible + /// with the pragma, pair of original function/variant ref expression + /// otherwise. + std::optional> + checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, + OMPTraitInfo &TI, unsigned NumAppendArgs, + SourceRange SR); - void CheckFreeArguments(const CallExpr *E); + /// Called on well-formed '\#pragma omp declare variant' after parsing of + /// the associated method/function. + /// \param FD Function declaration to which declare variant directive is + /// applied to. + /// \param VariantRef Expression that references the variant function, which + /// must be used instead of the original one, specified in \p DG. + /// \param TI The context traits associated with the function variant. + /// \param AdjustArgsNothing The list of 'nothing' arguments. + /// \param AdjustArgsNeedDevicePtr The list of 'need_device_ptr' arguments. + /// \param AppendArgs The list of 'append_args' arguments. + /// \param AdjustArgsLoc The Location of an 'adjust_args' clause. + /// \param AppendArgsLoc The Location of an 'append_args' clause. + /// \param SR The SourceRange of the 'declare variant' directive. + void ActOnOpenMPDeclareVariantDirective( + FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, + ArrayRef AdjustArgsNothing, + ArrayRef AdjustArgsNeedDevicePtr, + ArrayRef AppendArgs, SourceLocation AdjustArgsLoc, + SourceLocation AppendArgsLoc, SourceRange SR); - void CheckReturnValExpr(Expr *RetValExp, QualType lhsType, - SourceLocation ReturnLoc, - bool isObjCMethod = false, - const AttrVec *Attrs = nullptr, - const FunctionDecl *FD = nullptr); + OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'allocator' clause. + OMPClause *ActOnOpenMPAllocatorClause(Expr *Allocator, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'if' clause. + OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, + Expr *Condition, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation NameModifierLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc); + /// Called on well-formed 'final' clause. + OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'num_threads' clause. + OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'align' clause. + OMPClause *ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'safelen' clause. + OMPClause *ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'simdlen' clause. + OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-form 'sizes' clause. + OMPClause *ActOnOpenMPSizesClause(ArrayRef SizeExprs, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-form 'full' clauses. + OMPClause *ActOnOpenMPFullClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-form 'partial' clauses. + OMPClause *ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'collapse' clause. + OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'ordered' clause. + OMPClause * + ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, + SourceLocation LParenLoc = SourceLocation(), + Expr *NumForLoops = nullptr); + /// Called on well-formed 'grainsize' clause. + OMPClause *ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, + Expr *Size, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ModifierLoc, + SourceLocation EndLoc); + /// Called on well-formed 'num_tasks' clause. + OMPClause *ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, + Expr *NumTasks, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ModifierLoc, + SourceLocation EndLoc); + /// Called on well-formed 'hint' clause. + OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'detach' clause. + OMPClause *ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); -public: - void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS, - BinaryOperatorKind Opcode); + OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, + SourceLocation ArgumentLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'when' clause. + OMPClause *ActOnOpenMPWhenClause(OMPTraitInfo &TI, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'default' clause. + OMPClause *ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'proc_bind' clause. + OMPClause *ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'order' clause. + OMPClause *ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, + OpenMPOrderClauseKind Kind, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation MLoc, SourceLocation KindLoc, + SourceLocation EndLoc); + /// Called on well-formed 'update' clause. + OMPClause *ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); -private: - void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); - void CheckBoolLikeConversion(Expr *E, SourceLocation CC); - void CheckForIntOverflow(const Expr *E); - void CheckUnsequencedOperations(const Expr *E); + OMPClause *ActOnOpenMPSingleExprWithArgClause( + OpenMPClauseKind Kind, ArrayRef Arguments, Expr *Expr, + SourceLocation StartLoc, SourceLocation LParenLoc, + ArrayRef ArgumentsLoc, SourceLocation DelimLoc, + SourceLocation EndLoc); + /// Called on well-formed 'schedule' clause. + OMPClause *ActOnOpenMPScheduleClause( + OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, + OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, + SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc); - /// Perform semantic checks on a completed expression. This will either - /// be a full-expression or a default argument expression. - void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(), - bool IsConstexpr = false); + OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'nowait' clause. + OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'untied' clause. + OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'mergeable' clause. + OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'read' clause. + OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'write' clause. + OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'update' clause. + OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'capture' clause. + OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'compare' clause. + OMPClause *ActOnOpenMPCompareClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'fail' clause. + OMPClause *ActOnOpenMPFailClause(SourceLocation StartLoc, + SourceLocation EndLoc); + OMPClause *ActOnOpenMPFailClause(OpenMPClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field, - Expr *Init); + /// Called on well-formed 'seq_cst' clause. + OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'acq_rel' clause. + OMPClause *ActOnOpenMPAcqRelClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'acquire' clause. + OMPClause *ActOnOpenMPAcquireClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'release' clause. + OMPClause *ActOnOpenMPReleaseClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'relaxed' clause. + OMPClause *ActOnOpenMPRelaxedClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'weak' clause. + OMPClause *ActOnOpenMPWeakClause(SourceLocation StartLoc, + SourceLocation EndLoc); - /// Check if there is a field shadowing. - void CheckShadowInheritedFields(const SourceLocation &Loc, - DeclarationName FieldName, - const CXXRecordDecl *RD, - bool DeclIsField = true); + /// Called on well-formed 'init' clause. + OMPClause * + ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation VarLoc, SourceLocation EndLoc); - /// Check if the given expression contains 'break' or 'continue' - /// statement that produces control flow different from GCC. - void CheckBreakContinueBinding(Expr *E); + /// Called on well-formed 'use' clause. + OMPClause *ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation VarLoc, SourceLocation EndLoc); - /// Check whether receiver is mutable ObjC container which - /// attempts to add itself into the container - void CheckObjCCircularContainer(ObjCMessageExpr *Message); + /// Called on well-formed 'destroy' clause. + OMPClause *ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation VarLoc, + SourceLocation EndLoc); + /// Called on well-formed 'novariants' clause. + OMPClause *ActOnOpenMPNovariantsClause(Expr *Condition, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'nocontext' clause. + OMPClause *ActOnOpenMPNocontextClause(Expr *Condition, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'filter' clause. + OMPClause *ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'threads' clause. + OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'simd' clause. + OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'nogroup' clause. + OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// Called on well-formed 'unified_address' clause. + OMPClause *ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, + SourceLocation EndLoc); - void CheckTCBEnforcement(const SourceLocation CallExprLoc, - const NamedDecl *Callee); + /// Called on well-formed 'unified_address' clause. + OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, + SourceLocation EndLoc); - void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE); - void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, - bool DeleteWasArrayForm); -public: - /// Register a magic integral constant to be used as a type tag. - void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, - uint64_t MagicValue, QualType Type, - bool LayoutCompatible, bool MustBeNull); + /// Called on well-formed 'reverse_offload' clause. + OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, + SourceLocation EndLoc); - struct TypeTagData { - TypeTagData() {} + /// Called on well-formed 'dynamic_allocators' clause. + OMPClause *ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, + SourceLocation EndLoc); - TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) : - Type(Type), LayoutCompatible(LayoutCompatible), - MustBeNull(MustBeNull) - {} + /// Called on well-formed 'atomic_default_mem_order' clause. + OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause( + OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - QualType Type; + /// Called on well-formed 'at' clause. + OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - /// If true, \c Type should be compared with other expression's types for - /// layout-compatibility. - LLVM_PREFERRED_TYPE(bool) - unsigned LayoutCompatible : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned MustBeNull : 1; - }; + /// Called on well-formed 'severity' clause. + OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - /// A pair of ArgumentKind identifier and magic value. This uniquely - /// identifies the magic value. - typedef std::pair TypeTagMagicValue; + /// Called on well-formed 'message' clause. + /// passing string for message. + OMPClause *ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); -private: - /// A map from magic value to type information. - std::unique_ptr> - TypeTagForDatatypeMagicValues; + /// Data used for processing a list of variables in OpenMP clauses. + struct OpenMPVarListDataTy final { + Expr *DepModOrTailExpr = nullptr; + Expr *IteratorExpr = nullptr; + SourceLocation ColonLoc; + SourceLocation RLoc; + CXXScopeSpec ReductionOrMapperIdScopeSpec; + DeclarationNameInfo ReductionOrMapperId; + int ExtraModifier = -1; ///< Additional modifier for linear, map, depend or + ///< lastprivate clause. + SmallVector + MapTypeModifiers; + SmallVector + MapTypeModifiersLoc; + SmallVector + MotionModifiers; + SmallVector MotionModifiersLoc; + bool IsMapTypeImplicit = false; + SourceLocation ExtraModifierLoc; + SourceLocation OmpAllMemoryLoc; + SourceLocation + StepModifierLoc; /// 'step' modifier location for linear clause + }; - /// Peform checks on a call of a function with argument_with_type_tag - /// or pointer_with_type_tag attributes. - void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, - const ArrayRef ExprArgs, - SourceLocation CallSiteLoc); + OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind, + ArrayRef Vars, + const OMPVarListLocTy &Locs, + OpenMPVarListDataTy &Data); + /// Called on well-formed 'inclusive' clause. + OMPClause *ActOnOpenMPInclusiveClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'exclusive' clause. + OMPClause *ActOnOpenMPExclusiveClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'allocate' clause. + OMPClause * + ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef VarList, + SourceLocation StartLoc, SourceLocation ColonLoc, + SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'private' clause. + OMPClause *ActOnOpenMPPrivateClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'firstprivate' clause. + OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'lastprivate' clause. + OMPClause *ActOnOpenMPLastprivateClause( + ArrayRef VarList, OpenMPLastprivateModifier LPKind, + SourceLocation LPKindLoc, SourceLocation ColonLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); + /// Called on well-formed 'shared' clause. + OMPClause *ActOnOpenMPSharedClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'reduction' clause. + OMPClause *ActOnOpenMPReductionClause( + ArrayRef VarList, OpenMPReductionClauseModifier Modifier, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation ModifierLoc, SourceLocation ColonLoc, + SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId, + ArrayRef UnresolvedReductions = std::nullopt); + /// Called on well-formed 'task_reduction' clause. + OMPClause *ActOnOpenMPTaskReductionClause( + ArrayRef VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId, + ArrayRef UnresolvedReductions = std::nullopt); + /// Called on well-formed 'in_reduction' clause. + OMPClause *ActOnOpenMPInReductionClause( + ArrayRef VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, + CXXScopeSpec &ReductionIdScopeSpec, + const DeclarationNameInfo &ReductionId, + ArrayRef UnresolvedReductions = std::nullopt); + /// Called on well-formed 'linear' clause. + OMPClause *ActOnOpenMPLinearClause( + ArrayRef VarList, Expr *Step, SourceLocation StartLoc, + SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, + SourceLocation LinLoc, SourceLocation ColonLoc, + SourceLocation StepModifierLoc, SourceLocation EndLoc); + /// Called on well-formed 'aligned' clause. + OMPClause *ActOnOpenMPAlignedClause(ArrayRef VarList, Expr *Alignment, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc); + /// Called on well-formed 'copyin' clause. + OMPClause *ActOnOpenMPCopyinClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'copyprivate' clause. + OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'flush' pseudo clause. + OMPClause *ActOnOpenMPFlushClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'depobj' pseudo clause. + OMPClause *ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'depend' clause. + OMPClause *ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, + Expr *DepModifier, + ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'device' clause. + OMPClause *ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, + Expr *Device, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ModifierLoc, + SourceLocation EndLoc); + /// Called on well-formed 'map' clause. + OMPClause *ActOnOpenMPMapClause( + Expr *IteratorModifier, ArrayRef MapTypeModifiers, + ArrayRef MapTypeModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, + OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, + SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef VarList, + const OMPVarListLocTy &Locs, bool NoDiagnose = false, + ArrayRef UnresolvedMappers = std::nullopt); + /// Called on well-formed 'num_teams' clause. + OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'thread_limit' clause. + OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'priority' clause. + OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); + /// Called on well-formed 'dist_schedule' clause. + OMPClause *ActOnOpenMPDistScheduleClause( + OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, + SourceLocation CommaLoc, SourceLocation EndLoc); + /// Called on well-formed 'defaultmap' clause. + OMPClause *ActOnOpenMPDefaultmapClause( + OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, + SourceLocation KindLoc, SourceLocation EndLoc); + /// Called on well-formed 'to' clause. + OMPClause * + ActOnOpenMPToClause(ArrayRef MotionModifiers, + ArrayRef MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, + DeclarationNameInfo &MapperId, SourceLocation ColonLoc, + ArrayRef VarList, const OMPVarListLocTy &Locs, + ArrayRef UnresolvedMappers = std::nullopt); + /// Called on well-formed 'from' clause. + OMPClause * + ActOnOpenMPFromClause(ArrayRef MotionModifiers, + ArrayRef MotionModifiersLoc, + CXXScopeSpec &MapperIdScopeSpec, + DeclarationNameInfo &MapperId, SourceLocation ColonLoc, + ArrayRef VarList, const OMPVarListLocTy &Locs, + ArrayRef UnresolvedMappers = std::nullopt); + /// Called on well-formed 'use_device_ptr' clause. + OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef VarList, + const OMPVarListLocTy &Locs); + /// Called on well-formed 'use_device_addr' clause. + OMPClause *ActOnOpenMPUseDeviceAddrClause(ArrayRef VarList, + const OMPVarListLocTy &Locs); + /// Called on well-formed 'is_device_ptr' clause. + OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef VarList, + const OMPVarListLocTy &Locs); + /// Called on well-formed 'has_device_addr' clause. + OMPClause *ActOnOpenMPHasDeviceAddrClause(ArrayRef VarList, + const OMPVarListLocTy &Locs); + /// Called on well-formed 'nontemporal' clause. + OMPClause *ActOnOpenMPNontemporalClause(ArrayRef VarList, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - /// Check if we are taking the address of a packed field - /// as this may be a problem if the pointer value is dereferenced. - void CheckAddressOfPackedMember(Expr *rhs); + /// Data for list of allocators. + struct UsesAllocatorsData { + /// Allocator. + Expr *Allocator = nullptr; + /// Allocator traits. + Expr *AllocatorTraits = nullptr; + /// Locations of '(' and ')' symbols. + SourceLocation LParenLoc, RParenLoc; + }; + /// Called on well-formed 'uses_allocators' clause. + OMPClause *ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef Data); + /// Called on well-formed 'affinity' clause. + OMPClause *ActOnOpenMPAffinityClause(SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation ColonLoc, + SourceLocation EndLoc, Expr *Modifier, + ArrayRef Locators); + /// Called on a well-formed 'bind' clause. + OMPClause *ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, + SourceLocation KindLoc, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - /// The parser's current scope. - /// - /// The parser maintains this state here. - Scope *CurScope; + /// Called on a well-formed 'ompx_dyn_cgroup_mem' clause. + OMPClause *ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - mutable IdentifierInfo *Ident_super; + /// Called on well-formed 'doacross' clause. + OMPClause * + ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, + SourceLocation DepLoc, SourceLocation ColonLoc, + ArrayRef VarList, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc); - /// Nullability type specifiers. - IdentifierInfo *Ident__Nonnull = nullptr; - IdentifierInfo *Ident__Nullable = nullptr; - IdentifierInfo *Ident__Nullable_result = nullptr; - IdentifierInfo *Ident__Null_unspecified = nullptr; + /// Called on a well-formed 'ompx_attribute' clause. + OMPClause *ActOnOpenMPXAttributeClause(ArrayRef Attrs, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc); - IdentifierInfo *Ident_NSError = nullptr; + /// Called on a well-formed 'ompx_bare' clause. + OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc, + SourceLocation EndLoc); - /// The handler for the FileChanged preprocessor events. - /// - /// Used for diagnostics that implement custom semantic analysis for #include - /// directives, like -Wpragma-pack. - sema::SemaPPCallbacks *SemaPPCallbackHandler; +private: + void *VarDataSharingAttributesStack; -protected: - friend class Parser; - friend class InitializationSequence; - friend class ASTReader; - friend class ASTDeclReader; - friend class ASTWriter; + /// Number of nested '#pragma omp declare target' directives. + SmallVector DeclareTargetNesting; -public: - /// Retrieve the keyword associated - IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability); + /// Initialization of data-sharing attributes stack. + void InitDataSharingAttributesStack(); + void DestroyDataSharingAttributesStack(); - /// The struct behind the CFErrorRef pointer. - RecordDecl *CFError = nullptr; - bool isCFError(RecordDecl *D); + /// Returns OpenMP nesting level for current directive. + unsigned getOpenMPNestingLevel() const; - /// Retrieve the identifier "NSError". - IdentifierInfo *getNSErrorIdent(); + /// Adjusts the function scopes index for the target-based regions. + void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex, + unsigned Level) const; - /// Retrieve the parser's current scope. - /// - /// This routine must only be used when it is certain that semantic analysis - /// and the parser are in precisely the same context, which is not the case - /// when, e.g., we are performing any kind of template instantiation. - /// Therefore, the only safe places to use this scope are in the parser - /// itself and in routines directly invoked from the parser and *never* from - /// template substitution or instantiation. - Scope *getCurScope() const { return CurScope; } + /// Returns the number of scopes associated with the construct on the given + /// OpenMP level. + int getNumberOfConstructScopes(unsigned Level) const; - void incrementMSManglingNumber() const { - return CurScope->incrementMSManglingNumber(); - } + /// Push new OpenMP function region for non-capturing function. + void pushOpenMPFunctionRegion(); - IdentifierInfo *getSuperIdentifier() const; + /// Pop OpenMP function region for non-capturing function. + void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI); - ObjCContainerDecl *getObjCDeclContext() const; + /// Analyzes and checks a loop nest for use by a loop transformation. + /// + /// \param Kind The loop transformation directive kind. + /// \param NumLoops How many nested loops the directive is expecting. + /// \param AStmt Associated statement of the transformation directive. + /// \param LoopHelpers [out] The loop analysis result. + /// \param Body [out] The body code nested in \p NumLoops loop. + /// \param OriginalInits [out] Collection of statements and declarations that + /// must have been executed/declared before entering the + /// loop. + /// + /// \return Whether there was any error. + bool checkTransformableLoopNest( + OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, + SmallVectorImpl &LoopHelpers, + Stmt *&Body, + SmallVectorImpl, 0>> + &OriginalInits); - DeclContext *getCurLexicalContext() const { - return OriginalLexicalContext ? OriginalLexicalContext : CurContext; - } + /// Helper to keep information about the current `omp begin/end declare + /// variant` nesting. + struct OMPDeclareVariantScope { + /// The associated OpenMP context selector. + OMPTraitInfo *TI; - const DeclContext *getCurObjCLexicalContext() const { - const DeclContext *DC = getCurLexicalContext(); - // A category implicitly has the attribute of the interface. - if (const ObjCCategoryDecl *CatD = dyn_cast(DC)) - DC = CatD->getClassInterface(); - return DC; - } + /// The associated OpenMP context selector mangling. + std::string NameSuffix; - /// Determine the number of levels of enclosing template parameters. This is - /// only usable while parsing. Note that this does not include dependent - /// contexts in which no template parameters have yet been declared, such as - /// in a terse function template or generic lambda before the first 'auto' is - /// encountered. - unsigned getTemplateDepth(Scope *S) const; + OMPDeclareVariantScope(OMPTraitInfo &TI); + }; - /// To be used for checking whether the arguments being passed to - /// function exceeds the number of parameters expected for it. - static bool TooManyArguments(size_t NumParams, size_t NumArgs, - bool PartialOverloading = false) { - // We check whether we're just after a comma in code-completion. - if (NumArgs > 0 && PartialOverloading) - return NumArgs + 1 > NumParams; // If so, we view as an extra argument. - return NumArgs > NumParams; + /// Return the OMPTraitInfo for the surrounding scope, if any. + OMPTraitInfo *getOMPTraitInfoForSurroundingScope() { + return OMPDeclareVariantScopes.empty() ? nullptr + : OMPDeclareVariantScopes.back().TI; } - // Emitting members of dllexported classes is delayed until the class - // (including field initializers) is fully parsed. - SmallVector DelayedDllExportClasses; - SmallVector DelayedDllExportMemberFunctions; - -private: - int ParsingClassDepth = 0; - - class SavePendingParsedClassStateRAII { - public: - SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); } - - ~SavePendingParsedClassStateRAII() { - assert(S.DelayedOverridingExceptionSpecChecks.empty() && - "there shouldn't be any pending delayed exception spec checks"); - assert(S.DelayedEquivalentExceptionSpecChecks.empty() && - "there shouldn't be any pending delayed exception spec checks"); - swapSavedState(); - } + /// The current `omp begin/end declare variant` scopes. + SmallVector OMPDeclareVariantScopes; - private: - Sema &S; - decltype(DelayedOverridingExceptionSpecChecks) - SavedOverridingExceptionSpecChecks; - decltype(DelayedEquivalentExceptionSpecChecks) - SavedEquivalentExceptionSpecChecks; + /// The current `omp begin/end assumes` scopes. + SmallVector OMPAssumeScoped; - void swapSavedState() { - SavedOverridingExceptionSpecChecks.swap( - S.DelayedOverridingExceptionSpecChecks); - SavedEquivalentExceptionSpecChecks.swap( - S.DelayedEquivalentExceptionSpecChecks); - } - }; + /// All `omp assumes` we encountered so far. + SmallVector OMPAssumeGlobal; - /// Helper class that collects misaligned member designations and - /// their location info for delayed diagnostics. - struct MisalignedMember { - Expr *E; - RecordDecl *RD; - ValueDecl *MD; - CharUnits Alignment; + /// OMPD_loop is mapped to OMPD_for, OMPD_distribute or OMPD_simd depending + /// on the parameter of the bind clause. In the methods for the + /// mapped directives, check the parameters of the lastprivate clause. + bool checkLastPrivateForMappedDirectives(ArrayRef Clauses); + /// Depending on the bind clause of OMPD_loop map the directive to new + /// directives. + /// 1) loop bind(parallel) --> OMPD_for + /// 2) loop bind(teams) --> OMPD_distribute + /// 3) loop bind(thread) --> OMPD_simd + /// This is being handled in Sema instead of Codegen because of the need for + /// rigorous semantic checking in the new mapped directives. + bool mapLoopConstruct(llvm::SmallVector &ClausesWithoutBind, + ArrayRef Clauses, + OpenMPBindClauseKind &BindKind, + OpenMPDirectiveKind &Kind, + OpenMPDirectiveKind &PrevMappedDirective, + SourceLocation StartLoc, SourceLocation EndLoc, + const DeclarationNameInfo &DirName, + OpenMPDirectiveKind CancelRegion); - MisalignedMember() : E(), RD(), MD() {} - MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD, - CharUnits Alignment) - : E(E), RD(RD), MD(MD), Alignment(Alignment) {} - explicit MisalignedMember(Expr *E) - : MisalignedMember(E, nullptr, nullptr, CharUnits()) {} + ///@} - bool operator==(const MisalignedMember &m) { return this->E == m.E; } - }; - /// Small set of gathered accesses to potentially misaligned members - /// due to the packed attribute. - SmallVector MisalignedMembers; + // + // + // ------------------------------------------------------------------------- + // + // - /// Adds an expression to the set of gathered misaligned members. - void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD, - CharUnits Alignment); + /// \name SYCL Constructs + /// Implementations are in SemaSYCL.cpp + ///@{ public: - /// Diagnoses the current set of gathered accesses. This typically - /// happens at full expression level. The set is cleared after emitting the - /// diagnostics. - void DiagnoseMisalignedMembers(); - - /// This function checks if the expression is in the sef of potentially - /// misaligned members and it is converted to some pointer type T with lower - /// or equal alignment requirements. If so it removes it. This is used when - /// we do not want to diagnose such misaligned access (e.g. in conversions to - /// void*). - void DiscardMisalignedMemberAddress(const Type *T, Expr *E); - - /// This function calls Action when it determines that E designates a - /// misaligned member due to the packed attribute. This is used to emit - /// local diagnostics like in reference binding. - void RefersToMemberWithReducedAlignment( - Expr *E, - llvm::function_ref - Action); - - /// Describes the reason a calling convention specification was ignored, used - /// for diagnostics. - enum class CallingConventionIgnoredReason { - ForThisTarget = 0, - VariadicFunction, - ConstructorDestructor, - BuiltinFunction - }; /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current /// context is "used as device code". /// @@ -14508,6 +14755,8 @@ class Sema final { void deepTypeCheckForSYCLDevice(SourceLocation UsedAt, llvm::DenseSet Visited, ValueDecl *DeclToCheck); + + ///@} }; DeductionFailureInfo diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index cfb653e665ea0..720d5fd5f0428 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -188,38 +188,38 @@ const uint64_t Sema::MaximumAlignment; Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) - : ExternalSource(nullptr), CurFPFeatures(pp.getLangOpts()), + : 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), CollectStats(false), - CodeCompleter(CodeCompleter), CurContext(nullptr), - OriginalLexicalContext(nullptr), MSStructPragmaOn(false), + APINotes(SourceMgr, LangOpts), AnalysisWarnings(*this), + ThreadSafetyDeclCache(nullptr), LateTemplateParser(nullptr), + LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), + CurContext(nullptr), ExternalSource(nullptr), CurScope(nullptr), + Ident_super(nullptr), MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), - VtorDispStack(LangOpts.getVtorDispMode()), + 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), - IsBuildingRecoveryCallExpr(false), LateTemplateParser(nullptr), - LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), - StdInitializerList(nullptr), StdCoroutineTraitsCache(nullptr), - CXXTypeInfoDecl(nullptr), StdSourceLocationImplDecl(nullptr), + StdCoroutineTraitsCache(nullptr), IdResolver(pp), + OriginalLexicalContext(nullptr), StdInitializerList(nullptr), + FullyCheckedComparisonCategories( + static_cast(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), + ArgumentPackSubstitutionIndex(-1), SatisfactionCache(Context), NSNumberDecl(nullptr), NSValueDecl(nullptr), NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr), ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr), - DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false), - TUKind(TUKind), NumSFINAEErrors(0), - FullyCheckedComparisonCategories( - static_cast(ComparisonCategoryType::Last) + 1), - SatisfactionCache(Context), AccessCheckingSFINAE(false), - InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), - ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr), - DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this), - ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr), - CurScope(nullptr), Ident_super(nullptr) { + DictionaryWithObjectsMethod(nullptr), CodeCompleter(CodeCompleter), + VarDataSharingAttributesStack(nullptr) { assert(pp.TUKind == TUKind); TUScope = nullptr;