[clang] [clang][NFC] Regroup declarations in `Sema` (PR #82217)
Vlad Serebrennikov via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 6 00:55:22 PST 2024
https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/82217
>From 2efe0a503831f66432a550111abc4a31be0702da Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Feb 2024 09:51:53 +0300
Subject: [PATCH 1/8] [clang][NFC] Regroup declarations in `Sema`
This patch regroups declarations in `Sema` based on the file they are implemented in (e.g. `SemaChecking.cpp`). This allows to logically split `Sema` in 42 groups. Table of contents added at the very beginning of `Sema`.
While grouping is intentional, as well as each group consisting of `public` declarations followed by `private` ones (without changing access in-between), exact contents and order of declarations of each group is partially carried over from old structure, partially accidental due to time constrains to do the regrouping over the weekend (`Sema` is just enormously big). Further work is expected to refine contents and order of declarations.
What is also intentional is some kind of layering, where Concepts group follows template groups, and ObjC, code completion, CUDA, HLSL, OpenACC, OpenMP, and SYCL are all placed at the end of the file, after C and C++ parts of `Sema`.
Member initializer list of `Sema` in `Sema.cpp` is rewritten to reflect new order of data members in order to avoid `-Wreorder-ctor`.
---
clang/include/clang/Sema/Sema.h | 22954 +++++++++++++++---------------
clang/lib/Sema/Sema.cpp | 38 +-
2 files changed, 11782 insertions(+), 11210 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e9cd42ae777df5..48ffffa791d8da 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -423,590 +423,650 @@ enum class TemplateDeductionResult {
/// Sema - This implements semantic analysis and AST building for C.
class Sema final {
- Sema(const Sema &) = delete;
- void operator=(const Sema &) = delete;
-
- ///Source of additional semantic information.
- IntrusiveRefCntPtr<ExternalSemaSource> 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<QualType> 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<DeclGroupRef> DeclGroupPtrTy;
- typedef OpaquePtr<TemplateName> TemplateTy;
- typedef OpaquePtr<QualType> 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<Scope*, 2> 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<TypoExpr *, 2> 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 <typename T>
+ 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 <typename T,
+ typename = std::enable_if_t<!std::is_lvalue_reference<T>::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 };
+ 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
+ };
- // #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.");
- }
+ SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
+ const FunctionDecl *Fn, Sema &S);
+ SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
+ SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;
- // #pragma align info constructor
- AlignPackInfo(AlignPackInfo::Mode M, bool IsXL)
- : PackAttr(false), AlignMode(M),
- PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {}
+ // The copy and move assignment operator is defined as deleted pending
+ // further motivation.
+ SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete;
+ SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete;
- explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {}
+ ~SemaDiagnosticBuilder();
- AlignPackInfo() : AlignPackInfo(Native, false) {}
+ bool isImmediate() const { return ImmediateDiag.has_value(); }
- // 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;
-
- Encoding |= static_cast<uint32_t>(Info.getAlignMode()) << 1;
-
- 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<uint32_t>(Info.getPackNumber()) << 4;
+ template <typename T>
+ 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;
+ }
- return Encoding;
+ // 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 <typename T,
+ typename = std::enable_if_t<!std::is_lvalue_reference<T>::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;
}
- static AlignPackInfo getFromRawEncoding(unsigned Encoding) {
- bool IsXL = static_cast<bool>(Encoding & IsXLMask);
- AlignPackInfo::Mode M =
- static_cast<AlignPackInfo::Mode>((Encoding & AlignModeMask) >> 1);
- int PackNumber = (Encoding & PackNumMask) >> 4;
+ 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;
+ }
- if (Encoding & PackAttrMask)
- return AlignPackInfo(M, PackNumber, IsXL);
+ void AddFixItHint(const FixItHint &Hint) const {
+ if (ImmediateDiag)
+ ImmediateDiag->AddFixItHint(Hint);
+ else if (PartialDiagId)
+ S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint);
+ }
- return AlignPackInfo(M, IsXL);
+ 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 IsPackAttr() const { return PackAttr; }
+ private:
+ Sema &S;
+ SourceLocation Loc;
+ unsigned DiagID;
+ const FunctionDecl *Fn;
+ bool ShowCallStack;
- bool IsAlignAttr() const { return !PackAttr; }
+ // Invariant: At most one of these Optionals has a value.
+ // FIXME: Switch these to a Variant once that exists.
+ std::optional<ImmediateDiagBuilder> ImmediateDiag;
+ std::optional<unsigned> PartialDiagId;
+ };
- Mode getAlignMode() const { return AlignMode; }
+ void PrintStats() const;
- unsigned getPackNumber() const { return PackNumber; }
+ /// Warn that the stack is nearly exhausted.
+ void warnStackExhausted(SourceLocation Loc);
- 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;
- }
+ /// 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<void()> Fn);
- bool IsXLStack() const { return XLStack; }
+ /// Returns default addr space for method qualifiers.
+ LangAS getDefaultCXXMethodAddrSpace() const;
- bool operator==(const AlignPackInfo &Info) const {
- return std::tie(AlignMode, PackNumber, PackAttr, XLStack) ==
- std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
- Info.XLStack);
- }
+ /// Load weak undeclared identifiers from the external source.
+ void LoadExternalWeakUndeclaredIdentifiers();
- bool operator!=(const AlignPackInfo &Info) const {
- return !(*this == Info);
- }
+ /// 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;
- private:
- /// \brief True if this is a pragma pack attribute,
- /// not a pragma align attribute.
- bool PackAttr;
+ /// Obtain a sorted list of functions that are undefined but ODR-used.
+ void getUndefinedButUsed(
+ SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
- /// \brief The alignment mode that is in effect.
- Mode AlignMode;
+ typedef std::pair<SourceLocation, bool> DeleteExprLoc;
+ typedef llvm::SmallVector<DeleteExprLoc, 4> DeleteLocs;
+ /// Retrieves list of suspicious delete-expressions that will be checked at
+ /// the end of translation unit.
+ const llvm::MapVector<FieldDecl *, DeleteLocs> &
+ getMismatchingDeleteExpressions() const;
- /// \brief The pack number of the stack.
- unsigned char PackNumber;
+ /// 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 True if it is a XL #pragma align/pack stack.
- bool XLStack;
+ void addImplicitTypedef(StringRef Name, QualType T);
- /// \brief Uninitialized pack value.
- static constexpr unsigned char UninitPackVal = -1;
+ /// Emit a diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
+ bool DeferHint = false);
- // 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 partial diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
+ bool DeferHint = false);
- template<typename ValueType>
- 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) {}
- };
+ /// Whether uncompilable error has occurred. This includes error happens
+ /// in deferred diagnostics.
+ bool hasUncompilableErrorOccurred() const;
- 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;
- }
- }
+ bool findMacroSpelling(SourceLocation &loc, StringRef name);
- // 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 <name>(push, InternalPragmaSlot, <current_pragma_value>)
- // void Method {}
- // #pragma <name>(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);
- }
+ /// Calls \c Lexer::getLocForEndOfToken()
+ SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
- // Constructors.
- explicit PragmaStack(const ValueType &Default)
- : DefaultValue(Default), CurrentValue(Default) {}
+ /// Retrieve the module loader associated with the preprocessor.
+ ModuleLoader &getModuleLoader() const;
- bool hasValue() const { return CurrentValue != DefaultValue; }
+ /// Invent a new identifier for parameters of abbreviated templates.
+ IdentifierInfo *
+ InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
+ unsigned Index);
- SmallVector<Slot, 2> 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).
+ void emitAndClearUnusedLocalTypedefWarnings();
- /// 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<MSVtorDispMode> VtorDispStack;
- PragmaStack<AlignPackInfo> AlignPackStack;
- // The current #pragma align/pack values and locations at each #include.
- struct AlignPackIncludeState {
- AlignPackInfo CurrentValue;
- SourceLocation CurrentPragmaLocation;
- bool HasNonDefaultValue, ShouldWarnOnInclude;
+ // Emit all deferred diagnostics.
+ void emitDeferredDiags();
+
+ 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
};
- SmallVector<AlignPackIncludeState, 8> AlignPackIncludeStack;
- // Segment #pragmas.
- PragmaStack<StringLiteral *> DataSegStack;
- PragmaStack<StringLiteral *> BSSSegStack;
- PragmaStack<StringLiteral *> ConstSegStack;
- PragmaStack<StringLiteral *> CodeSegStack;
- // #pragma strict_gs_check.
- PragmaStack<bool> StrictGuardStackCheckStack;
+ void ActOnStartOfTranslationUnit();
+ void ActOnEndOfTranslationUnit();
+ void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind);
- // This stack tracks the current state of Sema.CurFPFeatures.
- PragmaStack<FPOptionsOverride> FpPragmaStack;
- FPOptionsOverride CurFPFeatureOverrides() {
- FPOptionsOverride result;
- if (!FpPragmaStack.hasValue()) {
- result = FPOptionsOverride();
- } else {
- result = FpPragmaStack.CurrentValue;
- }
- return result;
- }
+ Scope *getScopeForContext(DeclContext *Ctx);
- // 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); }
+ void PushFunctionScope();
+ void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+ sema::LambdaScopeInfo *PushLambdaScope();
- private:
- Sema &S;
- PragmaStack<FPOptionsOverride> SavedStack;
- };
+ /// 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 resetFPOptions(FPOptions FPO) {
- CurFPFeatures = FPO;
- FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
- }
+ void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
+ RecordDecl *RD, CapturedRegionKind K,
+ unsigned OpenMPCaptureLevel = 0);
- // 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();
+ /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
+ /// time after they've been popped.
+ class PoppedFunctionScopeDeleter {
+ Sema *Self;
- private:
- Sema &S;
- StringRef SlotLabel;
- bool ShouldAct;
+ public:
+ explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {}
+ void operator()(sema::FunctionScopeInfo *Scope) const;
};
- /// A mapping that describes the nullability we've seen in each header file.
- FileNullabilityMap NullabilityMap;
+ using PoppedFunctionScopePtr =
+ std::unique_ptr<sema::FunctionScopeInfo, PoppedFunctionScopeDeleter>;
- /// Last section used with #pragma init_seg.
- StringLiteral *CurInitSeg;
- SourceLocation CurInitSegLoc;
+ PoppedFunctionScopePtr
+ PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
+ const Decl *D = nullptr,
+ QualType BlockType = QualType());
- /// Sections used with #pragma alloc_text.
- llvm::StringMap<std::tuple<StringRef, SourceLocation>> FunctionToSectionMap;
+ sema::FunctionScopeInfo *getEnclosingFunction() const;
- /// VisContext - Manages the stack for \#pragma GCC visibility.
- void *VisContext; // Really a "PragmaVisStack*"
+ void setFunctionHasBranchIntoScope();
+ void setFunctionHasBranchProtectedScope();
+ void setFunctionHasIndirectGoto();
+ void setFunctionHasMustTail();
- /// This an attribute introduced by \#pragma clang attribute.
- struct PragmaAttributeEntry {
- SourceLocation Loc;
- ParsedAttr *Attribute;
- SmallVector<attr::SubjectMatchRule, 4> MatchRules;
- bool IsUsed;
- };
+ void PushCompoundScope(bool IsStmtExpr);
+ void PopCompoundScope();
- /// 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<PragmaAttributeEntry, 2> Entries;
- };
+ bool hasAnyUnrecoverableErrorsInThisFunction() const;
- SmallVector<PragmaAttributeGroup, 2> PragmaAttributeStack;
+ /// Retrieve the current block, if any.
+ sema::BlockScopeInfo *getCurBlock();
- /// The declaration that is currently receiving an attribute from the
- /// #pragma attribute stack.
- const Decl *PragmaAttributeCurrentTargetDecl;
+ /// 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;
- /// 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;
+ /// 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);
- /// 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;
+ /// Retrieve the current generic lambda info, if any.
+ sema::LambdaScopeInfo *getCurGenericLambda();
- /// Set of no-builtin functions listed by \#pragma function.
- llvm::SmallSetVector<StringRef, 4> MSFunctionNoBuiltins;
+ /// Retrieve the current captured region, if any.
+ sema::CapturedRegionScopeInfo *getCurCapturedRegion();
- /// 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;
+ void ActOnComment(SourceRange Comment);
- /// Used to control the generation of ExprWithCleanups.
- CleanupInfo Cleanup;
+ /// 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; }
- /// ExprCleanupObjects - This is the stack of objects requiring
- /// cleanup that are created by the current full expression.
- SmallVector<ExprWithCleanups::CleanupObject, 8> ExprCleanupObjects;
+ IdentifierInfo *getSuperIdentifier() const;
- /// 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<Expr *, 4>;
- MaybeODRUseExprSet MaybeODRUseExprs;
+ DeclContext *getCurLexicalContext() const {
+ return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
+ }
- std::unique_ptr<sema::FunctionScopeInfo> CachedFunctionScope;
+ 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;
+ }
- /// Stack containing information about each of the nested
- /// function, block, and method scopes that are currently active.
- SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+ /// Check if the type is allowed to be used for the current target.
+ void checkTypeSupport(QualType Ty, SourceLocation Loc,
+ ValueDecl *D = nullptr);
- /// The index of the first FunctionScope that corresponds to the current
- /// context.
- unsigned FunctionScopesStart = 0;
+ /// 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
+ };
- /// Track the number of currently active capturing scopes.
- unsigned CapturingFunctionScopes = 0;
+ /// 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);
- ArrayRef<sema::FunctionScopeInfo*> getFunctionScopes() const {
- return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
- FunctionScopes.end());
- }
+ /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
+ /// to the conversion from scalar type ScalarTy to the Boolean type.
+ static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
- /// 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<InventedTemplateParameterInfo, 4> InventedParameterInfos;
+ /// If \p AllowLambda is true, treat lambda as function.
+ DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const;
- /// The index of the first InventedParameterInfo that refers to the current
- /// context.
- unsigned InventedParameterInfosStart = 0;
+ /// 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;
- ArrayRef<InventedTemplateParameterInfo> getInventedParameterInfos() const {
- return llvm::ArrayRef(InventedParameterInfos.begin() +
- InventedParameterInfosStart,
- InventedParameterInfos.end());
+ /// 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;
+
+ /// 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);
}
- typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
- &ExternalSemaSource::ReadExtVectorDecls, 2, 2>
- ExtVectorDeclsType;
+ /// Retrieve a suitable printing policy for diagnostics.
+ static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx,
+ const Preprocessor &PP);
- /// 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;
+ /// Scope actions.
+ void ActOnTranslationUnitScope(Scope *S);
- /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
- std::unique_ptr<CXXFieldCollector> FieldCollector;
+ /// Determine whether \param D is function like (function or function
+ /// template) for parsing.
+ bool isDeclaratorFunctionLike(Declarator &D);
- typedef llvm::SmallSetVector<const NamedDecl *, 16> NamedDeclSetType;
+ /// 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;
- /// Set containing all declared private fields that are not used.
- NamedDeclSetType UnusedPrivateFields;
+ /// Flag indicating whether or not to collect detailed statistics.
+ bool CollectStats;
- /// Set containing all typedefs that are likely unused.
- llvm::SmallSetVector<const TypedefNameDecl *, 4>
- UnusedLocalTypedefNameCandidates;
+ std::unique_ptr<sema::FunctionScopeInfo> CachedFunctionScope;
- /// Delete-expressions to be analyzed at the end of translation unit
+ /// Stack containing information about each of the nested
+ /// function, block, and method scopes that are currently active.
+ SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+
+ /// The index of the first FunctionScope that corresponds to the current
+ /// context.
+ unsigned FunctionScopesStart = 0;
+
+ /// Track the number of currently active capturing scopes.
+ unsigned CapturingFunctionScopes = 0;
+
+ llvm::BumpPtrAllocator BumpAlloc;
+
+ /// The kind of translation unit we are processing.
///
- /// 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<SourceLocation, bool> DeleteExprLoc;
- typedef llvm::SmallVector<DeleteExprLoc, 4> DeleteLocs;
- llvm::MapVector<FieldDecl *, DeleteLocs> DeleteExprs;
+ /// 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 llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
+ /// 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;
- /// 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<RecordDeclSetTy> PureVirtualClassDiagSet;
+ bool WarnedStackExhausted = false;
- /// ParsingInitForAutoVars - a set of declarations with auto types for which
- /// we are currently parsing the initializer.
- llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
+ void incrementMSManglingNumber() const {
+ return CurScope->incrementMSManglingNumber();
+ }
- /// Look for a locally scoped extern "C" declaration by the given name.
- NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
+ /// 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 LazyVector<VarDecl *, ExternalSemaSource,
- &ExternalSemaSource::ReadTentativeDefinitions, 2, 2>
- TentativeDefinitionsType;
+ /// Figure out if an expression could be turned into a call.
+ bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
+ UnresolvedSetImpl &NonTemplateOverloads);
- /// All the tentative definitions encountered in the TU.
- TentativeDefinitionsType TentativeDefinitions;
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+ typedef OpaquePtr<QualType> TypeTy;
- /// All the external declarations encoutered and used in the TU.
- SmallVector<VarDecl *, 4> ExternalDeclarations;
+ OpenCLOptions OpenCLFeatures;
+ FPOptions CurFPFeatures;
- typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource,
- &ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2>
- UnusedFileScopedDeclsType;
+ const LangOptions &LangOpts;
+ Preprocessor &PP;
+ ASTContext &Context;
+ ASTConsumer &Consumer;
+ DiagnosticsEngine &Diags;
+ SourceManager &SourceMgr;
+ api_notes::APINotesManager APINotes;
- /// 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;
+ /// A RAII object to enter scope of a compound statement.
+ class CompoundScopeRAII {
+ public:
+ CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) {
+ S.ActOnStartOfCompoundStmt(IsStmtExpr);
+ }
- typedef LazyVector<CXXConstructorDecl *, ExternalSemaSource,
- &ExternalSemaSource::ReadDelegatingConstructors, 2, 2>
- DelegatingCtorDeclsType;
+ ~CompoundScopeRAII() {
+ S.ActOnFinishOfCompoundStmt();
+ }
- /// All the delegating constructors seen so far in the file, used for
- /// cycle detection at the end of the TU.
- DelegatingCtorDeclsType DelegatingCtorDecls;
+ private:
+ Sema &S;
+ };
- /// All the overriding functions seen during a class definition
- /// that had their exception spec checks delayed, plus the overridden
- /// function.
- SmallVector<std::pair<const CXXMethodDecl*, const CXXMethodDecl*>, 2>
- DelayedOverridingExceptionSpecChecks;
+ /// 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; }
+ };
- /// 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<std::pair<FunctionDecl*, FunctionDecl*>, 2>
- DelayedEquivalentExceptionSpecChecks;
+ /// Build a partial diagnostic.
+ PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
- typedef llvm::MapVector<const FunctionDecl *,
- std::unique_ptr<LateParsedTemplate>>
- LateParsedTemplateMapT;
- LateParsedTemplateMapT LateParsedTemplateMap;
+ 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);
@@ -1027,6 +1087,14 @@ class Sema final {
std::function<TypeResult(StringRef, StringRef, SourceLocation)>
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 {
@@ -1089,1669 +1157,1674 @@ class Sema final {
}
} DelayedDiagnostics;
- enum CUDAFunctionTarget {
- CFT_Device,
- CFT_Global,
- CFT_Host,
- CFT_HostDevice,
- CFT_InvalidTarget
- };
-
- /// A RAII object to temporarily push a declaration context.
- class ContextRAII {
- private:
- Sema &S;
- DeclContext *SavedContext;
- ProcessingContextState SavedContextState;
- QualType SavedCXXThisTypeOverride;
- unsigned SavedFunctionScopesStart;
- unsigned SavedInventedParameterInfosStart;
+ ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
+ return DelayedDiagnostics.push(pool);
+ }
- 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();
- }
+ /// CurContext - This is the current declaration context of parsing.
+ DeclContext *CurContext;
- void pop() {
- if (!SavedContext) return;
- S.CurContext = SavedContext;
- S.DelayedDiagnostics.popUndelayed(SavedContextState);
- S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
- S.FunctionScopesStart = SavedFunctionScopesStart;
- S.InventedParameterInfosStart = SavedInventedParameterInfosStart;
- SavedContext = nullptr;
- }
+ friend class Parser;
+ friend class InitializationSequence;
+ friend class ASTReader;
+ friend class ASTDeclReader;
+ friend class ASTWriter;
- ~ContextRAII() {
- pop();
- }
- };
+private:
+ std::optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo;
+ bool WarnedDarwinSDKInfoMissing = false;
- /// RAII object to handle the state changes required to synthesize
- /// a function body.
- class SynthesizedFunctionScope {
- Sema &S;
- Sema::ContextRAII SavedContext;
- bool PushedCodeSynthesisContext = false;
-
- public:
- SynthesizedFunctionScope(Sema &S, DeclContext *DC)
- : S(S), SavedContext(S, DC) {
- auto *FD = dyn_cast<FunctionDecl>(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.back().InImmediateEscalatingFunctionContext =
- S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
- } else
- assert(isa<ObjCMethodDecl>(DC));
- }
-
- void addContextNote(SourceLocation UseLoc) {
- assert(!PushedCodeSynthesisContext);
-
- Sema::CodeSynthesisContext Ctx;
- Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction;
- Ctx.PointOfInstantiation = UseLoc;
- Ctx.Entity = cast<Decl>(S.CurContext);
- S.pushCodeSynthesisContext(Ctx);
-
- PushedCodeSynthesisContext = true;
- }
+ Sema(const Sema &) = delete;
+ void operator=(const Sema &) = delete;
- ~SynthesizedFunctionScope() {
- if (PushedCodeSynthesisContext)
- S.popCodeSynthesisContext();
- if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext)) {
- FD->setWillHaveBody(false);
- S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction());
- }
- S.PopExpressionEvaluationContext();
- S.PopFunctionScopeInfo();
- }
- };
+ /// Source of additional semantic information.
+ IntrusiveRefCntPtr<ExternalSemaSource> ExternalSource;
- /// WeakUndeclaredIdentifiers - Identifiers contained in \#pragma weak before
- /// declared. Rare. May alias another identifier, declared or undeclared.
+ /// The handler for the FileChanged preprocessor events.
///
- /// 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<WeakInfo, 1u>,
- llvm::SmallDenseSet<WeakInfo, 2u, WeakInfo::DenseMapInfoByAliasOnly>>>
- WeakUndeclaredIdentifiers;
-
- /// 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<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers;
+ /// Used for diagnostics that implement custom semantic analysis for #include
+ /// directives, like -Wpragma-pack.
+ sema::SemaPPCallbacks *SemaPPCallbackHandler;
+ /// The parser's current scope.
+ ///
+ /// The parser maintains this state here.
+ Scope *CurScope;
- /// Load weak undeclared identifiers from the external source.
- void LoadExternalWeakUndeclaredIdentifiers();
+ mutable IdentifierInfo *Ident_super;
- /// 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<Decl*,2> WeakTopLevelDecl;
+ /// @}
- IdentifierResolver IdResolver;
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- /// 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;
+ /// \name C++ Access Control
+ /// Implementations are in SemaAccess.cpp
+ /// @{
- /// The C++ "std" namespace, where the standard library resides.
- LazyDeclPtr StdNamespace;
+public:
+ enum AccessResult {
+ AR_accessible,
+ AR_inaccessible,
+ AR_dependent,
+ AR_delayed
+ };
- /// The C++ "std::bad_alloc" class, which is defined by the C++
- /// standard library.
- LazyDeclPtr StdBadAlloc;
+ bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+ NamedDecl *PrevMemberDecl,
+ AccessSpecifier LexicalAS);
- /// The C++ "std::align_val_t" enum class, which is defined by the C++
- /// standard library.
- LazyDeclPtr StdAlignValT;
+ 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<Expr *> 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());
+ }
- /// The C++ "std::initializer_list" template, which is defined in
- /// \<initializer_list>.
- ClassTemplateDecl *StdInitializerList;
+ void HandleDependentAccessCheck(const DependentDiagnostic &DD,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
- /// The C++ "std::coroutine_traits" template, which is defined in
- /// \<coroutine_traits>
- ClassTemplateDecl *StdCoroutineTraitsCache;
+ /// @}
- /// The C++ "type_info" declaration, which is defined in \<typeinfo>.
- RecordDecl *CXXTypeInfoDecl;
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- /// The C++ "std::source_location::__impl" struct, defined in
- /// \<source_location>.
- RecordDecl *StdSourceLocationImplDecl;
+ /// \name Attributes
+ /// Implementations are in SemaAttr.cpp
+ /// @{
- /// Caches identifiers/selectors for NSFoundation APIs.
- std::unique_ptr<NSAPI> NSAPIObj;
+public:
+ /// Controls member pointer representation format under the MS ABI.
+ LangOptions::PragmaMSPointersToMembersKind
+ MSPointerToMemberRepresentationMethod;
- /// The declaration of the Objective-C NSNumber class.
- ObjCInterfaceDecl *NSNumberDecl;
+ bool MSStructPragmaOn; // True when \#pragma ms_struct on
- /// The declaration of the Objective-C NSValue class.
- ObjCInterfaceDecl *NSValueDecl;
+ /// Source location for newly created implicit MSInheritanceAttrs
+ SourceLocation ImplicitMSInheritanceAttrLoc;
- /// Pointer to NSNumber type (NSNumber *).
- QualType NSNumberPointer;
+ /// pragma clang section kind
+ enum PragmaClangSectionKind {
+ PCSK_Invalid = 0,
+ PCSK_BSS = 1,
+ PCSK_Data = 2,
+ PCSK_Rodata = 3,
+ PCSK_Text = 4,
+ PCSK_Relro = 5
+ };
- /// Pointer to NSValue type (NSValue *).
- QualType NSValuePointer;
+ enum PragmaClangSectionAction {
+ PCSA_Set = 0,
+ PCSA_Clear = 1
+ };
- /// The Objective-C NSNumber methods used to create NSNumber literals.
- ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
+ struct PragmaClangSection {
+ std::string SectionName;
+ bool Valid = false;
+ SourceLocation PragmaLocation;
+ };
- /// The declaration of the Objective-C NSString class.
- ObjCInterfaceDecl *NSStringDecl;
+ PragmaClangSection PragmaClangBSSSection;
+ PragmaClangSection PragmaClangDataSection;
+ PragmaClangSection PragmaClangRodataSection;
+ PragmaClangSection PragmaClangRelroSection;
+ PragmaClangSection PragmaClangTextSection;
- /// Pointer to NSString type (NSString *).
- QualType NSStringPointer;
+ 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)
+ };
- /// The declaration of the stringWithUTF8String: method.
- ObjCMethodDecl *StringWithUTF8StringMethod;
+ struct PragmaPackInfo {
+ PragmaMsStackAction Action;
+ StringRef SlotLabel;
+ Token Alignment;
+ };
- /// The declaration of the valueWithBytes:objCType: method.
- ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
+ // #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 NSArray class.
- ObjCInterfaceDecl *NSArrayDecl;
+ // #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.");
+ }
- /// The declaration of the arrayWithObjects:count: method.
- ObjCMethodDecl *ArrayWithObjectsMethod;
+ // #pragma align info constructor
+ AlignPackInfo(AlignPackInfo::Mode M, bool IsXL)
+ : PackAttr(false), AlignMode(M),
+ PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {}
- /// The declaration of the Objective-C NSDictionary class.
- ObjCInterfaceDecl *NSDictionaryDecl;
+ explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {}
- /// The declaration of the dictionaryWithObjects:forKeys:count: method.
- ObjCMethodDecl *DictionaryWithObjectsMethod;
+ AlignPackInfo() : AlignPackInfo(Native, false) {}
- /// id<NSCopying> type.
- QualType QIDNSCopying;
+ // 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;
- /// will hold 'respondsToSelector:'
- Selector RespondsToSelectorSel;
+ Encoding |= static_cast<uint32_t>(Info.getAlignMode()) << 1;
- /// A flag to remember whether the implicit forms of operator new and delete
- /// have been declared.
- bool GlobalNewDeleteDeclared;
+ if (Info.IsPackAttr())
+ Encoding |= PackAttrMask;
- /// 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,
+ Encoding |= static_cast<uint32_t>(Info.getPackNumber()) << 4;
- /// 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,
+ return Encoding;
+ }
- /// 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,
+ static AlignPackInfo getFromRawEncoding(unsigned Encoding) {
+ bool IsXL = static_cast<bool>(Encoding & IsXLMask);
+ AlignPackInfo::Mode M =
+ static_cast<AlignPackInfo::Mode>((Encoding & AlignModeMask) >> 1);
+ int PackNumber = (Encoding & PackNumMask) >> 4;
- /// 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,
+ if (Encoding & PackAttrMask)
+ return AlignPackInfo(M, PackNumber, IsXL);
- /// 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,
+ return AlignPackInfo(M, IsXL);
+ }
- /// 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 IsPackAttr() const { return PackAttr; }
- /// 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,
+ bool IsAlignAttr() const { return !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
- };
+ Mode getAlignMode() const { return AlignMode; }
- using ImmediateInvocationCandidate = llvm::PointerIntPair<ConstantExpr *, 1>;
+ unsigned getPackNumber() const { return PackNumber; }
- /// Data structure used to record current or nested
- /// expression evaluation contexts.
- struct ExpressionEvaluationContextRecord {
- /// The expression evaluation context.
- ExpressionEvaluationContext Context;
+ 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;
+ }
- /// Whether the enclosing context needed a cleanup.
- CleanupInfo ParentCleanup;
+ bool IsXLStack() const { return XLStack; }
- /// The number of active cleanup objects when we entered
- /// this expression evaluation context.
- unsigned NumCleanupObjects;
+ bool operator==(const AlignPackInfo &Info) const {
+ return std::tie(AlignMode, PackNumber, PackAttr, XLStack) ==
+ std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
+ Info.XLStack);
+ }
- /// The number of typos encountered during this expression evaluation
- /// context (i.e. the number of TypoExprs created).
- unsigned NumTypos;
+ bool operator!=(const AlignPackInfo &Info) const {
+ return !(*this == Info);
+ }
- MaybeODRUseExprSet SavedMaybeODRUseExprs;
+ private:
+ /// \brief True if this is a pragma pack attribute,
+ /// not a pragma align attribute.
+ bool PackAttr;
- /// The lambdas that are present within this context, if it
- /// is indeed an unevaluated context.
- SmallVector<LambdaExpr *, 2> Lambdas;
+ /// \brief The alignment mode that is in effect.
+ Mode AlignMode;
- /// 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;
+ /// \brief The pack number of the stack.
+ unsigned char PackNumber;
- /// 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<CallExpr *, 8> DelayedDecltypeCalls;
+ /// \brief True if it is a XL #pragma align/pack stack.
+ bool XLStack;
- /// If we are processing a decltype type, a set of temporary binding
- /// expressions for which we have deferred checking the destructor.
- SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
+ /// \brief Uninitialized pack value.
+ static constexpr unsigned char UninitPackVal = -1;
- llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
+ // 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};
+ };
- /// 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<Expr*, 2> VolatileAssignmentLHSs;
+ template<typename ValueType>
+ 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) {}
+ };
- /// Set of candidates for starting an immediate invocation.
- llvm::SmallVector<ImmediateInvocationCandidate, 4> ImmediateInvocationCandidates;
+ 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;
+ }
+ }
- /// Set of DeclRefExprs referencing a consteval function when used in a
- /// context not already known to be immediately invoked.
- llvm::SmallPtrSet<DeclRefExpr *, 4> ReferenceToConsteval;
+ // 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 <name>(push, InternalPragmaSlot, <current_pragma_value>)
+ // void Method {}
+ // #pragma <name>(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);
+ }
- /// 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<MaterializeTemporaryExpr *, 8> ForRangeLifetimeExtendTemps;
+ // Constructors.
+ explicit PragmaStack(const ValueType &Default)
+ : DefaultValue(Default), CurrentValue(Default) {}
- /// \brief Describes whether we are in an expression constext which we have
- /// to handle differently.
- enum ExpressionKind {
- EK_Decltype, EK_TemplateArgument, EK_Other
- } ExprContext;
+ bool hasValue() const { return CurrentValue != DefaultValue; }
- // 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;
-
- bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
+ SmallVector<Slot, 2> 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).
- // 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;
+ /// 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<MSVtorDispMode> VtorDispStack;
+ PragmaStack<AlignPackInfo> AlignPackStack;
+ // The current #pragma align/pack values and locations at each #include.
+ struct AlignPackIncludeState {
+ AlignPackInfo CurrentValue;
+ SourceLocation CurrentPragmaLocation;
+ bool HasNonDefaultValue, ShouldWarnOnInclude;
+ };
+ SmallVector<AlignPackIncludeState, 8> AlignPackIncludeStack;
+ // Segment #pragmas.
+ PragmaStack<StringLiteral *> DataSegStack;
+ PragmaStack<StringLiteral *> BSSSegStack;
+ PragmaStack<StringLiteral *> ConstSegStack;
+ PragmaStack<StringLiteral *> CodeSegStack;
- /// 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;
+ // #pragma strict_gs_check.
+ PragmaStack<bool> StrictGuardStackCheckStack;
- /// 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<T> 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;
+ // This stack tracks the current state of Sema.CurFPFeatures.
+ PragmaStack<FPOptionsOverride> FpPragmaStack;
+ FPOptionsOverride CurFPFeatureOverrides() {
+ FPOptionsOverride result;
+ if (!FpPragmaStack.hasValue()) {
+ result = FPOptionsOverride();
+ } else {
+ result = FpPragmaStack.CurrentValue;
+ }
+ return result;
+ }
- // 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");
- }
+ enum PragmaSectionKind {
+ PSK_DataSeg,
+ PSK_BSSSeg,
+ PSK_ConstSeg,
+ PSK_CodeSeg,
+ };
- SourceLocation Loc;
- ValueDecl *Decl = nullptr;
- DeclContext *Context = nullptr;
- };
- std::optional<InitializationContext> DelayedDefaultInitializationContext;
+ // 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();
- 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) {}
+ private:
+ Sema &S;
+ StringRef SlotLabel;
+ bool ShouldAct;
+ };
- bool isUnevaluated() const {
- return Context == ExpressionEvaluationContext::Unevaluated ||
- Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
- Context == ExpressionEvaluationContext::UnevaluatedList;
- }
+ /// Last section used with #pragma init_seg.
+ StringLiteral *CurInitSeg;
+ SourceLocation CurInitSegLoc;
- bool isConstantEvaluated() const {
- return Context == ExpressionEvaluationContext::ConstantEvaluated ||
- Context == ExpressionEvaluationContext::ImmediateFunctionContext;
- }
+ /// Sections used with #pragma alloc_text.
+ llvm::StringMap<std::tuple<StringRef, SourceLocation>> FunctionToSectionMap;
- 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);
- }
+ /// VisContext - Manages the stack for \#pragma GCC visibility.
+ void *VisContext; // Really a "PragmaVisStack*"
- bool isDiscardedStatementContext() const {
- return Context == ExpressionEvaluationContext::DiscardedStatement ||
- (Context ==
- ExpressionEvaluationContext::ImmediateFunctionContext &&
- InDiscardedStatement);
- }
+ /// This an attribute introduced by \#pragma clang attribute.
+ struct PragmaAttributeEntry {
+ SourceLocation Loc;
+ ParsedAttr *Attribute;
+ SmallVector<attr::SubjectMatchRule, 4> MatchRules;
+ bool IsUsed;
};
- /// A stack of expression evaluation contexts.
- SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+ /// 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<PragmaAttributeEntry, 2> Entries;
+ };
- // Set of failed immediate invocations to avoid double diagnosing.
- llvm::SmallPtrSet<ConstantExpr *, 4> FailedImmediateInvocations;
+ SmallVector<PragmaAttributeGroup, 2> PragmaAttributeStack;
- /// Emit a warning for all pending noderef expressions that we recorded.
- void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
+ /// The declaration that is currently receiving an attribute from the
+ /// #pragma attribute stack.
+ const Decl *PragmaAttributeCurrentTargetDecl;
- /// 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<MangleNumberingContext *, Decl *>
- getCurrentMangleNumberContext(const DeclContext *DC);
+ /// 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;
+ /// 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;
+ }
- /// 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
- };
- private:
- llvm::PointerIntPair<CXXMethodDecl *, 2> Pair;
+ /// 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;
- public:
- SpecialMemberOverloadResult() {}
- SpecialMemberOverloadResult(CXXMethodDecl *MD)
- : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {}
+ /// Set of no-builtin functions listed by \#pragma function.
+ llvm::SmallSetVector<StringRef, 4> MSFunctionNoBuiltins;
- CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
- void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
+ /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
+ /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
+ void AddAlignmentAttributesForRecord(RecordDecl *RD);
- Kind getKind() const { return static_cast<Kind>(Pair.getInt()); }
- void setKind(Kind K) { Pair.setInt(K); }
- };
+ /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
+ void AddMsStructLayoutForRecord(RecordDecl *RD);
- class SpecialMemberOverloadResultEntry
- : public llvm::FastFoldingSetNode,
- public SpecialMemberOverloadResult {
- public:
- SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
- : FastFoldingSetNode(ID)
- {}
- };
+ /// 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);
- /// A cache of special member function overload resolution results
- /// for C++ records.
- llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache;
+ /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
+ void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
- /// A cache of the flags available in enumerations with the flag_bits
- /// attribute.
- mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache;
+ /// Add [[gsl::Pointer]] attributes for std:: types.
+ void inferGslPointerAttribute(TypedefNameDecl *TD);
- /// 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;
-
- llvm::BumpPtrAllocator BumpAlloc;
+ 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
+ };
- /// The number of SFINAE diagnostics that have been trapped.
- unsigned NumSFINAEErrors;
+ /// ActOnPragmaClangSection - Called on well formed \#pragma clang section
+ void ActOnPragmaClangSection(SourceLocation PragmaLoc,
+ PragmaClangSectionAction Action,
+ PragmaClangSectionKind SecKind, StringRef SecName);
- typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>>
- UnparsedDefaultArgInstantiationsMap;
+ /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
+ void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+ SourceLocation PragmaLoc);
- /// 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;
+ /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
+ void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
+ StringRef SlotLabel, Expr *Alignment);
- // Contains the locations of the beginning of unparsed default
- // argument locations.
- llvm::DenseMap<ParmVarDecl *, SourceLocation> UnparsedDefaultArgLocs;
+ /// 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<Expr *> Args);
- /// UndefinedInternals - all the used, undefined objects which require a
- /// definition in this translation unit.
- llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed;
+ enum class PragmaAlignPackDiagnoseKind {
+ NonDefaultStateAtInclude,
+ ChangedStateAtExit
+ };
- /// 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;
+ void DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
+ SourceLocation IncludeLoc);
+ void DiagnoseUnterminatedPragmaAlignPack();
- /// Obtain a sorted list of functions that are undefined but ODR-used.
- void getUndefinedButUsed(
- SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
+ /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
+ void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
- /// Retrieves list of suspicious delete-expressions that will be checked at
- /// the end of translation unit.
- const llvm::MapVector<FieldDecl *, DeleteLocs> &
- getMismatchingDeleteExpressions() const;
+ /// ActOnPragmaMSComment - Called on well formed
+ /// \#pragma comment(kind, "arg").
+ void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
+ StringRef Arg);
- class GlobalMethodPool {
- public:
- using Lists = std::pair<ObjCMethodList, ObjCMethodList>;
- using iterator = llvm::DenseMap<Selector, Lists>::iterator;
- iterator begin() { return Methods.begin(); }
- iterator end() { return Methods.end(); }
- iterator find(Selector Sel) { return Methods.find(Sel); }
- std::pair<iterator, bool> insert(std::pair<Selector, Lists> &&Val) {
- return Methods.insert(Val);
- }
- int count(Selector Sel) const { return Methods.count(Sel); }
- bool empty() const { return Methods.empty(); }
+ /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
+ void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+ StringRef Value);
- private:
- llvm::DenseMap<Selector, Lists> Methods;
- };
+ /// Are precise floating point semantics currently enabled?
+ bool isPreciseFPEnabled() {
+ return !CurFPFeatures.getAllowFPReassociate() &&
+ !CurFPFeatures.getNoSignedZero() &&
+ !CurFPFeatures.getAllowReciprocal() &&
+ !CurFPFeatures.getAllowApproxFunc();
+ }
- /// 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;
+ void ActOnPragmaFPEvalMethod(SourceLocation Loc,
+ LangOptions::FPEvalMethodKind Value);
- /// Method selectors used in a \@selector expression. Used for implementation
- /// of -Wselector.
- llvm::MapVector<Selector, SourceLocation> ReferencedSelectors;
+ /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
+ void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
+ PragmaFloatControlKind Value);
- /// List of SourceLocations where 'self' is implicitly retained inside a
- /// block.
- llvm::SmallVector<std::pair<SourceLocation, const BlockDecl *>, 1>
- ImplicitlyRetainedSelfLocs;
+ /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
+ /// pointers_to_members(representation method[, general purpose
+ /// representation]).
+ void ActOnPragmaMSPointersToMembers(
+ LangOptions::PragmaMSPointersToMembersKind Kind,
+ SourceLocation PragmaLoc);
- /// Kinds of C++ special members.
- enum CXXSpecialMember {
- CXXDefaultConstructor,
- CXXCopyConstructor,
- CXXMoveConstructor,
- CXXCopyAssignment,
- CXXMoveAssignment,
- CXXDestructor,
- CXXInvalid
- };
+ /// Called on well formed \#pragma vtordisp().
+ void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
+ SourceLocation PragmaLoc,
+ MSVtorDispMode Value);
- typedef llvm::PointerIntPair<CXXRecordDecl *, 3, CXXSpecialMember>
- SpecialMemberDecl;
+ bool UnifySection(StringRef SectionName, int SectionFlags,
+ NamedDecl *TheDecl);
+ bool UnifySection(StringRef SectionName,
+ int SectionFlags,
+ SourceLocation PragmaSectionLocation);
- /// 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<SpecialMemberDecl, 4> SpecialMembersBeingDeclared;
+ /// 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);
- /// 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,
- };
+ /// Called on well formed \#pragma section().
+ void ActOnPragmaMSSection(SourceLocation PragmaLocation,
+ int SectionFlags, StringLiteral *SegmentName);
- /// 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<const NamedDecl *, 4> TypoCorrectedFunctionDefinitions;
+ /// Called on well-formed \#pragma init_seg().
+ void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
+ StringLiteral *SegmentName);
- /// Stack of types that correspond to the parameter entities that are
- /// currently being copy-initialized. Can be empty.
- llvm::SmallVector<QualType, 4> CurrentParameterCopyTypes;
+ /// Called on well-formed \#pragma alloc_text().
+ void ActOnPragmaMSAllocText(
+ SourceLocation PragmaLocation, StringRef Section,
+ const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>>
+ &Functions);
- void ReadMethodPool(Selector Sel);
- void updateOutOfDateSelector(Selector Sel);
+ /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma
+ /// strict_gs_check.
+ void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ bool Value);
- /// Private Helper predicate to check for 'self'.
- bool isSelfExpr(Expr *RExpr);
- bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method);
+ /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
+ void ActOnPragmaUnused(const Token &Identifier,
+ Scope *curScope,
+ SourceLocation PragmaLoc);
- /// 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);
+ /// 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);
- /// Records and restores the CurFPFeatures state on entry/exit of compound
- /// statements.
- class FPFeaturesStateRAII {
- public:
- FPFeaturesStateRAII(Sema &S);
- ~FPFeaturesStateRAII();
- FPOptionsOverride getOverrides() { return OldOverrides; }
+ void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
+ SourceLocation PragmaLoc,
+ attr::ParsedSubjectMatchRuleSet Rules);
+ void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace);
- private:
- Sema& S;
- FPOptions OldFPFeaturesState;
- FPOptionsOverride OldOverrides;
- LangOptions::FPEvalMethodKind OldEvalMethod;
- SourceLocation OldFPPragmaLocation;
- };
+ /// Called on well-formed '\#pragma clang attribute pop'.
+ void ActOnPragmaAttributePop(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace);
- void addImplicitTypedef(StringRef Name, QualType T);
+ /// Adds the attributes that have been specified using the
+ /// '\#pragma clang attribute push' directives to the given declaration.
+ void AddPragmaAttributes(Scope *S, Decl *D);
- bool WarnedStackExhausted = false;
+ void PrintPragmaAttributeInstantiationPoint();
- /// 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<const VarDecl *, int> RefsMinusAssignments;
+ void DiagnoseUnterminatedPragmaAttribute();
- /// Indicate RISC-V vector builtin functions enabled or not.
- bool DeclareRISCVVBuiltins = false;
+ /// Called on well formed \#pragma clang optimize.
+ void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
- /// Indicate RISC-V SiFive vector builtin functions enabled or not.
- bool DeclareRISCVSiFiveVectorBuiltins = false;
+ /// #pragma optimize("[optimization-list]", on | off).
+ void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn);
-private:
- std::unique_ptr<sema::RISCVIntrinsicManager> RVIntrinsicManager;
+ /// Call on well formed \#pragma function.
+ void
+ ActOnPragmaMSFunction(SourceLocation Loc,
+ const llvm::SmallVectorImpl<StringRef> &NoBuiltins);
- std::optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo;
+ /// 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);
- bool WarnedDarwinSDKInfoMissing = false;
+ /// 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);
-public:
- Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
- TranslationUnitKind TUKind = TU_Complete,
- CodeCompleteConsumer *CompletionConsumer = nullptr);
- ~Sema();
+ /// 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);
- /// Perform initialization that occurs after the parser has been
- /// initialized but before it parses anything.
- void Initialize();
+ /// 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);
- /// 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();
+ /// 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);
- const LangOptions &getLangOpts() const { return LangOpts; }
- OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
- FPOptions &getCurFPFeatures() { return CurFPFeatures; }
+ /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used,
+ /// add an appropriate visibility attribute.
+ void AddPushedVisibilityAttribute(Decl *RD);
- 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(); }
+ /// FreeVisContext - Deallocate and null out VisContext.
+ void FreeVisContext();
- DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
- StringRef Platform);
- DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking();
+ /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
+ void ActOnPragmaVisibility(const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc);
- ///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);
+ /// ActOnPragmaFPContract - Called on well formed
+ /// \#pragma {STDC,OPENCL} FP_CONTRACT and
+ /// \#pragma clang fp contract
+ void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
- void PrintStats() const;
+ /// Called on well formed
+ /// \#pragma clang fp reassociate
+ /// or
+ /// \#pragma clang fp reciprocal
+ void ActOnPragmaFPValueChangingOption(SourceLocation Loc, PragmaFPKind Kind,
+ bool IsEnabled);
- /// Warn that the stack is nearly exhausted.
- void warnStackExhausted(SourceLocation Loc);
+ /// ActOnPragmaFenvAccess - Called on well formed
+ /// \#pragma STDC FENV_ACCESS
+ void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
- /// 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<void()> Fn);
+ /// ActOnPragmaCXLimitedRange - Called on well formed
+ /// \#pragma STDC CX_LIMITED_RANGE
+ void ActOnPragmaCXLimitedRange(SourceLocation Loc,
+ LangOptions::ComplexRangeKind Range);
- /// 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;
+ /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
+ void ActOnPragmaFPExceptions(SourceLocation Loc,
+ LangOptions::FPExceptionModeKind);
- 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) {}
+ /// Called to set constant rounding mode for floating point operations.
+ void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
- // 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;
+ /// Called to set exception behavior for floating point operations.
+ void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
- ~ImmediateDiagBuilder() {
- // If we aren't active, there is nothing to do.
- if (!isActive()) return;
+ /// PushNamespaceVisibilityAttr - Note that we've entered a
+ /// namespace with a visibility attribute.
+ void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
+ SourceLocation Loc);
- // 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();
+ /// 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);
- // Dispatch to Sema to emit the diagnostic.
- SemaRef.EmitCurrentDiagnostic(DiagID);
- }
+ /// 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);
- /// Teach operator<< to produce an object of the correct type.
- template <typename T>
- friend const ImmediateDiagBuilder &
- operator<<(const ImmediateDiagBuilder &Diag, const T &Value) {
- const DiagnosticBuilder &BaseDiag = Diag;
- BaseDiag << Value;
- return Diag;
- }
+ /// @}
- // 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 <typename T,
- typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>>
- const ImmediateDiagBuilder &operator<<(T &&V) const {
- const DiagnosticBuilder &BaseDiag = *this;
- BaseDiag << std::move(V);
- return *this;
- }
- };
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- /// 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
- };
+ /// \name Availability Attribute Handling
+ /// Implementations are in SemaAvailability.cpp
+ /// @{
- SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
- const FunctionDecl *Fn, Sema &S);
- SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
- SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;
+public:
+ /// Issue any -Wunguarded-availability warnings in \c FD
+ void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
- // The copy and move assignment operator is defined as deleted pending
- // further motivation.
- SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete;
- SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete;
+ void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
- ~SemaDiagnosticBuilder();
+ /// Retrieve the current function, if any, that should be analyzed for
+ /// potential availability violations.
+ sema::FunctionScopeInfo *getCurFunctionAvailabilityContext();
- bool isImmediate() const { return ImmediateDiag.has_value(); }
+ void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ bool ObjCPropertyAccess,
+ bool AvoidPartialAvailabilityChecks = false,
+ ObjCInterfaceDecl *ClassReceiver = nullptr);
- /// 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(); }
+ /// @}
- template <typename T>
- 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;
- }
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- // 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 <typename T,
- typename = std::enable_if_t<!std::is_lvalue_reference<T>::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;
- }
-
- 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;
- }
+ /// \name Casts
+ /// Implementations are in SemaCast.cpp
+ /// @{
- void AddFixItHint(const FixItHint &Hint) const {
- if (ImmediateDiag)
- ImmediateDiag->AddFixItHint(Hint);
- else if (PartialDiagId)
- S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint);
- }
+public:
+ static bool isCast(CheckedConversionKind CCK) {
+ return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
+ CCK == CCK_OtherCast;
+ }
- 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); }
+ /// 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);
- private:
- Sema &S;
- SourceLocation Loc;
- unsigned DiagID;
- const FunctionDecl *Fn;
- bool ShowCallStack;
+ ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ TypeSourceInfo *Ty,
+ Expr *E,
+ SourceRange AngleBrackets,
+ SourceRange Parens);
- // Invariant: At most one of these Optionals has a value.
- // FIXME: Switch these to a Variant once that exists.
- std::optional<ImmediateDiagBuilder> ImmediateDiag;
- std::optional<unsigned> PartialDiagId;
- };
+ ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
+ ExprResult Operand,
+ SourceLocation RParenLoc);
- /// Is the last error level diagnostic immediate. This is used to determined
- /// whether the next info diagnostic should be immediate.
- bool IsLastErrorImmediate = true;
+ ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI,
+ Expr *Operand, SourceLocation RParenLoc);
- /// Emit a diagnostic.
- SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
- bool DeferHint = false);
+ // Checks that reinterpret casts don't have undefined behavior.
+ void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
+ bool IsDereference, SourceRange Range);
- /// Emit a partial diagnostic.
- SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
- bool DeferHint = false);
+ // 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);
- /// Build a partial diagnostic.
- PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+ // 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);
- /// Whether deferrable diagnostics should be deferred.
- bool DeferDiags = false;
+ ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *Ty,
+ SourceLocation RParenLoc,
+ Expr *Op);
- /// RAII class to control scope of DeferDiags.
- class DeferDiagsRAII {
- Sema &S;
- bool SavedDeferDiags = false;
+ ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type,
+ SourceLocation LParenLoc,
+ Expr *CastExpr,
+ SourceLocation RParenLoc);
- public:
- DeferDiagsRAII(Sema &S, bool DeferDiags)
- : S(S), SavedDeferDiags(S.DeferDiags) {
- S.DeferDiags = DeferDiags;
- }
- ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
- };
+ /// @}
- /// Whether uncompilable error has occurred. This includes error happens
- /// in deferred diagnostics.
- bool hasUncompilableErrorOccurred() const;
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- bool findMacroSpelling(SourceLocation &loc, StringRef name);
+ /// \name Extra Semantic Checking
+ /// Implementations are in SemaChecking.cpp
+ /// @{
- /// 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;
+public:
+ /// Used to change context to isConstantEvaluated without pushing a heavy
+ /// ExpressionEvaluationContextRecord object.
+ bool isConstantEvaluatedOverride = false;
- /// Calls \c Lexer::getLocForEndOfToken()
- SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
+ bool isConstantEvaluatedContext() const {
+ return currentEvaluationContext().isConstantEvaluated() ||
+ isConstantEvaluatedOverride;
+ }
- /// Retrieve the module loader associated with the preprocessor.
- ModuleLoader &getModuleLoader() const;
+ SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const;
- /// Invent a new identifier for parameters of abbreviated templates.
- IdentifierInfo *
- InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
- unsigned Index);
+ 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
+ };
- void emitAndClearUnusedLocalTypedefWarnings();
+ // Used to grab the relevant information from a FormatAttr and a
+ // FunctionDeclaration.
+ struct FormatStringInfo {
+ unsigned FormatIdx;
+ unsigned FirstDataArg;
+ FormatArgumentPassingKind ArgPassingKind;
+ };
- private:
- /// Function or variable declarations to be checked for whether the deferred
- /// diagnostics should be emitted.
- llvm::SmallSetVector<Decl *, 4> DeclsToCheckForDeferredDiags;
+ static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+ bool IsVariadic, FormatStringInfo *FSI);
- public:
- // Emit all deferred diagnostics.
- void emitDeferredDiags();
+ // Used by C++ template instantiation.
+ ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+ ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
- 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
+ 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);
- void ActOnStartOfTranslationUnit();
- void ActOnEndOfTranslationUnit();
- void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind);
+ bool FormatStringHasSArg(const StringLiteral *FExpr);
- void CheckDelegatingCtorCycles();
+ static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
- Scope *getScopeForContext(DeclContext *Ctx);
+ void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
+ BinaryOperatorKind Opcode);
- void PushFunctionScope();
- void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
- sema::LambdaScopeInfo *PushLambdaScope();
+ /// 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);
- /// 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);
+ struct TypeTagData {
+ TypeTagData() {}
- void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
- RecordDecl *RD, CapturedRegionKind K,
- unsigned OpenMPCaptureLevel = 0);
+ TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) :
+ Type(Type), LayoutCompatible(LayoutCompatible),
+ MustBeNull(MustBeNull)
+ {}
- /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
- /// time after they've been popped.
- class PoppedFunctionScopeDeleter {
- Sema *Self;
+ QualType Type;
- public:
- explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {}
- void operator()(sema::FunctionScopeInfo *Scope) const;
+ /// 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;
};
- using PoppedFunctionScopePtr =
- std::unique_ptr<sema::FunctionScopeInfo, PoppedFunctionScopeDeleter>;
-
- PoppedFunctionScopePtr
- PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
- const Decl *D = nullptr,
- QualType BlockType = QualType());
-
- sema::FunctionScopeInfo *getCurFunction() const {
- return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
- }
+ /// A pair of ArgumentKind identifier and magic value. This uniquely
+ /// identifies the magic value.
+ typedef std::pair<const IdentifierInfo *, uint64_t> TypeTagMagicValue;
- sema::FunctionScopeInfo *getEnclosingFunction() const;
+ /// 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 setFunctionHasBranchIntoScope();
- void setFunctionHasBranchProtectedScope();
- void setFunctionHasIndirectGoto();
- void setFunctionHasMustTail();
+ /// 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 PushCompoundScope(bool IsStmtExpr);
- void PopCompoundScope();
+ /// 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<void(Expr *, RecordDecl *, FieldDecl *, CharUnits)>
+ Action);
- sema::CompoundScopeInfo &getCurCompoundScope() const;
+ enum class AtomicArgumentOrder { API, AST };
+ ExprResult
+ BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
+ SourceLocation RParenLoc, MultiExprArg Args,
+ AtomicExpr::AtomicOp Op,
+ AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API);
- bool hasAnyUnrecoverableErrorsInThisFunction() const;
+ /// Check to see if a given expression could have '.c_str()' called on it.
+ bool hasCStrMethod(const Expr *E);
- /// Retrieve the current block, if any.
- sema::BlockScopeInfo *getCurBlock();
+ void DiagnoseAlwaysNonNullPointer(Expr *E,
+ Expr::NullPointerConstantKind NullType,
+ bool IsEqual, SourceRange Range);
- /// 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;
+ bool CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
+ bool CheckParameterNames);
- /// 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 CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
- /// Retrieve the current generic lambda info, if any.
- sema::LambdaScopeInfo *getCurGenericLambda();
+ /// 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);
- /// Retrieve the current captured region, if any.
- sema::CapturedRegionScopeInfo *getCurCapturedRegion();
+ /// checkUnsafeAssigns - Check whether +1 expr is being assigned
+ /// to weak/__unsafe_unretained type.
+ bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
- /// Retrieve the current function, if any, that should be analyzed for
- /// potential availability violations.
- sema::FunctionScopeInfo *getCurFunctionAvailabilityContext();
+ /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
+ /// to weak/__unsafe_unretained expression.
+ void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
- /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
- SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+ /// 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);
- /// Called before parsing a function declarator belonging to a function
- /// declaration.
- void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
- unsigned TemplateParameterDepth);
+ /// 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);
- /// Called after parsing a function declarator belonging to a function
- /// declaration.
- void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
+ /// Warn if a value is moved to itself.
+ void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+ SourceLocation OpLoc);
- void ActOnComment(SourceRange Comment);
+ // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+ enum VariadicCallType {
+ VariadicFunction,
+ VariadicBlock,
+ VariadicMethod,
+ VariadicConstructor,
+ VariadicDoesNotApply
+ };
- //===--------------------------------------------------------------------===//
- // Type Analysis / Processing: SemaType.cpp.
- //
+private:
+ void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
+ const ArraySubscriptExpr *ASE = nullptr,
+ bool AllowOnePastEnd = true, bool IndexNegated = false);
+ void CheckArrayAccess(const Expr *E);
- 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 CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto);
+ bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
+ ArrayRef<const Expr *> Args);
+ bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
+ const FunctionProtoType *Proto);
+ bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto);
+ void CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
+ ArrayRef<const Expr *> Args,
+ const FunctionProtoType *Proto, SourceLocation Loc);
- QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
- SourceLocation AttrLoc);
+ void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
- /// Same as above, but constructs the AddressSpace index if not provided.
- QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
- SourceLocation AttrLoc);
+ void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
+ StringRef ParamName, QualType ArgTy, QualType ParamTy);
- CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
- bool CheckRebuiltStmtAttributes(ArrayRef<const Attr *> Attrs);
+ void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
+ const Expr *ThisArg, ArrayRef<const Expr *> Args,
+ bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
+ VariadicCallType CallType);
- bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
+ bool CheckObjCString(Expr *Arg);
+ ExprResult CheckOSLogFormatStringArg(Expr *Arg);
- bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
+ ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
+ unsigned BuiltinID, CallExpr *TheCall);
- /// Check an argument list for placeholders that we won't try to
- /// handle later.
- bool CheckArgsForPlaceholders(MultiExprArg args);
+ bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+ CallExpr *TheCall);
- /// 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<QualType> ParamTypes,
- SourceLocation Loc, DeclarationName Entity,
- const FunctionProtoType::ExtProtoInfo &EPI);
+ void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
- 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);
+ 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<std::tuple<int, int, int>, 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);
- TypeSourceInfo *GetTypeForDeclarator(Declarator &D);
- TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
+ 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<int> ArgNums);
+ bool CheckX86BuiltinTileDuplicate(CallExpr *TheCall, ArrayRef<int> ArgNums);
+ bool CheckX86BuiltinTileRangeAndDuplicate(CallExpr *TheCall,
+ ArrayRef<int> 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);
- /// 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);
+ 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);
- TypeResult ActOnTypeName(Declarator &D);
+ 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);
- /// The parser has parsed the context-sensitive type 'instancetype'
- /// in an Objective-C message declaration. Return the appropriate type.
- ParsedType ActOnObjCInstanceType(SourceLocation Loc);
+ bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
- /// Abstract class used to diagnose incomplete types.
- struct TypeDiagnoser {
- TypeDiagnoser() {}
+ bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
+ bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall);
+ bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
+ bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);
- virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
- virtual ~TypeDiagnoser() {}
- };
+ bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall);
- 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();}
+ // Matrix builtin handling.
+ ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
+ ExprResult CallResult);
+ ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
+ ExprResult CallResult);
+ ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
+ ExprResult CallResult);
- template <typename... Ts> class BoundTypeDiagnoser : public TypeDiagnoser {
- protected:
- unsigned DiagID;
- std::tuple<const Ts &...> Args;
+ // 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);
- template <std::size_t... Is>
- void emit(const SemaDiagnosticBuilder &DB,
- std::index_sequence<Is...>) const {
- // Apply all tuple elements to the builder in order.
- bool Dummy[] = {false, (DB << getPrintable(std::get<Is>(Args)))...};
- (void)Dummy;
- }
+ bool CheckFormatArguments(const FormatAttr *Format,
+ ArrayRef<const Expr *> Args, bool IsCXXMember,
+ VariadicCallType CallType, SourceLocation Loc,
+ SourceRange Range,
+ llvm::SmallBitVector &CheckedVarArgs);
+ bool CheckFormatArguments(ArrayRef<const Expr *> Args,
+ FormatArgumentPassingKind FAPK, unsigned format_idx,
+ unsigned firstDataArg, FormatStringType Type,
+ VariadicCallType CallType, SourceLocation Loc,
+ SourceRange range,
+ llvm::SmallBitVector &CheckedVarArgs);
- public:
- BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
- : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
- assert(DiagID != 0 && "no diagnostic for type diagnoser");
- }
+ void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
- void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
- const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
- emit(DB, std::index_sequence_for<Ts...>());
- DB << T;
- }
- };
+ void CheckAbsoluteValueFunction(const CallExpr *Call,
+ const FunctionDecl *FDecl);
- /// 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);
+ void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
- /// 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 <typename... Ts>
- class SizelessTypeDiagnoser : public BoundTypeDiagnoser<Ts...> {
- public:
- SizelessTypeDiagnoser(unsigned DiagID, const Ts &... Args)
- : BoundTypeDiagnoser<Ts...>(DiagID, Args...) {}
+ void CheckMemaccessArguments(const CallExpr *Call,
+ unsigned BId,
+ IdentifierInfo *FnName);
- void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
- const SemaDiagnosticBuilder &DB = S.Diag(Loc, this->DiagID);
- this->emit(DB, std::index_sequence_for<Ts...>());
- DB << T->isSizelessType() << T;
- }
- };
+ void CheckStrlcpycatArguments(const CallExpr *Call,
+ IdentifierInfo *FnName);
- enum class CompleteTypeKind {
- /// Apply the normal rules for complete types. In particular,
- /// treat all sizeless types as incomplete.
- Normal,
+ void CheckStrncatArguments(const CallExpr *Call,
+ IdentifierInfo *FnName);
- /// Relax the normal rules for complete types so that they include
- /// sizeless built-in types.
- AcceptSizeless,
+ void CheckFreeArguments(const CallExpr *E);
- // FIXME: Eventually we should flip the default to Normal and opt in
- // to AcceptSizeless rather than opt out of it.
- Default = AcceptSizeless
- };
+ void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
+ SourceLocation ReturnLoc,
+ bool isObjCMethod = false,
+ const AttrVec *Attrs = nullptr,
+ const FunctionDecl *FD = nullptr);
- enum class AcceptableKind { Visible, Reachable };
+ void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+ void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
+ void CheckForIntOverflow(const Expr *E);
+ void CheckUnsequencedOperations(const Expr *E);
-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);
+ /// 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);
- bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
- CompleteTypeKind Kind, TypeDiagnoser *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);
- struct ModuleScope {
- SourceLocation BeginLoc;
- clang::Module *Module = nullptr;
- VisibleModuleSet OuterVisibleModules;
- };
- /// The modules we're currently parsing.
- llvm::SmallVector<ModuleScope, 16> ModuleScopes;
+ void CheckTCBEnforcement(const SourceLocation CallExprLoc,
+ const NamedDecl *Callee);
- /// For an interface unit, this is the implicitly imported interface unit.
- clang::Module *ThePrimaryInterface = nullptr;
+ /// A map from magic value to type information.
+ std::unique_ptr<llvm::DenseMap<TypeTagMagicValue, TypeTagData>>
+ TypeTagForDatatypeMagicValues;
- /// 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;
+ /// 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<const Expr *> ExprArgs,
+ SourceLocation CallSiteLoc);
- /// 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;
-
- /// Namespace definitions that we will export when they finish.
- llvm::SmallPtrSet<const NamespaceDecl*, 8> 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<const FunctionDecl *, 8> PendingInlineFuncDecls;
-
- /// Helper function to judge if we are in module purview.
- /// Return false if we are not in a module.
- bool isCurrentModulePurview() const;
+ /// 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);
- /// Enter the scope of the explicit global module fragment.
- Module *PushGlobalModuleFragment(SourceLocation BeginLoc);
- /// Leave the scope of the explicit global module fragment.
- void PopGlobalModuleFragment();
+ /// Helper class that collects misaligned member designations and
+ /// their location info for delayed diagnostics.
+ struct MisalignedMember {
+ Expr *E;
+ RecordDecl *RD;
+ ValueDecl *MD;
+ CharUnits Alignment;
- /// Enter the scope of an implicit global module fragment.
- Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc);
- /// Leave the scope of an implicit global module fragment.
- void PopImplicitGlobalModuleFragment();
+ 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()) {}
- VisibleModuleSet VisibleModules;
+ 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<MisalignedMember, 4> MisalignedMembers;
- /// Cache for module units which is usable for current module.
- llvm::DenseSet<const Module *> UsableModuleUnitsCache;
+ /// Adds an expression to the set of gathered misaligned members.
+ void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
+ CharUnits Alignment);
+ /// @}
- bool isUsableModule(const Module *M);
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
+ /// \name C++ Coroutines
+ /// Implementations are in SemaCoroutine.cpp
+ /// @{
public:
- /// Get the module unit whose scope we are currently within.
- Module *getCurrentModule() const {
- return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
- }
+ /// The C++ "std::coroutine_traits" template, which is defined in
+ /// \<coroutine_traits>
+ ClassTemplateDecl *StdCoroutineTraitsCache;
- /// Is the module scope we are an implementation unit?
- bool currentModuleIsImplementation() const {
- return ModuleScopes.empty()
- ? false
- : ModuleScopes.back().Module->isModuleImplementation();
- }
+ 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);
- /// Is the module scope we are in a C++ Header Unit?
- bool currentModuleIsHeaderUnit() const {
- return ModuleScopes.empty() ? false
- : ModuleScopes.back().Module->isHeaderUnit();
- }
+ 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);
- /// Get the module owning an entity.
- Module *getOwningModule(const Decl *Entity) {
- return Entity->getOwningModule();
- }
+ // 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);
- /// Make a merged definition of an existing hidden definition \p ND
- /// visible at the specified location.
- void makeMergedDefinitionVisible(NamedDecl *ND);
+ /// @}
- bool isModuleVisible(const Module *M, bool ModulePrivate = 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);
- }
+ /// \name C++ Scope Specifiers
+ /// Implementations are in SemaCXXScopeSpec.cpp
+ /// @{
- /// Determine whether a declaration is visible to name lookup.
- bool isVisible(const NamedDecl *D) {
- return D->isUnconditionallyVisible() ||
- isAcceptableSlow(D, AcceptableKind::Visible);
- }
+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);
- /// Determine whether a declaration is reachable.
- bool isReachable(const NamedDecl *D) {
- // All visible declarations are reachable.
- return D->isUnconditionallyVisible() ||
- isAcceptableSlow(D, AcceptableKind::Reachable);
- }
+ DeclContext *computeDeclContext(QualType T);
+ DeclContext *computeDeclContext(const CXXScopeSpec &SS,
+ bool EnteringContext = false);
+ bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
+ CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
- /// Determine whether a declaration is acceptable (visible/reachable).
- bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) {
- return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D);
- }
+ /// 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);
- /// Determine whether any declaration of an entity is visible.
- bool
- hasVisibleDeclaration(const NamedDecl *D,
- llvm::SmallVectorImpl<Module *> *Modules = nullptr) {
- return isVisible(D) || hasVisibleDeclarationSlow(D, Modules);
- }
+ /// 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 hasVisibleDeclarationSlow(const NamedDecl *D,
- llvm::SmallVectorImpl<Module *> *Modules);
- /// Determine whether any declaration of an entity is reachable.
- bool
- hasReachableDeclaration(const NamedDecl *D,
- llvm::SmallVectorImpl<Module *> *Modules = nullptr) {
- return isReachable(D) || hasReachableDeclarationSlow(D, Modules);
- }
- bool hasReachableDeclarationSlow(
- const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
+ bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
+ bool *CanCorrect = nullptr);
+ NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
- bool hasVisibleMergedDefinition(const NamedDecl *Def);
- bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def);
+ /// 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;
- /// 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);
+ /// The identifier preceding the '::'.
+ IdentifierInfo *Identifier;
- /// 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<NamedDecl*>(D), &Hidden);
- }
+ /// The location of the identifier.
+ SourceLocation IdentifierLoc;
- /// 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);
- }
+ /// The location of the '::'.
+ SourceLocation CCLoc;
- bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
- AcceptableKind Kind,
- bool OnlyNeedComplete = false);
- bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) {
- NamedDecl *Hidden;
- return hasAcceptableDefinition(D, &Hidden, Kind);
- }
+ /// 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) {
+ }
- /// Determine if the template parameter \p D has a visible default argument.
- bool
- hasVisibleDefaultArgument(const NamedDecl *D,
- llvm::SmallVectorImpl<Module *> *Modules = nullptr);
- /// Determine if the template parameter \p D has a reachable default argument.
- bool hasReachableDefaultArgument(
- const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
- /// Determine if the template parameter \p D has a reachable default argument.
- bool hasAcceptableDefaultArgument(const NamedDecl *D,
- llvm::SmallVectorImpl<Module *> *Modules,
- Sema::AcceptableKind Kind);
+ NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
+ SourceLocation ColonColonLoc, QualType ObjectType)
+ : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
+ IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {
+ }
+ };
- /// 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<Module *> *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<Module *> *Modules = nullptr);
-
- /// 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<Module *> *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<Module *> *Modules = nullptr);
-
- /// 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<const NamedDecl *> Equiv);
-
- bool isUsualDeallocationFunction(const CXXMethodDecl *FD);
-
- // 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);
-
- 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 <typename... Ts>
- bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID,
- const Ts &...Args) {
- BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
- return RequireCompleteType(Loc, T, Diagnoser);
- }
-
- template <typename... Ts>
- bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID,
- const Ts &... Args) {
- SizelessTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
- return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser);
- }
+ bool BuildCXXNestedNameSpecifier(Scope *S,
+ NestedNameSpecInfo &IdInfo,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ NamedDecl *ScopeLookupResult,
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon = nullptr,
+ bool OnlyNamespace = false);
- /// 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.
+ /// The parser has parsed a nested-name-specifier 'identifier::'.
///
- /// 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);
+ /// \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);
- void completeExprArrayBound(Expr *E);
- bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind,
- TypeDiagnoser &Diagnoser);
- bool RequireCompleteExprType(Expr *E, unsigned DiagID);
+ /// 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);
- template <typename... Ts>
- bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) {
- BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
- return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser);
- }
+ bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
+ const DeclSpec &DS,
+ SourceLocation ColonColonLoc);
- template <typename... Ts>
- bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
- const Ts &... Args) {
- SizelessTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
- return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
- }
+ bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
+ const DeclSpec &DS,
+ SourceLocation ColonColonLoc,
+ QualType Type);
- bool RequireLiteralType(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser);
- bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID);
+ bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+ NestedNameSpecInfo &IdInfo,
+ bool EnteringContext);
- template <typename... Ts>
- bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID,
- const Ts &...Args) {
- BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
- return RequireLiteralType(Loc, T, Diagnoser);
- }
+ /// 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);
- QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
- const CXXScopeSpec &SS, QualType T,
- TagDecl *OwnedTagDecl = nullptr);
+ /// 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);
- // Returns the underlying type of a decltype with the given expression.
- QualType getDecltypeForExpr(Expr *E);
+ bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
- 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);
+ /// 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);
- QualType ActOnPackIndexingType(QualType Pattern, Expr *IndexExpr,
- SourceLocation Loc,
- SourceLocation EllipsisLoc);
- QualType BuildPackIndexingType(QualType Pattern, Expr *IndexExpr,
- SourceLocation Loc, SourceLocation EllipsisLoc,
- bool FullySubstituted = false,
- ArrayRef<QualType> Expansions = {});
+ /// 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);
- 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);
+ /// @}
- //===--------------------------------------------------------------------===//
- // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
//
- struct SkipBodyInfo {
- SkipBodyInfo() = default;
- bool ShouldSkip = false;
- bool CheckSameAsPrevious = false;
- NamedDecl *Previous = nullptr;
- NamedDecl *New = nullptr;
- };
+ /// \name Declarations
+ /// Implementations are in SemaDecl.cpp
+ /// @{
- DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
+public:
+ IdentifierResolver IdResolver;
- void DiagnoseUseOfUnimplementedSelectors();
+ /// The index of the first InventedParameterInfo that refers to the current
+ /// context.
+ unsigned InventedParameterInfosStart = 0;
- ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
+ /// A RAII object to temporarily push a declaration context.
+ class ContextRAII {
+ private:
+ Sema &S;
+ DeclContext *SavedContext;
+ ProcessingContextState SavedContextState;
+ QualType SavedCXXThisTypeOverride;
+ unsigned SavedFunctionScopesStart;
+ unsigned SavedInventedParameterInfosStart;
+
+ 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();
+ }
+
+ void pop() {
+ if (!SavedContext) return;
+ S.CurContext = SavedContext;
+ S.DelayedDiagnostics.popUndelayed(SavedContextState);
+ S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
+ S.FunctionScopesStart = SavedFunctionScopesStart;
+ S.InventedParameterInfosStart = SavedInventedParameterInfosStart;
+ SavedContext = nullptr;
+ }
+
+ ~ContextRAII() {
+ pop();
+ }
+ };
+
+ void DiagnoseInvalidJumps(Stmt *Body);
+
+ /// 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<const NamedDecl *, 4> TypoCorrectedFunctionDefinitions;
+
+ /// A cache of the flags available in enumerations with the flag_bits
+ /// attribute.
+ mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache;
+
+ /// 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<WeakInfo, 1u>,
+ llvm::SmallDenseSet<WeakInfo, 2u, WeakInfo::DenseMapInfoByAliasOnly>>>
+ WeakUndeclaredIdentifiers;
+
+ /// 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<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers;
+
+ /// Set containing all typedefs that are likely unused.
+ llvm::SmallSetVector<const TypedefNameDecl *, 4>
+ UnusedLocalTypedefNameCandidates;
+
+ typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2>
+ UnusedFileScopedDeclsType;
+
+ /// 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;
+
+ typedef LazyVector<VarDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadTentativeDefinitions, 2, 2>
+ TentativeDefinitionsType;
+
+ /// All the tentative definitions encountered in the TU.
+ TentativeDefinitionsType TentativeDefinitions;
+
+ /// All the external declarations encoutered and used in the TU.
+ SmallVector<VarDecl *, 4> ExternalDeclarations;
+
+ /// Generally null except when we temporarily switch decl contexts,
+ /// like in \see ActOnObjCTemporaryExitContainerContext.
+ DeclContext *OriginalLexicalContext;
+
+ /// Is the module scope we are in a C++ Header Unit?
+ bool currentModuleIsHeaderUnit() const {
+ return ModuleScopes.empty() ? false
+ : ModuleScopes.back().Module->isHeaderUnit();
+ }
+
+ /// Get the module owning an entity.
+ Module *getOwningModule(const Decl *Entity) {
+ return Entity->getOwningModule();
+ }
+
+ struct SkipBodyInfo {
+ SkipBodyInfo() = default;
+ bool ShouldSkip = false;
+ bool CheckSameAsPrevious = false;
+ NamedDecl *Previous = nullptr;
+ NamedDecl *New = nullptr;
+ };
+
+ DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
+
+ ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
Scope *S, CXXScopeSpec *SS = nullptr,
bool isClassName = false, bool HasTrailingDot = false,
ParsedType ObjectType = nullptr,
@@ -3011,9 +3084,6 @@ class Sema final {
// diagnoseExprIntendedAsTemplateName.
return false;
}
- void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
- SourceLocation Less,
- SourceLocation Greater);
void warnOnReservedIdentifier(const NamedDecl *D);
@@ -3030,16 +3100,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);
@@ -3056,13 +3117,6 @@ 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<const NamedDecl *, const NamedDecl *> ShadowingDecls;
-
-public:
- void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
void handleTagNumbering(const TagDecl *Tag, Scope *TagScope);
void setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
TypedefNameDecl *NewTD);
@@ -3076,21 +3130,11 @@ class Sema final {
Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
bool &AddToScope, ArrayRef<BindingDecl *> 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,
TypeSourceInfo *TInfo,
@@ -3099,22 +3143,6 @@ class Sema final {
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<CXXMethodDecl*> &OverloadedMethods);
- void NoteHiddenVirtualMethods(CXXMethodDecl *MD,
- SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
// Returns true if the function declaration is a redeclaration
bool CheckFunctionDeclaration(Scope *S,
FunctionDecl *NewFD, LookupResult &Previous,
@@ -3146,17 +3174,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.
@@ -3204,13 +3221,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);
@@ -3247,14 +3262,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<ObjCMethodDecl>(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
@@ -3275,10 +3282,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);
@@ -3300,164 +3303,36 @@ class Sema final {
DiagnoseSizeOfParametersAndReturnValue(ArrayRef<ParmVarDecl *> Parameters,
QualType ReturnTy, NamedDecl *D);
- void DiagnoseInvalidJumps(Stmt *Body);
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();
+ /// Called once it is known whether
+ /// a tag declaration is an anonymous union or struct.
+ void ActOnDefinedDeclarationSpecifier(Decl *D);
-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);
+ void DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record);
- /// 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<Module *> 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);
-
- void DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record);
-
- Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
- RecordDecl *Record);
+ Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+ RecordDecl *Record);
/// Common ways to introduce type names without a tag for use in diagnostics.
/// Keep in sync with err_tag_reference_non_tag.
@@ -3511,24 +3386,6 @@ 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<Decl *> &Decls);
Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
Declarator &D, Expr *BitfieldWidth);
@@ -3536,12 +3393,6 @@ class Sema final {
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);
FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
TypeSourceInfo *TInfo,
@@ -3553,64 +3404,6 @@ class Sema final {
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<DefaultedComparisonKind>(Comparison) != DefaultedComparisonKind::None;
- }
-
- explicit operator bool() const {
- return isSpecialMember() || isComparison();
- }
-
- CXXSpecialMember asSpecialMember() const { return static_cast<CXXSpecialMember>(SpecialMember); }
- DefaultedComparisonKind asComparison() const { return static_cast<DefaultedComparisonKind>(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<Decl *> &AllIvarDecls);
@@ -3632,20 +3425,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 <typename T,
- typename = std::enable_if_t<std::is_base_of<NamedDecl, T>::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.
@@ -3723,25 +3502,6 @@ class Sema final {
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);
@@ -3783,9496 +3543,9349 @@ 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);
+ static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
- 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<void(SourceLocation Loc, PartialDiagnostic PD)>
+ 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<const Decl*, 4> ParsingInitForAutoVars;
- bool FunctionParamTypesAreEqual(ArrayRef<QualType> Old,
- ArrayRef<QualType> 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<FunctionDecl *> &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<Decl *, 4> 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<const NamedDecl *, const NamedDecl *> 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;
+ /// @}
- virtual ~ContextualImplicitConverter() {}
- };
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- class ICEConvertDiagnoser : public ContextualImplicitConverter {
- bool AllowScopedEnumerations;
+ /// \name Declaration Attribute Handling
+ /// Implementations are in SemaDeclAttr.cpp
+ /// @{
- public:
- ICEConvertDiagnoser(bool AllowScopedEnumerations,
- bool Suppress, bool SuppressConversion)
- : ContextualImplicitConverter(Suppress, SuppressConversion),
- AllowScopedEnumerations(AllowScopedEnumerations) {}
+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,
- /// Match an integral or (possibly scoped) enumeration type.
- bool match(QualType T) override;
+ /// The availability attribute was applied using '#pragma clang attribute'.
+ AP_PragmaClangAttribute = 1,
- SemaDiagnosticBuilder
- diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override {
- return diagnoseNotInt(S, Loc, T);
- }
+ /// The availability attribute for a specific platform was inferred from
+ /// an availability attribute for another platform.
+ AP_InferredFromOtherPlatform = 2
+ };
- /// Emits a diagnostic complaining that the expression does not have
- /// integral or enumeration type.
- virtual SemaDiagnosticBuilder
- diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
+ /// Describes the reason a calling convention specification was ignored, used
+ /// for diagnostics.
+ enum class CallingConventionIgnoredReason {
+ ForThisTarget = 0,
+ VariadicFunction,
+ ConstructorDestructor,
+ BuiltinFunction
};
- /// Perform a contextual implicit conversion.
- ExprResult PerformContextualImplicitConversion(
- SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
+ /// 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<Decl*,2> WeakTopLevelDecl;
+ /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
+ SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
- enum ObjCSubscriptKind {
- OS_Array,
- OS_Dictionary,
- OS_Error
- };
- ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
+ typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadExtVectorDecls, 2, 2>
+ ExtVectorDeclsType;
- // 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);
+ /// 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;
- ExprResult PerformObjectMemberConversion(Expr *From,
- NestedNameSpecifier *Qualifier,
- NamedDecl *FoundDecl,
- NamedDecl *Member);
+ 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);
- // Members have to be NamespaceDecl* or TranslationUnitDecl*.
- // TODO: make this is a typesafe union.
- typedef llvm::SmallSetVector<DeclContext *, 16> AssociatedNamespaceSet;
- typedef llvm::SmallSetVector<CXXRecordDecl *, 16> AssociatedClassSet;
+ /// 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);
- using ADLCallKind = CallExpr::ADLCallKind;
+ /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
+ /// declaration.
+ void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+ Expr *OE);
- void AddOverloadCandidate(
- FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> 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<Expr *> 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<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversion = false,
- OverloadCandidateParamOrder PO = {});
- void
- AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
- CXXRecordDecl *ActingContext, QualType ObjectType,
- Expr::Classification ObjectClassification,
- ArrayRef<Expr *> 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<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions = false,
- bool PartialOverloading = false,
- OverloadCandidateParamOrder PO = {});
- void AddTemplateOverloadCandidate(
- FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
- TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> 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<QualType> ParamTypes,
- ArrayRef<Expr *> 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<Expr *> Args,
- OverloadCandidateSet& CandidateSet);
- void AddNonMemberOperatorCandidates(
- const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
- void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
- SourceLocation OpLoc, ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- OverloadCandidateParamOrder PO = {});
- void AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- bool IsAssignmentOperator = false,
- unsigned NumContextualBoolArguments = 0);
- void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
- SourceLocation OpLoc, ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet);
- void AddArgumentDependentLookupCandidates(DeclarationName Name,
- SourceLocation Loc,
- ArrayRef<Expr *> Args,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- OverloadCandidateSet& CandidateSet,
- bool PartialOverloading = false);
+ /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
+ /// declaration.
+ void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *ParamExpr);
- // 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);
+ bool CheckAttrTarget(const ParsedAttr &CurrAttr);
+ bool CheckAttrNoArgs(const ParsedAttr &CurrAttr);
- // 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);
+ 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);
- /// 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<Expr *> Args,
- bool MissingImplicitThis = false);
+ llvm::Error isValidSectionSpecifier(StringRef Str);
+ bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
+ CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef Name);
- /// Find the failed Boolean condition within a given Boolean
- /// constant expression, and describe it with a string.
- std::pair<Expr *, std::string> findFailedBooleanCondition(Expr *Cond);
+ 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<SmallString<64>> &StringsBuffer);
- /// 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<const Expr *> Args,
- SourceLocation Loc);
+ ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef NewUserDiagnostic);
+ FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
+ IdentifierInfo *Format, int FormatIdx,
+ int FirstArg);
- /// 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);
+ /// 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);
- /// 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());
+ /// AddAlignValueAttr - Adds an align_value attribute to a particular
+ /// declaration.
+ void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
- // [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);
+ /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
+ void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef Annot, MutableArrayRef<Expr *> Args);
- FunctionDecl *
- ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
- QualType TargetType,
- bool Complain,
- DeclAccessPair &Found,
- bool *pHadMultipleCandidates = nullptr);
+ bool checkMSInheritanceAttrOnDefinition(
+ CXXRecordDecl *RD, SourceRange Range, bool BestCase,
+ MSInheritanceModel SemanticSpelling);
- FunctionDecl *
- resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult);
+ void CheckAlignasUnderalignment(Decl *D);
- bool resolveAndFixAddressOfSingleOverloadCandidate(
- ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
+ /// 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);
- FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
- OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr,
- TemplateSpecCandidateSet *FailedTSC = nullptr);
+ enum CUDAFunctionTarget {
+ CFT_Device,
+ CFT_Global,
+ CFT_Host,
+ CFT_HostDevice,
+ CFT_InvalidTarget
+ };
- bool ResolveAndFixSingleFunctionTemplateSpecialization(
- ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
- bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(),
- QualType DestTypeForComplaining = QualType(),
- unsigned DiagIDForComplaining = 0);
+ /// 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 FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
- FunctionDecl *Fn);
- ExprResult FixOverloadedFunctionReference(ExprResult,
- DeclAccessPair FoundDecl,
- FunctionDecl *Fn);
+ void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
+ ParameterABI ABI);
+ bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
- void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- bool PartialOverloading = false);
- void AddOverloadedCallCandidates(
- LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs,
- ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet);
+ /// Create an CUDALaunchBoundsAttr attribute.
+ CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI,
+ Expr *MaxThreads,
+ Expr *MinBlocks,
+ Expr *MaxBlocks);
- // An enum used to represent the different possible results of building a
- // range-based for loop.
- enum ForRangeStatus {
- FRS_Success,
- FRS_NoViableFunction,
- FRS_DiagnosticIssued
- };
-
- ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
- SourceLocation RangeLoc,
- const DeclarationNameInfo &NameInfo,
- LookupResult &MemberLookup,
- OverloadCandidateSet *CandidateSet,
- Expr *Range, ExprResult *CallExpr);
+ /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
+ /// declaration.
+ void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
- ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
- UnresolvedLookupExpr *ULE,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation RParenLoc,
- Expr *ExecConfig,
- bool AllowTypoCorrection=true,
- bool CalleesAddressIsTaken=false);
+ enum class RetainOwnershipKind {NS, CF, OS};
+ void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
+ RetainOwnershipKind K, bool IsTemplateInstantiation);
- bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
- MultiExprArg Args, SourceLocation RParenLoc,
- OverloadCandidateSet *CandidateSet,
- ExprResult *Result);
+ bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
- ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
- NestedNameSpecifierLoc NNSLoc,
- DeclarationNameInfo DNI,
- const UnresolvedSetImpl &Fns,
- bool PerformADL = true);
+ /// 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 CreateOverloadedUnaryOp(SourceLocation OpLoc,
- UnaryOperatorKind Opc,
- const UnresolvedSetImpl &Fns,
- Expr *input, bool RequiresADL = true);
+ UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
- void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
- OverloadedOperatorKind Op,
- const UnresolvedSetImpl &Fns,
- ArrayRef<Expr *> 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);
+ 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);
- ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
- SourceLocation RLoc, Expr *Base,
- MultiExprArg Args);
+ WebAssemblyImportNameAttr *mergeImportNameAttr(
+ Decl *D, const WebAssemblyImportNameAttr &AL);
+ WebAssemblyImportModuleAttr *mergeImportModuleAttr(
+ Decl *D, const WebAssemblyImportModuleAttr &AL);
- 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);
+ /// Create an AMDGPUWavesPerEUAttr attribute.
+ AMDGPUFlatWorkGroupSizeAttr *
+ CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,
+ Expr *Max);
- ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- bool *NoArrowOperatorFound = nullptr);
+ /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
+ /// attribute to a particular declaration.
+ void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *Min, Expr *Max);
- /// 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);
+ /// Create an AMDGPUWavesPerEUAttr attribute.
+ AMDGPUWavesPerEUAttr *
+ CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min,
+ Expr *Max);
- /// Helpers for dealing with blocks and functions.
- bool CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters,
- bool CheckParameterNames);
- void CheckCXXDefaultArguments(FunctionDecl *FD);
- void CheckExtraCXXDefaultArguments(Declarator &D);
- Scope *getNonFieldDeclScope(Scope *S);
+ /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
+ /// particular declaration.
+ void addAMDGPUWavesPerEUAttr(Decl *D, 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.
- //@{
+ 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);
- /// 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
- };
+ bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD);
- /// 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
- };
+ EnforceTCBAttr *mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL);
+ EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D,
+ const EnforceTCBLeafAttr &AL);
- 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<Decl>(CurContext)
- ->getOwningModuleForLinkage(/*IgnoreLinkage*/true))
- return ForVisibleRedeclaration;
- return ForExternalRedeclaration;
- }
+ // Helper for delayed processing of attributes.
+ void ProcessDeclAttributeDelayed(Decl *D,
+ const ParsedAttributesView &AttrList);
- /// 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,
- };
+ // Options for ProcessDeclAttributeList().
+ struct ProcessDeclAttributeOptions {
+ ProcessDeclAttributeOptions()
+ : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {}
- SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D,
- CXXSpecialMember SM,
- bool ConstArg,
- bool VolatileArg,
- bool RValueThis,
- bool ConstThis,
- bool VolatileThis);
+ ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) {
+ ProcessDeclAttributeOptions Result = *this;
+ Result.IncludeCXX11Attributes = Val;
+ return Result;
+ }
- typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
- typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
- TypoRecoveryCallback;
+ ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) {
+ ProcessDeclAttributeOptions Result = *this;
+ Result.IgnoreTypeAttributes = Val;
+ return Result;
+ }
-private:
- bool CppLookupName(LookupResult &R, Scope *S);
+ // Should C++11 attributes be processed?
+ bool IncludeCXX11Attributes;
- struct TypoExprState {
- std::unique_ptr<TypoCorrectionConsumer> Consumer;
- TypoDiagnosticGenerator DiagHandler;
- TypoRecoveryCallback RecoveryHandler;
- TypoExprState();
- TypoExprState(TypoExprState &&other) noexcept;
- TypoExprState &operator=(TypoExprState &&other) noexcept;
+ // 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;
};
- /// The set of unhandled TypoExprs and their associated state.
- llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
+ void ProcessDeclAttributeList(Scope *S, Decl *D,
+ const ParsedAttributesView &AttrList,
+ const ProcessDeclAttributeOptions &Options =
+ ProcessDeclAttributeOptions());
+ bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
+ const ParsedAttributesView &AttrList);
- /// Creates a new TypoExpr AST node.
- TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
- TypoDiagnosticGenerator TDG,
- TypoRecoveryCallback TRC, SourceLocation TypoLoc);
+ void checkUnusedDeclAttributes(Declarator &D);
- // 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<NamespaceDecl*, bool> KnownNamespaces;
+ NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
+ SourceLocation Loc);
+ void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W);
- /// Whether we have already loaded known namespaces from an extenal
- /// source.
- bool LoadedExternalKnownNamespaces;
+ 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 CorrectTypo and CorrectTypoDelayed used to create and
- /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
- /// should be skipped entirely.
- std::unique_ptr<TypoCorrectionConsumer>
- makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo,
- Sema::LookupNameKind LookupKind, Scope *S,
- CXXScopeSpec *SS,
- CorrectionCandidateCallback &CCC,
- DeclContext *MemberContext, bool EnteringContext,
- const ObjCObjectPointerType *OPT,
- bool ErrorRecovery);
+ void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
-public:
- const TypoExprState &getTypoExprState(TypoExpr *TE) const;
+ void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
- /// Clears the state of the given TypoExpr.
- void clearDelayedTypo(TypoExpr *TE);
+ /// @}
- /// 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 LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
- UnresolvedSetImpl &Functions);
+ /// \name C++ Declarations
+ /// Implementations are in SemaDeclCXX.cpp
+ /// @{
- LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = SourceLocation());
+public:
+ void CheckDelegatingCtorCycles();
- 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);
+ /// Called before parsing a function declarator belonging to a function
+ /// declaration.
+ void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
+ unsigned TemplateParameterDepth);
- bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
- bool IsUDSuffix);
- LiteralOperatorLookupResult
- LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys,
- bool AllowRaw, bool AllowTemplate,
- bool AllowStringTemplate, bool DiagnoseMissing,
- StringLiteral *StringLit = nullptr);
- bool isKnownName(StringRef name);
+ /// Called after parsing a function declarator belonging to a function
+ /// declaration.
+ void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
- /// 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);
+ // 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);
- // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
- bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
+ NamespaceDecl *getStdNamespace() const;
+ NamespaceDecl *getOrCreateStdNamespace();
- void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
- ArrayRef<Expr *> Args, ADLResult &Functions);
+ CXXRecordDecl *getStdBadAlloc() const;
+ EnumDecl *getStdAlignValT() const;
- 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);
+ ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl,
+ const IdentifierInfo *MemberOrBase);
- enum CorrectTypoKind {
- CTK_NonError, // CorrectTypo used in a non error recovery situation.
- CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
+ 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,
};
- 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);
+ /// 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);
- 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);
+ /// 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);
- /// 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.
+ /// 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<ExprResult(Expr *)> Filter =
- [](Expr *E) -> ExprResult { return E; });
-
- ExprResult CorrectDelayedTyposInExpr(
- ExprResult ER, VarDecl *InitDecl = nullptr,
- bool RecoverUncorrectedTypos = false,
- llvm::function_ref<ExprResult(Expr *)> Filter =
- [](Expr *E) -> ExprResult { return E; }) {
- return ER.isInvalid()
- ? ER
- : CorrectDelayedTyposInExpr(ER.get(), InitDecl,
- RecoverUncorrectedTypos, Filter);
- }
+ /// \returns The instantiated template, or null on error.
+ QualType BuildStdInitializerList(QualType Element, SourceLocation Loc);
- void diagnoseTypo(const TypoCorrection &Correction,
- const PartialDiagnostic &TypoDiag,
- bool ErrorRecovery = true);
-
- void diagnoseTypo(const TypoCorrection &Correction,
- const PartialDiagnostic &TypoDiag,
- const PartialDiagnostic &PrevNote,
- bool ErrorRecovery = true);
+ /// Determine whether Ctor is an initializer-list constructor, as
+ /// defined in [dcl.init.list]p2.
+ bool isInitListConstructor(const FunctionDecl *Ctor);
- void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F);
+ Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc, CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ const ParsedAttributesView &AttrList);
- void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
- ArrayRef<Expr *> Args,
- AssociatedNamespaceSet &AssociatedNamespaces,
- AssociatedClassSet &AssociatedClasses);
+ void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
- void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
- bool ConsiderLinkage, bool AllowInlineNamespace);
+ Decl *ActOnNamespaceAliasDef(Scope *CurScope,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident);
- 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;
+ 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 DiagnoseAmbiguousLookup(LookupResult &Result);
- //@}
+ 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);
- /// Attempts to produce a RecoveryExpr after some AST node cannot be created.
- ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
- ArrayRef<Expr *> SubExprs,
- QualType T = QualType());
+ 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<NamedDecl *> Expansions);
- 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);
+ bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
- // More parsing and symbol table subroutines.
+ /// 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);
- 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);
+ 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);
- // Options for ProcessDeclAttributeList().
- struct ProcessDeclAttributeOptions {
- ProcessDeclAttributeOptions()
- : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {}
+ /// 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);
- ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) {
- ProcessDeclAttributeOptions Result = *this;
- Result.IncludeCXX11Attributes = Val;
- return Result;
- }
+ /// 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);
- ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) {
- ProcessDeclAttributeOptions Result = *this;
- Result.IgnoreTypeAttributes = Val;
- return Result;
- }
+ // 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);
- // Should C++11 attributes be processed?
- bool IncludeCXX11Attributes;
+ ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr,
+ SourceLocation InitLoc);
- // 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;
- };
+ /// FinalizeVarWithDestructor - Prepare for calling destructor on the
+ /// constructed variable.
+ void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
- void ProcessDeclAttributeList(Scope *S, Decl *D,
- const ParsedAttributesView &AttrList,
- const ProcessDeclAttributeOptions &Options =
- ProcessDeclAttributeOptions());
- bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
- const ParsedAttributesView &AttrList);
+ /// 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<CanQualType, 4> ExceptionsSeen;
+ SmallVector<QualType, 4> Exceptions;
- void checkUnusedDeclAttributes(Declarator &D);
+ void ClearExceptions() {
+ ExceptionsSeen.clear();
+ Exceptions.clear();
+ }
- /// 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);
+ public:
+ explicit ImplicitExceptionSpecification(Sema &Self)
+ : Self(&Self), ComputedEST(EST_BasicNoexcept) {
+ if (!Self.getLangOpts().CPlusPlus11)
+ ComputedEST = EST_DynamicNone;
+ }
- /// 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);
+ /// Get the computed exception specification type.
+ ExceptionSpecificationType getExceptionSpecType() const {
+ assert(!isComputedNoexcept(ComputedEST) &&
+ "noexcept(expr) should not be a possible result");
+ return ComputedEST;
+ }
- bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
+ /// The number of exceptions in the exception specification.
+ unsigned size() const { return Exceptions.size(); }
- /// 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<SmallString<64>> &StringsBuffer);
- bool checkMSInheritanceAttrOnDefinition(
- CXXRecordDecl *RD, SourceRange Range, bool BestCase,
- MSInheritanceModel SemanticSpelling);
+ /// The set of exceptions in the exception specification.
+ const QualType *data() const { return Exceptions.data(); }
- void CheckAlignasUnderalignment(Decl *D);
+ /// Integrate another called method into the collected data.
+ void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
- bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
- const AttributeCommonInfo &A);
- bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
- const AttributeCommonInfo &A);
+ /// Integrate an invoked expression into the collected data.
+ void CalledExpr(Expr *E) { CalledStmt(E); }
- bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD);
+ /// Integrate an invoked statement into the collected data.
+ void CalledStmt(Stmt *S);
- /// 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);
+ /// 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 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);
+ /// Evaluate the implicit exception specification for a defaulted
+ /// special member function.
+ void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD);
- /// 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;
+ /// Check the given exception-specification and update the
+ /// exception specification information with the results.
+ void checkExceptionSpecification(bool IsTopLevel,
+ ExceptionSpecificationType EST,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr,
+ SmallVectorImpl<QualType> &Exceptions,
+ FunctionProtoType::ExceptionSpecInfo &ESI);
- /// 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.
+ /// 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<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr);
+
+ /// Kinds of C++ special members.
+ enum CXXSpecialMember {
+ CXXDefaultConstructor,
+ CXXCopyConstructor,
+ CXXMoveConstructor,
+ CXXCopyAssignment,
+ CXXMoveAssignment,
+ CXXDestructor,
+ CXXInvalid
+ };
+
+ class InheritedConstructorInfo;
+
+ /// 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);
+
+ /// Produce notes explaining why a defaulted function was defined as deleted.
+ void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD);
+
+ /// Declare the implicit default constructor for the given class.
///
- /// \param Nullability The nullability specifier to add.
+ /// \param ClassDecl The class declaration into which the implicit
+ /// default constructor will be added.
///
- /// \param DiagLoc The location to use for diagnostics.
+ /// \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 AllowArrayTypes Whether to accept nullability specifiers on an
- /// array type (e.g., because it will decay to a pointer).
+ /// \param ClassDecl The class declaration into which the implicit
+ /// destructor will be added.
///
- /// \param OverrideExisting Whether to override an existing, locally-specified
- /// nullability specifier rather than complaining about the conflict.
+ /// \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.
///
- /// \returns true if nullability cannot be applied, false otherwise.
- bool CheckImplicitNullabilityTypeSpecifier(QualType &Type,
- NullabilityKind Nullability,
- SourceLocation DiagLoc,
- bool AllowArrayTypes,
- bool OverrideExisting);
+ /// 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);
- /// Process the attributes before creating an attributed statement. Returns
- /// the semantic attributes that have been processed.
- void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs,
- SmallVectorImpl<const Attr *> &OutAttrs);
+ /// Define the specified inheriting constructor.
+ void DefineInheritingConstructor(SourceLocation UseLoc,
+ CXXConstructorDecl *Constructor);
- void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
- ObjCMethodDecl *MethodDecl,
- bool IsProtocolMethodDecl);
+ /// 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);
- void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
- ObjCMethodDecl *Overridden,
- bool IsProtocolMethodDecl);
+ /// DefineImplicitCopyConstructor - Checks for feasibility of
+ /// defining this constructor as the copy constructor.
+ void DefineImplicitCopyConstructor(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 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);
- typedef llvm::SmallPtrSet<Selector, 8> SelectorSet;
+ /// DefineImplicitMoveConstructor - Checks for feasibility of
+ /// defining this constructor as the move constructor.
+ void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
- /// 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 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);
- /// 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 copy assignment operator.
+ void DefineImplicitCopyAssignment(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);
+ /// 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);
- /// Diagnose any null-resettable synthesized setters.
- void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl);
+ /// Defines an implicitly-declared move assignment operator.
+ void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
- /// 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 a completed declaration of an implicit special member.
+ void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
- /// 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);
+ /// Determine whether the given function is an implicitly-deleted
+ /// special member function.
+ bool isImplicitlyDeleted(FunctionDecl *FD);
- /// 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 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);
- /// 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;
+ /// Whether this' shows up in the exception specification of a static
+ /// member function.
+ bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
- /// 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);
+ /// Check whether 'this' shows up in the attributes of the given
+ /// static member function.
+ ///
+ /// \returns true if an error occurred.
+ bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
- /// 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 CheckImmediateEscalatingFunctionDefinition(
+ FunctionDecl *FD, const sema::FunctionScopeInfo *FSI);
- /// 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);
+ void DiagnoseImmediateEscalatingReason(FunctionDecl *FD);
- void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+ bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+ QualType DeclInitType, MultiExprArg ArgsPtr,
+ SourceLocation Loc,
+ SmallVectorImpl<Expr *> &ConvertedArgs,
+ bool AllowExplicit = false,
+ bool IsListInitialization = false);
- void DiagnoseMissingDesignatedInitOverrides(
- const ObjCImplementationDecl *ImplD,
- const ObjCInterfaceDecl *IFD);
+ /// 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 DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
+ /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+ /// initializer for the declaration 'Dcl'.
+ void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
- enum MethodMatchStrategy {
- MMS_loose,
- MMS_strict
- };
+ /// 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);
- /// 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);
+ /// 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);
- /// 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);
+ Decl *ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ Expr *LangStr,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc);
- /// 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);
+ //===--------------------------------------------------------------------===//
+ // 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);
- /// Add the given method to the list of globally-known methods.
- void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
+ bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
+ SourceLocation ColonLoc,
+ const ParsedAttributesView &Attrs);
- /// Returns default addr space for method qualifiers.
- LangAS getDefaultCXXMethodAddrSpace() const;
+ NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
+ Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Expr *BitfieldWidth, const VirtSpecifiers &VS,
+ InClassInitStyle InitStyle);
-private:
- /// AddMethodToGlobalPool - Add an instance or factory method to the global
- /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
- void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+ void ActOnStartCXXInClassMemberInitializer();
+ void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
+ SourceLocation EqualLoc,
+ Expr *Init);
- /// 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 ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
+ SourceLocation IdLoc,
+ SourceLocation LParenLoc,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc,
+ 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<ObjCMethodDecl*>& Methods,
- bool InstanceFirst, bool CheckTheOther,
- const ObjCObjectType *TypeBound = nullptr);
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
+ SourceLocation IdLoc,
+ Expr *InitList,
+ SourceLocation EllipsisLoc);
- bool
- AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
- SourceRange R, bool receiverIdOrClass,
- SmallVectorImpl<ObjCMethodDecl*>& Methods);
+ MemInitResult BuildMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
+ SourceLocation IdLoc,
+ Expr *Init,
+ SourceLocation EllipsisLoc);
- void
- DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
- Selector Sel, SourceRange R,
- bool receiverIdOrClass);
+ MemInitResult BuildMemberInitializer(ValueDecl *Member,
+ Expr *Init,
+ SourceLocation IdLoc);
-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<ObjCMethodDecl*>& Methods);
+ MemInitResult BuildBaseInitializer(QualType BaseType,
+ TypeSourceInfo *BaseTInfo,
+ Expr *Init,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc);
+ MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
+ Expr *Init,
+ CXXRecordDecl *ClassDecl);
- /// 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();
- }
+ bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+ CXXCtorInitializer *Initializer);
-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);
- }
+ bool SetCtorInitializers(
+ CXXConstructorDecl *Constructor, bool AnyErrors,
+ ArrayRef<CXXCtorInitializer *> Initializers = std::nullopt);
- /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
- void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
- AddMethodToGlobalPool(Method, impl, /*instance*/false);
- }
+ void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
- /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
- /// pool.
- void AddAnyMethodToGlobalPool(Decl *D);
- /// 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);
- }
+ /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
+ /// mark all the non-trivial destructors of its members and bases as
+ /// referenced.
+ void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
+ CXXRecordDecl *Record);
- /// 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);
- }
+ /// 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<const RecordType *> *DirectVirtualBases = nullptr);
- const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
- QualType ObjectType=QualType());
- /// LookupImplementedMethodInGlobalPool - Returns the method which has an
- /// implementation.
- ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
+ /// 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);
- /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
- /// initialization.
- void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
- SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ /// 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<CXXRecordDecl*, SourceLocation> VTableUse;
- //===--------------------------------------------------------------------===//
- // Statement Parsing Callbacks: SemaStmt.cpp.
-public:
- class FullExprArg {
- public:
- FullExprArg() : E(nullptr) { }
- FullExprArg(Sema &actions) : E(nullptr) { }
+ /// The list of vtables that are required but have not yet been
+ /// materialized.
+ SmallVector<VTableUse, 16> VTableUses;
- ExprResult release() {
- return E;
- }
+ /// 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<CXXRecordDecl *, bool> VTablesUsed;
- Expr *get() const { return E; }
+ /// Load any externally-stored vtable uses.
+ void LoadExternalVTableUses();
- Expr *operator->() {
- return E;
- }
+ /// Note that the vtable for the given class was used at the
+ /// given location.
+ void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+ bool DefinitionRequired = false);
- 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;
+ /// Mark the exception specifications of all virtual member functions
+ /// in the given class as needed.
+ void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
+ const CXXRecordDecl *RD);
- explicit FullExprArg(Expr *expr) : E(expr) {}
+ /// MarkVirtualMembersReferenced - Will mark all members of the given
+ /// CXXRecordDecl referenced.
+ void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD,
+ bool ConstexprOnly = false);
- Expr *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();
- 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 AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
- StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
- StmtResult ActOnExprStmtError();
+ void ActOnMemInitializers(Decl *ConstructorDecl,
+ SourceLocation ColonLoc,
+ ArrayRef<CXXCtorInitializer*> MemInits,
+ bool AnyErrors);
- StmtResult ActOnNullStmt(SourceLocation SemiLoc,
- bool HasLeadingEmptyMacro = 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);
- void ActOnStartOfCompoundStmt(bool IsStmtExpr);
- void ActOnAfterCompoundStatementLeadingPragmas();
- void ActOnFinishOfCompoundStmt();
- StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
- ArrayRef<Stmt *> Elts, bool isStmtExpr);
+ void referenceDLLExportedClassMethods();
- /// 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 propagateDLLAttrToBaseClassTemplate(
+ CXXRecordDecl *Class, Attr *ClassAttr,
+ ClassTemplateSpecializationDecl *BaseTemplateSpec,
+ SourceLocation BaseLoc);
- ~CompoundScopeRAII() {
- S.ActOnFinishOfCompoundStmt();
- }
+ void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
- private:
- Sema &S;
- };
+ /// 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);
- /// 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; }
- };
+ void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
+ Decl *TagDecl, SourceLocation LBrac,
+ SourceLocation RBrac,
+ const ParsedAttributesView &AttrList);
+ void ActOnFinishCXXMemberDecls();
+ void ActOnFinishCXXNonNestedClass();
- 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);
+ void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
+ unsigned ActOnReenterTemplateScope(Decl *Template,
+ llvm::function_ref<Scope *()> 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);
- StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
- SourceLocation ColonLoc,
- Stmt *SubStmt, Scope *CurScope);
- StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
- SourceLocation ColonLoc, Stmt *SubStmt);
+ 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);
- StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
- ArrayRef<const Attr *> Attrs, Stmt *SubStmt);
- StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList,
- Stmt *SubStmt);
+ Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+ MultiTemplateParamsArg TemplateParams);
+ NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParams);
- class ConditionResult;
+ 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 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);
+ void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
- 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);
+ bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
+ CXXSpecialMember CSM,
+ SourceLocation DefaultLoc);
+ void CheckDelayedMemberExceptionSpecs();
- 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
+ /// 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 ActOnCXXForRangeStmt(
- Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc,
- Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection,
- SourceLocation RParenLoc, BuildForRangeKind Kind,
- ArrayRef<MaterializeTemporaryExpr *> 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<MaterializeTemporaryExpr *> LifetimeExtendTemps = {});
- StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
-
- 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);
+ bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
+ DefaultedComparisonKind DCK);
+ void DeclareImplicitEqualityComparison(CXXRecordDecl *RD,
+ FunctionDecl *Spaceship);
+ void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
+ DefaultedComparisonKind DCK);
- void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
- CapturedRegionKind Kind, unsigned NumParams);
- typedef std::pair<StringRef, QualType> CapturedParamNameType;
- void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
- CapturedRegionKind Kind,
- ArrayRef<CapturedParamNameType> Params,
- unsigned OpenMPCaptureLevel = 0);
- StmtResult ActOnCapturedRegionEnd(Stmt *S);
- void ActOnCapturedRegionError();
- RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
- SourceLocation Loc,
- unsigned NumParams);
+ 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);
- struct NamedReturnInfo {
- const VarDecl *Candidate;
+ //===--------------------------------------------------------------------===//
+ // C++ Derived Classes
+ //
- enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
- Status S;
+ /// ActOnBaseSpecifier - Parsed a base specifier
+ CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc);
- 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);
+ BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+ const ParsedAttributesView &Attrs, bool Virtual,
+ AccessSpecifier Access, ParsedType basetype,
+ SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc);
- ExprResult
- PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
- const NamedReturnInfo &NRInfo, Expr *Value,
- bool SupressSimplerImplicitMoves = false);
+ bool AttachBaseSpecifiers(CXXRecordDecl *Class,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
+ void ActOnBaseSpecifiers(Decl *ClassDecl,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
- 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 IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
+ bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+ CXXBasePaths &Paths);
- 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);
+ // FIXME: I don't like this name.
+ void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
- 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<Token> AsmToks,
- StringRef AsmString,
- unsigned NumOutputs, unsigned NumInputs,
- ArrayRef<StringRef> Constraints,
- ArrayRef<StringRef> Clobbers,
- ArrayRef<Expr*> Exprs,
- SourceLocation EndLoc);
- LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
- SourceLocation Location,
- bool AlwaysCreate);
+ 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);
- VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
- SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- bool Invalid = false);
+ std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
- Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
+ bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
- StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
- Decl *Parm, Stmt *Body);
+ /// CheckOverridingFunctionReturnType - Checks whether the return types are
+ /// covariant, according to C++ [class.virtual]p5.
+ bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
- StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
+ // Check that the overriding method has no explicit object parameter.
+ bool CheckExplicitObjectOverride(CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
- StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
- MultiStmtArg Catch, Stmt *Finally);
+ bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
- 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);
+ /// CheckOverrideControl - Check C++11 override control semantics.
+ void CheckOverrideControl(NamedDecl *D);
- StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
+ /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
+ /// not used in the declaration of an overriding method.
+ void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent);
- VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
- SourceLocation StartLoc,
- SourceLocation IdLoc,
- IdentifierInfo *Id);
+ /// 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);
- Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+ enum AbstractDiagSelID {
+ AbstractNone = -1,
+ AbstractReturnType,
+ AbstractParamType,
+ AbstractVariableType,
+ AbstractFieldType,
+ AbstractIvarType,
+ AbstractSynthesizedIvarType,
+ AbstractArrayType
+ };
- StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
- Decl *ExDecl, Stmt *HandlerBlock);
- StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
- ArrayRef<Stmt *> Handlers);
+ struct TypeDiagnoser;
- 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 isAbstractType(SourceLocation Loc, QualType T);
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser);
+ template <typename... Ts>
+ bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
+ const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireNonAbstractType(Loc, T, Diagnoser);
+ }
- void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+ void DiagnoseAbstractType(const CXXRecordDecl *RD);
- bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+ //===--------------------------------------------------------------------===//
+ // C++ Overloaded Operators [C++ 13.5]
+ //
- /// If it's a file scoped decl that must warn if not used, keep track
- /// of it.
- void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
+ bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
- typedef llvm::function_ref<void(SourceLocation Loc, PartialDiagnostic PD)>
- DiagReceiverTy;
+ bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
- /// 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);
+ /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
+ /// found in an explicit(bool) specifier.
+ ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
- /// If VD is set but not otherwise used, diagnose, for a parameter or a
- /// variable.
- void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver);
+ /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
+ /// Returns true if the explicit specifier is now resolved.
+ bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
- /// 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);
+ DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
- /// 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);
+ // Emitting members of dllexported classes is delayed until the class
+ // (including field initializers) is fully parsed.
+ SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
+ SmallVector<CXXMethodDecl*, 4> DelayedDllExportMemberFunctions;
- /// Warn if a value is moved to itself.
- void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
- SourceLocation OpLoc);
+ void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
+ bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
- /// 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);
+ /// Helpers for dealing with blocks and functions.
+ void CheckCXXDefaultArguments(FunctionDecl *FD);
+ void CheckExtraCXXDefaultArguments(Declarator &D);
- /// 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);
-
- ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
- return DelayedDiagnostics.push(pool);
+ CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) {
+ return getDefaultedFunctionKind(MD).asSpecialMember();
}
- void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
- typedef ProcessingContextState ParsingClassState;
- ParsingClassState PushParsingClass() {
- ParsingClassDepth++;
- return DelayedDiagnostics.pushUndelayed();
- }
- void PopParsingClass(ParsingClassState state) {
- ParsingClassDepth--;
- DelayedDiagnostics.popUndelayed(state);
- }
+ VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id);
- void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
- void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
- const ObjCInterfaceDecl *UnknownObjCClass,
- bool ObjCPropertyAccess,
- bool AvoidPartialAvailabilityChecks = false,
- ObjCInterfaceDecl *ClassReceiver = nullptr);
+ void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
- bool makeUnavailableInSystemHeader(SourceLocation loc,
- UnavailableAttr::ImplicitReason reason);
+ DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
+ unsigned TagSpec, SourceLocation TagLoc,
+ CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ const ParsedAttributesView &Attr,
+ MultiTemplateParamsArg TempParamLists);
- /// Issue any -Wunguarded-availability warnings in \c FD
- void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
+ MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
+ SourceLocation DeclStart, Declarator &D,
+ Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
+ AccessSpecifier AS,
+ const ParsedAttr &MSPropertyAttr);
- void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+ void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM);
- //===--------------------------------------------------------------------===//
- // Expression Parsing Callbacks: SemaExpr.cpp.
+ enum TrivialABIHandling {
+ /// The triviality of a method unaffected by "trivial_abi".
+ TAH_IgnoreTrivialABI,
- 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);
- }
+ /// The triviality of a method affected by "trivial_abi".
+ TAH_ConsiderTrivialABI
+ };
- bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> 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<Expr *> Args);
+ bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
+ TrivialABIHandling TAH = TAH_IgnoreTrivialABI,
+ bool Diagnose = false);
- 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();
+ /// For a defaulted function, the kind of defaulted function that it is.
+ class DefaultedFunctionKind {
+ unsigned SpecialMember : 8;
+ unsigned Comparison : 8;
- void DiscardCleanupsInEvaluationContext();
+ 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)) {}
- ExprResult TransformToPotentiallyEvaluated(Expr *E);
- TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
- ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
+ bool isSpecialMember() const { return SpecialMember != CXXInvalid; }
+ bool isComparison() const {
+ return static_cast<DefaultedComparisonKind>(Comparison) != DefaultedComparisonKind::None;
+ }
- ExprResult CheckUnevaluatedOperand(Expr *E);
- void CheckUnusedVolatileAssignment(Expr *E);
+ explicit operator bool() const {
+ return isSpecialMember() || isComparison();
+ }
- ExprResult ActOnConstantExpression(ExprResult Res);
+ CXXSpecialMember asSpecialMember() const { return static_cast<CXXSpecialMember>(SpecialMember); }
+ DefaultedComparisonKind asComparison() const { return static_cast<DefaultedComparisonKind>(Comparison); }
- // 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);
+ /// 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;
+ }
+ };
- ExprResult CheckLValueToRValueConversionOperand(Expr *E);
- void CleanupVarDeclMarking();
+ DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD);
- enum TryCaptureKind {
- TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
+ /// Handle a C++11 empty-declaration and attribute-declaration.
+ Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList,
+ SourceLocation SemiLoc);
+
+ 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
};
- /// 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);
+ bool CheckConstexprFunctionDefinition(const FunctionDecl *FD,
+ CheckConstexprKind Kind);
- /// Try to capture the given variable.
- bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
- TryCaptureKind Kind = TryCapture_Implicit,
- SourceLocation EllipsisLoc = SourceLocation());
+ void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
+ void FindHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
+ void NoteHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl*> &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);
- /// Checks if the variable must be captured.
- bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
+ void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc);
+ void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
- /// Given a variable, determine the type that a reference to that
- /// variable will have in the given scope.
- QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
+ void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind);
+ void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
+ ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
+ ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
- /// 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<const Expr *> StopAt = std::nullopt);
+ NamedDecl *
+ ActOnDecompositionDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists);
+ void DiagPlaceholderVariableDefinition(SourceLocation Loc);
+ bool DiagRedefinedPlaceholderFieldDecl(SourceLocation Loc,
+ RecordDecl *ClassDecl,
+ const IdentifierInfo *Name);
- /// 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);
+ void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD);
- /// Figure out if an expression could be turned into a call.
- bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
- UnresolvedSetImpl &NonTemplateOverloads);
+ /// 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<InventedTemplateParameterInfo, 4> InventedParameterInfos;
- /// Try to convert an expression \p E to type \p Ty. Returns the result of the
- /// conversion.
- ExprResult tryConvertExprToType(Expr *E, QualType Ty);
+ /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+ std::unique_ptr<CXXFieldCollector> FieldCollector;
- /// 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<const Stmt *> Stmts,
- const PartialDiagnostic &PD);
+ typedef llvm::SmallSetVector<const NamedDecl *, 16> NamedDeclSetType;
+ /// Set containing all declared private fields that are not used.
+ NamedDeclSetType UnusedPrivateFields;
- /// 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<const Stmt*> Stmts,
- const PartialDiagnostic &PD);
+ typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
- // Primary Expressions.
- SourceRange getExprRange(Expr *E) const;
+ /// 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<RecordDeclSetTy> PureVirtualClassDiagSet;
- ExprResult ActOnIdExpression(
- Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC = nullptr,
- bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
+ typedef LazyVector<CXXConstructorDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadDelegatingConstructors, 2, 2>
+ DelegatingCtorDeclsType;
- void DecomposeUnqualifiedId(const UnqualifiedId &Id,
- TemplateArgumentListInfo &Buffer,
- DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *&TemplateArgs);
+ /// All the delegating constructors seen so far in the file, used for
+ /// cycle detection at the end of the TU.
+ DelegatingCtorDeclsType DelegatingCtorDecls;
- bool DiagnoseDependentMemberLookup(const LookupResult &R);
+ /// The C++ "std" namespace, where the standard library resides.
+ LazyDeclPtr StdNamespace;
- bool
- DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
- CorrectionCandidateCallback &CCC,
- TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
- ArrayRef<Expr *> Args = std::nullopt,
- DeclContext *LookupCtx = nullptr,
- TypoExpr **Out = nullptr);
+ /// The C++ "std::initializer_list" template, which is defined in
+ /// \<initializer_list>.
+ ClassTemplateDecl *StdInitializerList;
- DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
- IdentifierInfo *II);
- ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
+ // Contains the locations of the beginning of unparsed default
+ // argument locations.
+ llvm::DenseMap<ParmVarDecl *, SourceLocation> UnparsedDefaultArgLocs;
- ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
- IdentifierInfo *II,
- bool AllowBuiltinCreation=false);
+ /// UndefinedInternals - all the used, undefined objects which require a
+ /// definition in this translation unit.
+ llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed;
- ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- bool isAddressOfOperand,
- const TemplateArgumentListInfo *TemplateArgs);
+ typedef llvm::PointerIntPair<CXXRecordDecl *, 3, CXXSpecialMember>
+ SpecialMemberDecl;
- /// 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);
+ /// 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<SpecialMemberDecl, 4> SpecialMembersBeingDeclared;
- 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);
+ void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD);
- ExprResult
- BuildAnonymousStructUnionMemberReference(
- const CXXScopeSpec &SS,
- SourceLocation nameLoc,
- IndirectFieldDecl *indirectField,
- DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
- Expr *baseObjectExpr = nullptr,
- SourceLocation opLoc = SourceLocation());
+ void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
- 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);
+ typedef ProcessingContextState ParsingClassState;
+ ParsingClassState PushParsingClass() {
+ ParsingClassDepth++;
+ return DelayedDiagnostics.pushUndelayed();
+ }
+ void PopParsingClass(ParsingClassState state) {
+ ParsingClassDepth--;
+ DelayedDiagnostics.popUndelayed(state);
+ }
- ExprResult
- BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
- const DeclarationNameInfo &NameInfo,
- bool IsAddressOfOperand, const Scope *S,
- TypeSourceInfo **RecoveryTSI = nullptr);
+private:
+ void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
+ QualType ResultTy,
+ ArrayRef<QualType> Args);
- ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
+ // 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 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);
+ ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+ CXXScopeSpec &SS,
+ ParsedType TemplateTypeTy,
+ IdentifierInfo *MemberOrBase);
- ExprResult BuildLiteralOperatorCall(LookupResult &R,
- DeclarationNameInfo &SuffixInfo,
- ArrayRef<Expr *> Args,
- SourceLocation LitEndLoc,
- TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+ /// Check if there is a field shadowing.
+ void CheckShadowInheritedFields(const SourceLocation &Loc,
+ DeclarationName FieldName,
+ const CXXRecordDecl *RD,
+ bool DeclIsField = true);
- // 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<Token> ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks);
+ /// @}
- ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK);
- ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
- ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
- SourceLocation LParen,
- SourceLocation RParen,
- TypeSourceInfo *TSI);
- ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc,
- SourceLocation LParen,
- SourceLocation RParen,
- ParsedType ParsedTy);
+ /// \name C++ Exception Specifications
+ /// Implementations are in SemaExceptionSpec.cpp
+ /// @{
- bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
+public:
+ /// All the overriding functions seen during a class definition
+ /// that had their exception spec checks delayed, plus the overridden
+ /// function.
+ SmallVector<std::pair<const CXXMethodDecl *, const CXXMethodDecl *>, 2>
+ DelayedOverridingExceptionSpecChecks;
- 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);
+ /// 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<std::pair<FunctionDecl *, FunctionDecl *>, 2>
+ DelayedEquivalentExceptionSpecChecks;
- /// ActOnStringLiteral - The specified tokens were lexed as pasted string
- /// fragments (e.g. "foo" "bar" L"baz").
- ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks,
- Scope *UDLScope = nullptr);
+ /// 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 ActOnUnevaluatedStringLiteral(ArrayRef<Token> StringToks);
+ /// Check the given noexcept-specifier, convert its expression, and compute
+ /// the appropriate ExceptionSpecificationType.
+ ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr,
+ ExceptionSpecificationType &EST);
- /// 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<ParsedType> ArgTypes,
- ArrayRef<Expr *> 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<TypeSourceInfo *> Types,
- ArrayRef<Expr *> 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);
-
- bool isQualifiedMemberAccess(Expr *E);
- bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
- const Expr *Op,
- const CXXMethodDecl *MD);
+ 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);
- QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+ bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
- bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+ /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
+ /// spec is a subset of base spec.
+ bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
- bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty,
- SourceLocation OpLoc, SourceRange R);
- bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo,
- SourceLocation OpLoc, SourceRange R);
+ /// @}
- 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);
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- ExprResult CheckPlaceholderExpr(Expr *E);
- bool CheckVecStepExpr(Expr *E);
+ /// \name Expressions
+ /// Implementations are in SemaExpr.cpp
+ /// @{
- 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);
+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,
- ExprResult ActOnPackIndexingExpr(Scope *S, Expr *PackExpression,
- SourceLocation EllipsisLoc,
- SourceLocation LSquareLoc, Expr *IndexExpr,
- SourceLocation RSquareLoc);
+ /// 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,
- ExprResult BuildPackIndexingExpr(Expr *PackExpression,
- SourceLocation EllipsisLoc, Expr *IndexExpr,
- SourceLocation RSquareLoc,
- ArrayRef<Expr *> ExpandedExprs = {},
- bool EmptyPack = false);
+ /// 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,
- ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
- tok::TokenKind Kind, Expr *Input);
+ /// 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 ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
- MultiExprArg ArgExprs,
- SourceLocation RLoc);
- ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
- Expr *Idx, SourceLocation RLoc);
+ /// 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 CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
- Expr *ColumnIdx,
- SourceLocation RBLoc);
+ /// 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,
- 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<Expr *> Dims,
- ArrayRef<SourceRange> Brackets);
+ /// 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,
- /// Data structure for iterator expression.
- struct OMPIteratorData {
- IdentifierInfo *DeclIdent = nullptr;
- SourceLocation DeclIdentLoc;
- ParsedType Type;
- OMPIteratorExpr::IteratorRange Range;
- SourceLocation AssignLoc;
- SourceLocation ColonLoc;
- SourceLocation SecColonLoc;
+ /// 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 ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
- SourceLocation LLoc, SourceLocation RLoc,
- ArrayRef<OMPIteratorData> Data);
+ /// 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<Expr *, 4>;
+ MaybeODRUseExprSet MaybeODRUseExprs;
- // 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;
- };
+ using ImmediateInvocationCandidate = llvm::PointerIntPair<ConstantExpr *, 1>;
- 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);
+ /// Data structure used to record current or nested
+ /// expression evaluation contexts.
+ struct ExpressionEvaluationContextRecord {
+ /// The expression evaluation context.
+ ExpressionEvaluationContext Context;
- 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);
+ /// Whether the enclosing context needed a cleanup.
+ CleanupInfo ParentCleanup;
- ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
- SourceLocation OpLoc,
- const CXXScopeSpec &SS, FieldDecl *Field,
- DeclAccessPair FoundDecl,
- const DeclarationNameInfo &MemberNameInfo);
+ /// The number of active cleanup objects when we entered
+ /// this expression evaluation context.
+ unsigned NumCleanupObjects;
- ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
+ /// The number of typos encountered during this expression evaluation
+ /// context (i.e. the number of TypoExprs created).
+ unsigned NumTypos;
- bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
- const CXXScopeSpec &SS,
- const LookupResult &R);
+ MaybeODRUseExprSet SavedMaybeODRUseExprs;
- ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType,
- bool IsArrow, SourceLocation OpLoc,
- const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
+ /// The lambdas that are present within this context, if it
+ /// is indeed an unevaluated context.
+ SmallVector<LambdaExpr *, 2> Lambdas;
- ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- UnqualifiedId &Member,
- Decl *ObjCImpDecl);
+ /// 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;
- 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);
+ /// 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<CallExpr *, 8> DelayedDecltypeCalls;
- void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
- bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
- FunctionDecl *FDecl,
- const FunctionProtoType *Proto,
- ArrayRef<Expr *> Args,
- SourceLocation RParenLoc,
- bool ExecConfig = false);
- void CheckStaticArrayArgument(SourceLocation CallLoc,
- ParmVarDecl *Param,
- const Expr *ArgExpr);
+ /// If we are processing a decltype type, a set of temporary binding
+ /// expressions for which we have deferred checking the destructor.
+ SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds;
- /// 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<Expr *> Arg, SourceLocation RParenLoc,
- Expr *Config = nullptr, bool IsExecConfig = false,
- ADLCallKind UsesADL = ADLCallKind::NotADL);
+ llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
- ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
- MultiExprArg ExecConfig,
- SourceLocation GGGLoc);
+ /// 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<Expr*, 2> VolatileAssignmentLHSs;
- 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);
+ /// Set of candidates for starting an immediate invocation.
+ llvm::SmallVector<ImmediateInvocationCandidate, 4>
+ ImmediateInvocationCandidates;
- /// Build an altivec or OpenCL literal.
- ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
- SourceLocation RParenLoc, Expr *E,
- TypeSourceInfo *TInfo);
+ /// Set of DeclRefExprs referencing a consteval function when used in a
+ /// context not already known to be immediately invoked.
+ llvm::SmallPtrSet<DeclRefExpr *, 4> ReferenceToConsteval;
- ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+ /// 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<MaterializeTemporaryExpr *, 8> ForRangeLifetimeExtendTemps;
- ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
- ParsedType Ty,
- SourceLocation RParenLoc,
- Expr *InitExpr);
+ /// \brief Describes whether we are in an expression constext which we have
+ /// to handle differently.
+ enum ExpressionKind {
+ EK_Decltype, EK_TemplateArgument, EK_Other
+ } ExprContext;
- ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
- TypeSourceInfo *TInfo,
- SourceLocation RParenLoc,
- Expr *LiteralExpr);
+ // 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 ActOnInitList(SourceLocation LBraceLoc,
- MultiExprArg InitArgList,
- SourceLocation RBraceLoc);
+ bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
- ExprResult BuildInitList(SourceLocation LBraceLoc,
- MultiExprArg InitArgList,
- SourceLocation RBraceLoc);
+ // 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;
- ExprResult ActOnDesignatedInitializer(Designation &Desig,
- SourceLocation EqualOrColonLoc,
- bool GNUSyntax,
- ExprResult Init);
+ /// 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;
-private:
- static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
+ /// 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<T> 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;
-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);
+ // 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");
+ }
- void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc);
+ SourceLocation Loc;
+ ValueDecl *Decl = nullptr;
+ DeclContext *Context = nullptr;
+ };
+ std::optional<InitializationContext> DelayedDefaultInitializationContext;
- /// 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);
+ 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) {}
- /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
- ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
- LabelDecl *TheDecl);
+ bool isUnevaluated() const {
+ return Context == ExpressionEvaluationContext::Unevaluated ||
+ Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
+ Context == ExpressionEvaluationContext::UnevaluatedList;
+ }
- 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();
+ bool isConstantEvaluated() const {
+ return Context == ExpressionEvaluationContext::ConstantEvaluated ||
+ Context == ExpressionEvaluationContext::ImmediateFunctionContext;
+ }
- // __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;
+ 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);
+ }
+
+ bool isDiscardedStatementContext() const {
+ return Context == ExpressionEvaluationContext::DiscardedStatement ||
+ (Context ==
+ ExpressionEvaluationContext::ImmediateFunctionContext &&
+ InDiscardedStatement);
+ }
};
- /// __builtin_offsetof(type, a.b[123][456].c)
- ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
- TypeSourceInfo *TInfo,
- ArrayRef<OffsetOfComponent> Components,
- SourceLocation RParenLoc);
- ExprResult ActOnBuiltinOffsetOf(Scope *S,
- SourceLocation BuiltinLoc,
- SourceLocation TypeLoc,
- ParsedType ParsedArgTy,
- ArrayRef<OffsetOfComponent> Components,
- SourceLocation RParenLoc);
+ const ExpressionEvaluationContextRecord ¤tEvaluationContext() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back();
+ };
- // __builtin_choose_expr(constExpr, expr1, expr2)
- ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
- Expr *CondExpr, Expr *LHSExpr,
- Expr *RHSExpr, SourceLocation RPLoc);
+ /// 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<const VarDecl *, int> RefsMinusAssignments;
- // __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);
+ /// Used to control the generation of ExprWithCleanups.
+ CleanupInfo Cleanup;
- // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
- // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
- ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind,
- SourceLocation BuiltinLoc,
- SourceLocation RPLoc);
+ /// ExprCleanupObjects - This is the stack of objects requiring
+ /// cleanup that are created by the current full expression.
+ SmallVector<ExprWithCleanups::CleanupObject, 8> ExprCleanupObjects;
- // Build a potentially resolved SourceLocExpr.
- ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
- SourceLocation BuiltinLoc, SourceLocation RPLoc,
- DeclContext *ParentContext);
+ // 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
+ };
- // __null
- ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+ 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);
+ }
- bool CheckCaseExpression(Expr *E);
+ bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
+ const ObjCInterfaceDecl *UnknownObjCClass = nullptr,
+ bool ObjCPropertyAccess = false,
+ bool AvoidPartialAvailabilityChecks = false,
+ ObjCInterfaceDecl *ClassReciever = nullptr,
+ bool SkipTrailingRequiresClause = false);
+ void NoteDeletedFunction(FunctionDecl *FD);
- /// Describes the result of an "if-exists" condition check.
- enum IfExistsResult {
- /// The symbol exists.
- IER_Exists,
+ void DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc,
+ ArrayRef<Expr *> Args);
- /// The symbol does not exist.
- IER_DoesNotExist,
+ 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();
- /// The name is a dependent name, so the results will differ
- /// from one instantiation to the next.
- IER_Dependent,
+ void DiscardCleanupsInEvaluationContext();
- /// An error occurred.
- IER_Error
- };
+ ExprResult TransformToPotentiallyEvaluated(Expr *E);
+ TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
+ ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
- IfExistsResult
- CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
- const DeclarationNameInfo &TargetNameInfo);
+ void CheckUnusedVolatileAssignment(Expr *E);
- IfExistsResult
- CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
- bool IsIfExists, CXXScopeSpec &SS,
- UnqualifiedId &Name);
+ ExprResult ActOnConstantExpression(ExprResult Res);
- StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
- bool IsIfExists,
- NestedNameSpecifierLoc QualifierLoc,
- DeclarationNameInfo NameInfo,
- Stmt *Nested);
- StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
- bool IsIfExists,
- CXXScopeSpec &SS, UnqualifiedId &Name,
- Stmt *Nested);
+ // 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);
- //===------------------------- "Block" Extension ------------------------===//
+ ExprResult CheckLValueToRValueConversionOperand(Expr *E);
+ void CleanupVarDeclMarking();
- /// ActOnBlockStart - This callback is invoked when a block literal is
- /// started.
- void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+ enum TryCaptureKind {
+ TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
+ };
- /// 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 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);
- /// 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);
+ /// Try to capture the given variable.
+ bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
+ TryCaptureKind Kind = TryCapture_Implicit,
+ SourceLocation EllipsisLoc = SourceLocation());
- /// 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);
+ /// Checks if the variable must be captured.
+ bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
- //===---------------------------- Clang Extensions ----------------------===//
+ /// Given a variable, determine the type that a reference to that
+ /// variable will have in the given scope.
+ QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
- /// __builtin_convertvector(...)
- ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
- SourceLocation BuiltinLoc,
- SourceLocation RParenLoc);
+ /// 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<const Expr *> StopAt = std::nullopt);
- //===---------------------------- OpenCL Features -----------------------===//
+ /// Try to convert an expression \p E to type \p Ty. Returns the result of the
+ /// conversion.
+ ExprResult tryConvertExprToType(Expr *E, QualType Ty);
- /// __builtin_astype(...)
- ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
- SourceLocation BuiltinLoc,
- SourceLocation RParenLoc);
- ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
- SourceLocation BuiltinLoc,
- SourceLocation RParenLoc);
+ /// 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<const Stmt *> Stmts,
+ const PartialDiagnostic &PD);
- //===---------------------------- HLSL Features -------------------------===//
- Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
- SourceLocation KwLoc, IdentifierInfo *Ident,
- SourceLocation IdentLoc, SourceLocation LBrace);
- void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
+ /// 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<const Stmt*> Stmts,
+ const PartialDiagnostic &PD);
- //===---------------------------- C++ Features --------------------------===//
+ // Primary Expressions.
+ SourceRange getExprRange(Expr *E) const;
- // 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 ActOnIdExpression(
+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
+ CorrectionCandidateCallback *CCC = nullptr,
+ bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
- NamespaceDecl *getStdNamespace() const;
- NamespaceDecl *getOrCreateStdNamespace();
-
- CXXRecordDecl *getStdBadAlloc() const;
- EnumDecl *getStdAlignValT() const;
+ void DecomposeUnqualifiedId(const UnqualifiedId &Id,
+ TemplateArgumentListInfo &Buffer,
+ DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *&TemplateArgs);
- ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl,
- const IdentifierInfo *MemberOrBase);
+ bool DiagnoseDependentMemberLookup(const LookupResult &R);
-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;
+ bool
+ DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ CorrectionCandidateCallback &CCC,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+ ArrayRef<Expr *> Args = std::nullopt,
+ DeclContext *LookupCtx = nullptr,
+ TypoExpr **Out = nullptr);
- ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
- CXXScopeSpec &SS,
- ParsedType TemplateTypeTy,
- IdentifierInfo *MemberOrBase);
+ DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
+ IdentifierInfo *II);
+ ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
-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,
- };
+ ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
+ IdentifierInfo *II,
+ bool AllowBuiltinCreation=false);
- /// 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);
+ /// 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);
- /// 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);
+ 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);
- /// 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 UseArgumentDependentLookup(const CXXScopeSpec &SS,
+ const LookupResult &R,
+ bool HasTrailingLParen);
- /// Determine whether Ctor is an initializer-list constructor, as
- /// defined in [dcl.init.list]p2.
- bool isInitListConstructor(const FunctionDecl *Ctor);
+ ExprResult
+ BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsAddressOfOperand, const Scope *S,
+ TypeSourceInfo **RecoveryTSI = nullptr);
- Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
- SourceLocation NamespcLoc, CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *NamespcName,
- const ParsedAttributesView &AttrList);
+ 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);
- void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
+ // 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<Token> ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks);
- Decl *ActOnNamespaceAliasDef(Scope *CurScope,
- SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *Ident);
+ ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK);
+ ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
+ ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
- 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);
+ ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation LParen,
+ SourceLocation RParen,
+ TypeSourceInfo *TSI);
+ ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+ SourceLocation LParen,
+ SourceLocation RParen,
+ ParsedType ParsedTy);
- 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 CheckLoopHintExpr(Expr *E, SourceLocation Loc);
- 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<NamedDecl *> Expansions);
+ 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 CheckInheritingConstructorUsingDecl(UsingDecl *UD);
+ /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+ /// fragments (e.g. "foo" "bar" L"baz").
+ ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks,
+ Scope *UDLScope = nullptr);
- /// 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 ActOnUnevaluatedStringLiteral(ArrayRef<Token> StringToks);
- 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);
+ /// 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<ParsedType> ArgTypes,
+ ArrayRef<Expr *> 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<TypeSourceInfo *> Types,
+ ArrayRef<Expr *> Exprs);
- /// 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);
+ // 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);
- /// 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);
+ bool isQualifiedMemberAccess(Expr *E);
+ bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
+ const Expr *Op,
+ const CXXMethodDecl *MD);
- // 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 ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr,
- SourceLocation InitLoc);
-
- ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
+ QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+ bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty,
+ SourceLocation OpLoc, SourceRange R);
+ bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo,
+ SourceLocation OpLoc, SourceRange R);
- /// 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 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);
- /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
- /// the default expr if needed.
- ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
- ParmVarDecl *Param, Expr *Init = nullptr);
+ ExprResult CheckPlaceholderExpr(Expr *E);
+ bool CheckVecStepExpr(Expr *E);
- /// FinalizeVarWithDestructor - Prepare for calling destructor on the
- /// constructed variable.
- void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+ bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
+ bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc,
+ SourceRange ExprRange,
+ UnaryExprOrTypeTrait ExprKind,
+ StringRef KWName);
- /// 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<CanQualType, 4> ExceptionsSeen;
- SmallVector<QualType, 4> Exceptions;
+ ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind, Expr *Input);
- void ClearExceptions() {
- ExceptionsSeen.clear();
- Exceptions.clear();
- }
+ ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+ MultiExprArg ArgExprs,
+ SourceLocation RLoc);
+ ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
- public:
- explicit ImplicitExceptionSpecification(Sema &Self)
- : Self(&Self), ComputedEST(EST_BasicNoexcept) {
- if (!Self.getLangOpts().CPlusPlus11)
- ComputedEST = EST_DynamicNone;
- }
+ ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
+ Expr *ColumnIdx,
+ SourceLocation RBLoc);
- /// Get the computed exception specification type.
- ExceptionSpecificationType getExceptionSpecType() const {
- assert(!isComputedNoexcept(ComputedEST) &&
- "noexcept(expr) should not be a possible result");
- return ComputedEST;
- }
+ 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<Expr *> Dims,
+ ArrayRef<SourceRange> Brackets);
- /// The number of exceptions in the exception specification.
- unsigned size() const { return Exceptions.size(); }
+ /// Data structure for iterator expression.
+ struct OMPIteratorData {
+ IdentifierInfo *DeclIdent = nullptr;
+ SourceLocation DeclIdentLoc;
+ ParsedType Type;
+ OMPIteratorExpr::IteratorRange Range;
+ SourceLocation AssignLoc;
+ SourceLocation ColonLoc;
+ SourceLocation SecColonLoc;
+ };
- /// The set of exceptions in the exception specification.
- const QualType *data() const { return Exceptions.data(); }
+ ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
+ SourceLocation LLoc, SourceLocation RLoc,
+ ArrayRef<OMPIteratorData> Data);
- /// Integrate another called method into the collected data.
- void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
+ bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
+ FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc,
+ bool ExecConfig = false);
+ void CheckStaticArrayArgument(SourceLocation CallLoc,
+ ParmVarDecl *Param,
+ const Expr *ArgExpr);
- /// Integrate an invoked expression into the collected data.
- void CalledExpr(Expr *E) { CalledStmt(E); }
+ /// 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);
- /// Integrate an invoked statement into the collected data.
- void CalledStmt(Stmt *S);
+ using ADLCallKind = CallExpr::ADLCallKind;
- /// 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
+ BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
+ ArrayRef<Expr *> Arg, SourceLocation RParenLoc,
+ Expr *Config = nullptr, bool IsExecConfig = false,
+ ADLCallKind UsesADL = ADLCallKind::NotADL);
- /// Evaluate the implicit exception specification for a defaulted
- /// special member function.
- void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD);
+ ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
+ Declarator &D, ParsedType &Ty,
+ SourceLocation RParenLoc, Expr *CastExpr);
- /// Check the given noexcept-specifier, convert its expression, and compute
- /// the appropriate ExceptionSpecificationType.
- ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr,
- ExceptionSpecificationType &EST);
+ CastKind PrepareScalarCast(ExprResult &src, QualType destType);
- /// Check the given exception-specification and update the
- /// exception specification information with the results.
- void checkExceptionSpecification(bool IsTopLevel,
- ExceptionSpecificationType EST,
- ArrayRef<ParsedType> DynamicExceptions,
- ArrayRef<SourceRange> DynamicExceptionRanges,
- Expr *NoexceptExpr,
- SmallVectorImpl<QualType> &Exceptions,
- FunctionProtoType::ExceptionSpecInfo &ESI);
+ /// Build an altivec or OpenCL literal.
+ ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
+ SourceLocation RParenLoc, Expr *E,
+ TypeSourceInfo *TInfo);
- /// 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 MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
- /// 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<ParsedType> DynamicExceptions,
- ArrayRef<SourceRange> DynamicExceptionRanges,
- Expr *NoexceptExpr);
+ ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc,
+ Expr *InitExpr);
- class InheritedConstructorInfo;
+ ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+ TypeSourceInfo *TInfo,
+ SourceLocation RParenLoc,
+ Expr *LiteralExpr);
- /// 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);
+ ExprResult ActOnInitList(SourceLocation LBraceLoc,
+ MultiExprArg InitArgList,
+ SourceLocation RBraceLoc);
- /// Produce notes explaining why a defaulted function was defined as deleted.
- void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD);
+ ExprResult BuildInitList(SourceLocation LBraceLoc,
+ MultiExprArg InitArgList,
+ SourceLocation RBraceLoc);
- /// 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);
+ 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);
- /// DefineImplicitDefaultConstructor - Checks for feasibility of
- /// defining this constructor as the default constructor.
- void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
- CXXConstructorDecl *Constructor);
+ void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc);
- /// 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);
+ /// 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);
- /// DefineImplicitDestructor - Checks for feasibility of
- /// defining this destructor as the default destructor.
- void DefineImplicitDestructor(SourceLocation CurrentLocation,
- CXXDestructorDecl *Destructor);
+ /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+ LabelDecl *TheDecl);
- /// 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);
-
- /// Define the specified inheriting constructor.
- void DefineInheritingConstructor(SourceLocation UseLoc,
- CXXConstructorDecl *Constructor);
-
- /// 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);
+ 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();
- /// DefineImplicitCopyConstructor - Checks for feasibility of
- /// defining this constructor as the copy constructor.
- void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
- CXXConstructorDecl *Constructor);
+ // __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;
+ };
- /// 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);
+ /// __builtin_offsetof(type, a.b[123][456].c)
+ ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+ TypeSourceInfo *TInfo,
+ ArrayRef<OffsetOfComponent> Components,
+ SourceLocation RParenLoc);
+ ExprResult ActOnBuiltinOffsetOf(Scope *S,
+ SourceLocation BuiltinLoc,
+ SourceLocation TypeLoc,
+ ParsedType ParsedArgTy,
+ ArrayRef<OffsetOfComponent> Components,
+ SourceLocation RParenLoc);
- /// DefineImplicitMoveConstructor - Checks for feasibility of
- /// defining this constructor as the move constructor.
- void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
- CXXConstructorDecl *Constructor);
+ // __builtin_choose_expr(constExpr, expr1, expr2)
+ ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
+ Expr *CondExpr, Expr *LHSExpr,
+ Expr *RHSExpr, SourceLocation RPLoc);
- /// 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);
+ // __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);
- /// Defines an implicitly-declared copy assignment operator.
- void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
- CXXMethodDecl *MethodDecl);
+ // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
+ // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
+ ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind,
+ SourceLocation BuiltinLoc,
+ SourceLocation RPLoc);
- /// 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);
+ // Build a potentially resolved SourceLocExpr.
+ ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
+ SourceLocation BuiltinLoc, SourceLocation RPLoc,
+ DeclContext *ParentContext);
- /// Defines an implicitly-declared move assignment operator.
- void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
- CXXMethodDecl *MethodDecl);
+ // __null
+ ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
- /// Force the declaration of any implicitly-declared members of this
- /// class.
- void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+ bool CheckCaseExpression(Expr *E);
- /// Check a completed declaration of an implicit special member.
- void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
+ //===------------------------- "Block" Extension ------------------------===//
- /// Determine whether the given function is an implicitly-deleted
- /// special member function.
- bool isImplicitlyDeleted(FunctionDecl *FD);
+ /// ActOnBlockStart - This callback is invoked when a block literal is
+ /// started.
+ void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
- /// 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);
+ /// 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);
- /// Whether this' shows up in the exception specification of a static
- /// member function.
- bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
+ /// 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);
- /// Check whether 'this' shows up in the attributes of the given
- /// static member function.
- ///
- /// \returns true if an error occurred.
- bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
+ /// 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);
- /// 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);
+ //===---------------------------- Clang Extensions ----------------------===//
- /// Wrap the expression in a ConstantExpr if it is a potential immediate
- /// invocation.
- ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl);
+ /// __builtin_convertvector(...)
+ ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
- bool CheckImmediateEscalatingFunctionDefinition(
- FunctionDecl *FD, const sema::FunctionScopeInfo *FSI);
+ //===---------------------------- OpenCL Features -----------------------===//
- void MarkExpressionAsImmediateEscalating(Expr *E);
+ /// __builtin_astype(...)
+ ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+ ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
- void DiagnoseImmediateEscalatingReason(FunctionDecl *FD);
+ /// Attempts to produce a RecoveryExpr after some AST node cannot be created.
+ ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
+ ArrayRef<Expr *> SubExprs,
+ QualType T = QualType());
- bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
- QualType DeclInitType, MultiExprArg ArgsPtr,
- SourceLocation Loc,
- SmallVectorImpl<Expr *> &ConvertedArgs,
- bool AllowExplicit = false,
- bool IsListInitialization = false);
+ // 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);
- ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
- SourceLocation NameLoc,
- IdentifierInfo &Name);
+ ExprResult PerformObjectMemberConversion(Expr *From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ NamedDecl *Member);
- 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);
+ /// 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);
- ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
- ParsedType ObjectType);
+ /// Emit a warning for all pending noderef expressions that we recorded.
+ void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
- // Checks that reinterpret casts don't have undefined behavior.
- void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
- bool IsDereference, SourceRange Range);
+ ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
- // 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);
- // 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);
+ /// 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);
- /// 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);
+ /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+ /// the default expr if needed.
+ ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
+ ParmVarDecl *Param, Expr *Init = nullptr);
- ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- TypeSourceInfo *Ty,
- Expr *E,
- SourceRange AngleBrackets,
- SourceRange Parens);
+ /// Wrap the expression in a ConstantExpr if it is a potential immediate
+ /// invocation.
+ ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl);
- ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
- ExprResult Operand,
- SourceLocation RParenLoc);
+ void MarkExpressionAsImmediateEscalating(Expr *E);
- ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI,
- Expr *Operand, SourceLocation RParenLoc);
+ bool IsInvalidSMECallConversion(QualType FromType, QualType ToType);
- ExprResult BuildCXXTypeId(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- TypeSourceInfo *Operand,
- SourceLocation RParenLoc);
- ExprResult BuildCXXTypeId(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- Expr *Operand,
- SourceLocation RParenLoc);
+ const DeclContext *getCurObjCLexicalContext() const {
+ const DeclContext *DC = getCurLexicalContext();
+ // A category implicitly has the attribute of the interface.
+ if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(DC))
+ DC = CatD->getClassInterface();
+ return DC;
+ }
- /// ActOnCXXTypeid - Parse typeid( something ).
- ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
- SourceLocation LParenLoc, bool isType,
- void *TyOrExpr,
- SourceLocation RParenLoc);
+ /// Abstract base class used for diagnosing integer constant
+ /// expression violations.
+ class VerifyICEDiagnoser {
+ public:
+ bool Suppress;
- ExprResult BuildCXXUuidof(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- TypeSourceInfo *Operand,
- SourceLocation RParenLoc);
- ExprResult BuildCXXUuidof(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- Expr *Operand,
- SourceLocation RParenLoc);
+ VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { }
- /// ActOnCXXUuidof - Parse __uuidof( something ).
- ExprResult ActOnCXXUuidof(SourceLocation OpLoc,
- SourceLocation LParenLoc, bool isType,
- void *TyOrExpr,
- SourceLocation RParenLoc);
+ 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() {}
+ };
- /// 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<unsigned> NumExpansions);
- ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
- BinaryOperatorKind Operator);
+ enum AllowFoldKind {
+ NoFold,
+ AllowFold,
+ };
- //// ActOnCXXThis - Parse 'this' pointer.
- ExprResult ActOnCXXThis(SourceLocation loc);
+ /// 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);
+ }
- /// Build a CXXThisExpr and mark it referenced in the current context.
- Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
- void MarkThisReferenced(CXXThisExpr *This);
+ /// DiagnoseAssignmentAsCondition - Given that an expression is
+ /// being used as a boolean condition, warn if it's an assignment.
+ void DiagnoseAssignmentAsCondition(Expr *E);
- /// Try to retrieve the type of the 'this' pointer.
- ///
- /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
- QualType getCurrentThisType();
+ /// Redundant parentheses over an equality comparison can indicate
+ /// that the user intended an assignment used as condition.
+ void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
- /// 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 FullExprArg {
+ public:
+ FullExprArg() : E(nullptr) { }
+ FullExprArg(Sema &actions) : E(nullptr) { }
- /// 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 release() {
+ return E;
+ }
- 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);
+ Expr *get() const { return E; }
- ~CXXThisScopeRAII();
+ Expr *operator->() {
+ return E;
+ }
+
+ 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;
+
+ explicit FullExprArg(Expr *expr) : E(expr) {}
+
+ Expr *E;
};
- /// 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);
+ 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());
+ }
- /// 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);
+ class ConditionResult {
+ Decl *ConditionVar;
+ FullExprArg Condition;
+ bool Invalid;
+ std::optional<bool> KnownValue;
- /// ActOnCXXBoolLiteral - Parse {true,false} literals.
- ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+ 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<llvm::APSInt> Val =
+ Condition.get()->getIntegerConstantExpr(S.Context)) {
+ KnownValue = !!(*Val);
+ }
+ }
+ }
+ explicit ConditionResult(bool Invalid)
+ : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid),
+ KnownValue(std::nullopt) {}
+ public:
+ ConditionResult() : ConditionResult(false) {}
+ bool isInvalid() const { return Invalid; }
+ std::pair<VarDecl *, Expr *> get() const {
+ return std::make_pair(cast_or_null<VarDecl>(ConditionVar),
+ Condition.get());
+ }
+ std::optional<bool> getKnownValue() const { return KnownValue; }
+ };
+ static ConditionResult ConditionError() { return ConditionResult(true); }
- /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
- ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+ /// 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 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);
- ExprResult
- ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef<AvailabilitySpec> AvailSpecs,
- SourceLocation AtLoc, SourceLocation RParen);
+ 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.
+ };
- /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
- ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+ ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr,
+ ConditionKind CK, bool MissingOK = false);
- //// 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);
+ QualType CheckConditionalOperands( // C99 6.5.15
+ ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc);
- /// 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);
+ QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation QuestionLoc);
- ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
- SourceLocation LParenLoc,
- MultiExprArg Exprs,
- SourceLocation RParenLoc,
- bool ListInitialization);
+ bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
+ SourceLocation QuestionLoc);
- /// 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<Expr *> ArraySize,
- SourceRange DirectInitRange, Expr *Initializer);
+ /// 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);
- /// Determine whether \p FD is an aligned allocation or deallocation
- /// function that is unavailable.
- bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
+ /// 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,
+ };
- /// Produce diagnostics if \p FD is an aligned allocation or deallocation
- /// function that is unavailable.
- void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
- SourceLocation Loc);
+ // type checking for sizeless vector binary operators.
+ QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, bool IsCompAssign,
+ ArithConvKind OperationKind);
- bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
- SourceRange R);
+ /// 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);
- /// 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 isValidSveBitcast(QualType srcType, QualType destType);
+ bool isValidRVVBitcast(QualType srcType, QualType destType);
- /// 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<QualType> Params);
+ bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
- 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);
+ bool areVectorTypesSameSize(QualType srcType, QualType destType);
+ bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
+ bool isLaxVectorConversion(QualType srcType, QualType destType);
+ bool anyAltivecTypes(QualType srcType, QualType destType);
- /// 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);
+ // type checking C++ declaration initializers (C++ [dcl.init]).
- ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
- Expr *Operand, SourceLocation RParen);
- ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
- SourceLocation RParen);
+ ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
+ Expr *CastExpr, CastKind &CastKind,
+ ExprValueKind &VK, CXXCastPath &Path);
- /// Parsed one of the type trait support pseudo-functions.
- ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
- ArrayRef<ParsedType> Args,
- SourceLocation RParenLoc);
- ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
- ArrayRef<TypeSourceInfo *> Args,
- SourceLocation RParenLoc);
+ /// Force an expression with unknown-type to an expression of the
+ /// given type.
+ ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
- /// ActOnArrayTypeTrait - Parsed one of the binary type trait support
- /// pseudo-functions.
- ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
- SourceLocation KWLoc,
- ParsedType LhsTy,
- Expr *DimExpr,
- SourceLocation RParen);
+ /// Type-check an expression that's being passed to an
+ /// __unknown_anytype parameter.
+ ExprResult checkUnknownAnyArg(SourceLocation callLoc,
+ Expr *result, QualType ¶mType);
- ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT,
- SourceLocation KWLoc,
- TypeSourceInfo *TSInfo,
- Expr *DimExpr,
- 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);
- /// ActOnExpressionTrait - Parsed one of the unary type trait support
- /// pseudo-functions.
- ExprResult ActOnExpressionTrait(ExpressionTrait OET,
- SourceLocation KWLoc,
- Expr *Queried,
- SourceLocation RParen);
+ // 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);
- ExprResult BuildExpressionTrait(ExpressionTrait OET,
- SourceLocation KWLoc,
- Expr *Queried,
- SourceLocation RParen);
+ /// Prepare `SplattedExpr` for a vector splat operation, adding
+ /// implicit casts if necessary.
+ ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
- ExprResult ActOnStartCXXMemberReference(Scope *S,
- Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- ParsedType &ObjectType,
- bool &MayBePseudoDestructor);
+ // 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);
- ExprResult BuildPseudoDestructorExpr(Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- TypeSourceInfo *ScopeType,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- PseudoDestructorTypeStorage DestroyedType);
+ QualType PreferredConditionType(ConditionKind K) const {
+ return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy;
+ }
- ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName);
+ // 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 ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- SourceLocation TildeLoc,
- const DeclSpec& DS);
+ /// CallExprUnaryConversions - a special case of an unary conversion
+ /// performed on a function designator of a call expression.
+ ExprResult CallExprUnaryConversions(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);
+ // DefaultFunctionArrayConversion - converts functions and arrays
+ // to their respective pointers (C99 6.3.2.1).
+ ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
- MaterializeTemporaryExpr *
- CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
- bool BoundToLvalueReference);
+ // DefaultFunctionArrayLvalueConversion - converts functions and
+ // arrays to their respective pointers and performs the
+ // lvalue-to-rvalue conversion.
+ ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
+ bool Diagnose = true);
- 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);
+ // 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);
- // 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);
+ // 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);
- DeclContext *computeDeclContext(QualType T);
- DeclContext *computeDeclContext(const CXXScopeSpec &SS,
- bool EnteringContext = false);
- bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
- CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+ VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ Expr *Fn);
- /// 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);
-
- /// 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);
+ // 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
+ };
- bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
- bool *CanCorrect = nullptr);
- NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+ // Determines which VarArgKind fits an expression.
+ VarArgKind isValidVarArgType(const QualType &Ty);
- /// 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;
+ /// 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 identifier preceding the '::'.
- IdentifierInfo *Identifier;
+ /// GatherArgumentsForCall - Collector argument expressions for various
+ /// form of call prototypes.
+ bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ unsigned FirstParam, ArrayRef<Expr *> Args,
+ SmallVectorImpl<Expr *> &AllArgs,
+ VariadicCallType CallType = VariadicDoesNotApply,
+ bool AllowExplicit = false,
+ bool IsListInitialization = false);
- /// The location of the identifier.
- SourceLocation IdentifierLoc;
+ // 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);
- /// The location of the '::'.
- SourceLocation CCLoc;
+ // 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);
- /// 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) {
- }
+ /// 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,
- NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
- SourceLocation ColonColonLoc, QualType ObjectType)
- : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
- IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {
- }
- };
+ /// PointerToInt - The assignment converts a pointer to an int, which we
+ /// accept as an extension.
+ PointerToInt,
- bool BuildCXXNestedNameSpecifier(Scope *S,
- NestedNameSpecInfo &IdInfo,
- bool EnteringContext,
- CXXScopeSpec &SS,
- NamedDecl *ScopeLookupResult,
- bool ErrorRecoveryLookup,
- bool *IsCorrectedToColon = nullptr,
- bool OnlyNamespace = false);
+ /// IntToPointer - The assignment converts an int to a pointer, which we
+ /// accept as an extension.
+ IntToPointer,
- /// 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);
+ /// FunctionVoidPointer - The assignment is between a function pointer and
+ /// void*, which the standard doesn't allow, but we accept as an extension.
+ FunctionVoidPointer,
- ExprResult ActOnDecltypeExpression(Expr *E);
+ /// IncompatiblePointer - The assignment is between two pointers types that
+ /// are not compatible, but we accept them as an extension.
+ IncompatiblePointer,
- bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
- const DeclSpec &DS,
- SourceLocation ColonColonLoc);
+ /// IncompatibleFunctionPointer - The assignment is between two function
+ /// pointers types that are not compatible, but we accept them as an
+ /// extension.
+ IncompatibleFunctionPointer,
- bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
- const DeclSpec &DS,
- SourceLocation ColonColonLoc,
- QualType Type);
+ /// 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,
- bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
- NestedNameSpecInfo &IdInfo,
- bool EnteringContext);
+ /// 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,
- bool IsInvalidSMECallConversion(QualType FromType, QualType ToType);
+ /// CompatiblePointerDiscardsQualifiers - The assignment discards
+ /// c/v/r qualifiers, which we accept as an extension.
+ CompatiblePointerDiscardsQualifiers,
- /// 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);
+ /// IncompatiblePointerDiscardsQualifiers - The assignment
+ /// discards qualifiers that we don't permit to be discarded,
+ /// like address spaces.
+ IncompatiblePointerDiscardsQualifiers,
- /// 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);
+ /// 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,
- /// 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);
+ /// 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,
- bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+ /// IncompatibleVectors - The assignment is between two vector types that
+ /// have the same size, which we accept as an extension.
+ IncompatibleVectors,
- /// 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);
+ /// IntToBlockPointer - The assignment converts an int to a block
+ /// pointer. We disallow this.
+ IntToBlockPointer,
- /// 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);
+ /// IncompatibleBlockPointer - The assignment is between two block
+ /// pointers types that are not compatible.
+ IncompatibleBlockPointer,
- /// 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);
-
- /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
- /// initializer for the declaration 'Dcl'.
- void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
-
- /// Create a new lambda closure type.
- CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
- TypeSourceInfo *Info,
- unsigned LambdaDependencyKind,
- LambdaCaptureDefault CaptureDefault);
-
- /// Number lambda for linkage purposes if necessary.
- void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method,
- std::optional<CXXRecordDecl::LambdaNumbering>
- NumberingOverride = std::nullopt);
-
- /// 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);
+ /// IncompatibleObjCQualifiedId - The assignment is between a qualified
+ /// id type and something else (that is incompatible with it). For example,
+ /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
+ IncompatibleObjCQualifiedId,
- CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
- CXXRecordDecl *Class);
+ /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
+ /// object with __weak qualifier.
+ IncompatibleObjCWeakRef,
- void AddTemplateParametersToLambdaCallOperator(
- CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
- TemplateParameterList *TemplateParams);
+ /// Incompatible - We reject this conversion outright, it is invalid to
+ /// represent it in the AST.
+ Incompatible
+ };
- void CompleteLambdaCallOperator(
- CXXMethodDecl *Method, SourceLocation LambdaLoc,
- SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
- TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
- StorageClass SC, ArrayRef<ParmVarDecl *> Params,
- bool HasExplicitResultType);
+ /// 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);
- void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
+ /// 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);
- /// 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<unsigned> NumExpansions, IdentifierInfo *Id,
- bool DirectInit, Expr *&Init);
+ /// 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);
- /// Create a dummy variable within the declcontext of the lambda's
- /// call operator, for name lookup purposes for a lambda init capture.
+ /// Check assignment constraints for an assignment of RHS to LHSType.
///
- /// 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);
-
- /// Add an init-capture to a lambda scope.
- void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef);
+ /// \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);
- /// Note that we have finished the explicit captures for the
- /// given lambda.
- void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
+ // 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);
- /// Deduce a block or lambda's return type based on the return
- /// statements present in the body.
- void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+ /// the following "Check" methods will return a valid/converted QualType
+ /// or a null QualType (indicating an error diagnostic was issued).
- /// 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);
+ /// type checking binary operators (subroutines of CreateBuiltinBinOp).
+ QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS,
+ ExprResult &RHS);
+ QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS,
+ ExprResult &RHS);
- /// 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<NamedDecl *> TParams,
- SourceLocation RAngleLoc,
- ExprResult RequiresClause);
+ 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 ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
- SourceLocation MutableLoc);
+ bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr,
+ bool Diagnose = true);
- void ActOnLambdaClosureParameters(
- Scope *LambdaScope,
- MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo);
+ /// 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;
+ }
- /// 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);
+ /// 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;
- /// 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 isAlwaysConstantEvaluatedContext() const {
+ const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
+ return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) &&
+ !Ctx.InConditionallyConstantEvaluateContext;
+ }
- /// ActOnLambdaExpr - This is called when the body of a lambda expression
- /// was successfully completed.
- ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body);
+ /// Determines whether we are currently in a context that
+ /// is not evaluated as per C++ [expr] p5.
+ bool isUnevaluatedContext() const {
+ return currentEvaluationContext().isUnevaluated();
+ }
- /// Does copying/destroying the captured variable have side effects?
- bool CaptureHasSideEffects(const sema::Capture &From);
+ bool isImmediateFunctionContext() const {
+ return currentEvaluationContext().isImmediateFunctionContext();
+ }
- /// Diagnose if an explicit lambda capture is unused. Returns true if a
- /// diagnostic is emitted.
- bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
- const sema::Capture &From);
+ bool isInLifetimeExtendingContext() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back().InLifetimeExtendingContext;
+ }
- /// Build a FieldDecl suitable to hold the given capture.
- FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture);
+ bool isCheckingDefaultArgumentOrInitializer() const {
+ const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
+ return (Ctx.Context ==
+ ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
+ Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
+ }
- /// Initialize the given capture with a suitable expression.
- ExprResult BuildCaptureInit(const sema::Capture &Capture,
- SourceLocation ImplicitCaptureLoc,
- bool IsOpenMPMapping = false);
+ std::optional<ExpressionEvaluationContextRecord::InitializationContext>
+ 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;
+ }
- /// Complete a lambda-expression having processed and attached the
- /// lambda body.
- ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
- sema::LambdaScopeInfo *LSI);
+ std::optional<ExpressionEvaluationContextRecord::InitializationContext>
+ OutermostDeclarationWithDelayedImmediateInvocations() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ std::optional<ExpressionEvaluationContextRecord::InitializationContext> 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;
+ }
- /// 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);
+ /// 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;
+ }
+ }
- /// 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);
+ /// 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;
+ }
+ }
- /// 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);
+ DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
+ return getDefaultedFunctionKind(FD).asComparison();
+ }
- ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
- SourceLocation ConvLocation,
- CXXConversionDecl *Conv,
- Expr *Src);
+ /// 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);
- sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator);
+ void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
+
+ template <typename... Ts>
+ bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID,
+ const Ts &... Args) {
+ SizelessTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser);
+ }
+
+ template <typename... Ts>
+ bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
+ const Ts &... Args) {
+ SizelessTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
+ }
+
+ /// Abstract class used to diagnose incomplete types.
+ struct TypeDiagnoser {
+ TypeDiagnoser() {}
+
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
+ virtual ~TypeDiagnoser() {}
+ };
+
+ template <typename... Ts> class BoundTypeDiagnoser : public TypeDiagnoser {
+ protected:
+ unsigned DiagID;
+ std::tuple<const Ts &...> Args;
+
+ template <std::size_t... Is>
+ void emit(const SemaDiagnosticBuilder &DB,
+ std::index_sequence<Is...>) const {
+ // Apply all tuple elements to the builder in order.
+ bool Dummy[] = {false, (DB << getPrintable(std::get<Is>(Args)))...};
+ (void)Dummy;
+ }
- class LambdaScopeForCallOperatorInstantiationRAII
- : private FunctionScopeRAII {
public:
- LambdaScopeForCallOperatorInstantiationRAII(
- Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
- LocalInstantiationScope &Scope,
- bool ShouldAddDeclsFromParentScope = true);
+ BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
+ : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
+ assert(DiagID != 0 && "no diagnostic for type diagnoser");
+ }
+
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
+ const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
+ emit(DB, std::index_sequence_for<Ts...>());
+ DB << 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);
+ /// 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 <typename... Ts>
+ class SizelessTypeDiagnoser : public BoundTypeDiagnoser<Ts...> {
+ public:
+ SizelessTypeDiagnoser(unsigned DiagID, const Ts &... Args)
+ : BoundTypeDiagnoser<Ts...>(DiagID, 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<std::pair<NamedDecl *, NamedDecl *>, 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<NamedDecl *, NormalizedConstraint *>
- NormalizationCache;
+ void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
+ const SemaDiagnosticBuilder &DB = S.Diag(Loc, this->DiagID);
+ this->emit(DB, std::index_sequence_for<Ts...>());
+ DB << T->isSizelessType() << T;
+ }
+ };
- llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
- SatisfactionCache;
+ /// Check an argument list for placeholders that we won't try to
+ /// handle later.
+ bool CheckArgsForPlaceholders(MultiExprArg args);
- /// 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);
+ /// The C++ "std::source_location::__impl" struct, defined in
+ /// \<source_location>.
+ RecordDecl *StdSourceLocationImplDecl;
- /// Introduce the instantiated captures of the lambda into the local
- /// instantiation scope.
- bool addInstantiatedCapturesToScope(
- FunctionDecl *Function, const FunctionDecl *PatternDecl,
- LocalInstantiationScope &Scope,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ /// A stack of expression evaluation contexts.
+ SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
- /// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
- /// the case of lambdas) set up the LocalInstantiationScope of the current
- /// function.
- bool SetupConstraintScope(
- FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
- MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope);
+ // Set of failed immediate invocations to avoid double diagnosing.
+ llvm::SmallPtrSet<ConstantExpr *, 4> FailedImmediateInvocations;
- /// 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<MultiLevelTemplateArgumentList>
- SetupConstraintCheckingTemplateArgumentsAndScope(
- FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
- LocalInstantiationScope &Scope);
+ /// List of SourceLocations where 'self' is implicitly retained inside a
+ /// block.
+ llvm::SmallVector<std::pair<SourceLocation, const BlockDecl *>, 1>
+ ImplicitlyRetainedSelfLocs;
private:
- // The current stack of constraint satisfactions, so we can exit-early.
- using SatisfactionStackEntryTy =
- std::pair<const NamedDecl *, llvm::FoldingSetNodeID>;
- llvm::SmallVector<SatisfactionStackEntryTy, 10>
- SatisfactionStack;
+ static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
-public:
- void PushSatisfactionStackEntry(const NamedDecl *D,
- const llvm::FoldingSetNodeID &ID) {
- const NamedDecl *Can = cast<NamedDecl>(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<NamedDecl>(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<SatisfactionStackEntryTy, 10>
- 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<SatisfactionStackEntryTy> &NewSS) {
- SatisfactionStack.swap(NewSS);
- }
+ /// The C++ "type_info" declaration, which is defined in \<typeinfo>.
+ RecordDecl *CXXTypeInfoDecl;
- const NormalizedConstraint *
- getNormalizedAssociatedConstraints(
- NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> 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<const Expr *> AC1,
- NamedDecl *D2, MutableArrayRef<const Expr *> 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<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> 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<FieldDecl *, DeleteLocs> 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<const Expr *> ConstraintExprs,
- const MultiLevelTemplateArgumentList &TemplateArgLists,
- SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
- llvm::SmallVector<Expr *, 4> 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<const Expr *> ConstraintExprs,
- llvm::SmallVectorImpl<Expr *> &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);
+ ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ IdentifierInfo &Name);
- /// \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 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 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);
+ ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
+ ParsedType ObjectType);
- /// \brief Emit diagnostics explaining why a constraint expression was deemed
- /// unsatisfied.
- void
- DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
- bool First = true);
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXTypeId(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ SourceLocation RParenLoc);
- // ParseObjCStringLiteral - Parse Objective-C string literals.
- ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
- ArrayRef<Expr *> Strings);
+ /// ActOnCXXTypeid - Parse typeid( something ).
+ ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc);
- ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
+ ExprResult BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXUuidof(QualType TypeInfoType,
+ SourceLocation TypeidLoc,
+ Expr *Operand,
+ 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);
+ /// ActOnCXXUuidof - Parse __uuidof( something ).
+ ExprResult ActOnCXXUuidof(SourceLocation OpLoc,
+ SourceLocation LParenLoc, bool isType,
+ void *TyOrExpr,
+ SourceLocation RParenLoc);
- /// 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);
+ //// ActOnCXXThis - Parse 'this' pointer.
+ ExprResult ActOnCXXThis(SourceLocation loc);
- ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
- Expr *IndexExpr,
- ObjCMethodDecl *getterMethod,
- ObjCMethodDecl *setterMethod);
+ /// Build a CXXThisExpr and mark it referenced in the current context.
+ Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
+ void MarkThisReferenced(CXXThisExpr *This);
- ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
- MutableArrayRef<ObjCDictionaryElement> Elements);
+ /// Try to retrieve the type of the 'this' pointer.
+ ///
+ /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
+ QualType getCurrentThisType();
- ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
- TypeSourceInfo *EncodedTypeInfo,
- SourceLocation RParenLoc);
- ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
- CXXConversionDecl *Method,
- bool HadMultipleCandidates);
+ /// 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 ParseObjCEncodeExpression(SourceLocation AtLoc,
- SourceLocation EncodeLoc,
- SourceLocation LParenLoc,
- ParsedType Ty,
- SourceLocation RParenLoc);
+ /// 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;
- /// ParseObjCSelectorExpression - Build selector expression for \@selector
- ExprResult ParseObjCSelectorExpression(Selector Sel,
- SourceLocation AtLoc,
- SourceLocation SelLoc,
- SourceLocation LParenLoc,
- SourceLocation RParenLoc,
- bool WarnMultipleSelectors);
+ 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);
- /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
- ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
- SourceLocation AtLoc,
- SourceLocation ProtoLoc,
- SourceLocation LParenLoc,
- SourceLocation ProtoIdLoc,
- SourceLocation RParenLoc);
+ ~CXXThisScopeRAII();
+ };
- //===--------------------------------------------------------------------===//
- // C++ Declarations
- //
- Decl *ActOnStartLinkageSpecification(Scope *S,
- SourceLocation ExternLoc,
- Expr *LangStr,
- SourceLocation LBraceLoc);
- Decl *ActOnFinishLinkageSpecification(Scope *S,
- Decl *LinkageSpec,
- SourceLocation RBraceLoc);
+ /// 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);
+ /// 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);
- //===--------------------------------------------------------------------===//
- // 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);
+ /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+ ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
- bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
- SourceLocation ColonLoc,
- const ParsedAttributesView &Attrs);
- NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
- Declarator &D,
- MultiTemplateParamsArg TemplateParameterLists,
- Expr *BitfieldWidth, const VirtSpecifiers &VS,
- InClassInitStyle InitStyle);
+ /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
+ ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
- void ActOnStartCXXInClassMemberInitializer();
- void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
- SourceLocation EqualLoc,
- Expr *Init);
+ ExprResult
+ ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef<AvailabilitySpec> AvailSpecs,
+ SourceLocation AtLoc, SourceLocation RParen);
- MemInitResult ActOnMemInitializer(Decl *ConstructorD,
- Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *MemberOrBase,
- ParsedType TemplateTypeTy,
- const DeclSpec &DS,
- SourceLocation IdLoc,
- SourceLocation LParenLoc,
- ArrayRef<Expr *> Args,
- SourceLocation RParenLoc,
- SourceLocation EllipsisLoc);
+ /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
- MemInitResult ActOnMemInitializer(Decl *ConstructorD,
- Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *MemberOrBase,
- ParsedType TemplateTypeTy,
- const DeclSpec &DS,
- SourceLocation IdLoc,
- Expr *InitList,
- SourceLocation EllipsisLoc);
+ //// 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 BuildMemInitializer(Decl *ConstructorD,
- Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *MemberOrBase,
- ParsedType TemplateTypeTy,
- const DeclSpec &DS,
- SourceLocation IdLoc,
- Expr *Init,
- 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 BuildMemberInitializer(ValueDecl *Member,
- Expr *Init,
- SourceLocation IdLoc);
+ ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation RParenLoc,
+ bool ListInitialization);
- MemInitResult BuildBaseInitializer(QualType BaseType,
- TypeSourceInfo *BaseTInfo,
- Expr *Init,
- CXXRecordDecl *ClassDecl,
- 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<Expr *> ArraySize,
+ SourceRange DirectInitRange, Expr *Initializer);
- MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
- Expr *Init,
- CXXRecordDecl *ClassDecl);
+ /// Determine whether \p FD is an aligned allocation or deallocation
+ /// function that is unavailable.
+ bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
- bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
- CXXCtorInitializer *Initializer);
+ /// Produce diagnostics if \p FD is an aligned allocation or deallocation
+ /// function that is unavailable.
+ void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
+ SourceLocation Loc);
- bool SetCtorInitializers(
- CXXConstructorDecl *Constructor, bool AnyErrors,
- ArrayRef<CXXCtorInitializer *> Initializers = std::nullopt);
+ bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+ SourceRange R);
- void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
+ /// 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
+ };
+ /// 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<QualType> Params);
- /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
- /// mark all the non-trivial destructors of its members and bases as
- /// referenced.
- void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
- CXXRecordDecl *Record);
+ 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);
- /// 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<const RecordType *> *DirectVirtualBases = nullptr);
+ /// 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);
- /// 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 ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
+ Expr *Operand, SourceLocation RParen);
+ ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+ SourceLocation RParen);
- /// 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<CXXRecordDecl*, SourceLocation> VTableUse;
- /// The list of vtables that are required but have not yet been
- /// materialized.
- SmallVector<VTableUse, 16> VTableUses;
- /// 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<CXXRecordDecl *, bool> VTablesUsed;
+ ExprResult ActOnStartCXXMemberReference(Scope *S,
+ Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ ParsedType &ObjectType,
+ bool &MayBePseudoDestructor);
- /// Load any externally-stored vtable uses.
- void LoadExternalVTableUses();
+ ExprResult BuildPseudoDestructorExpr(Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ const CXXScopeSpec &SS,
+ TypeSourceInfo *ScopeType,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ PseudoDestructorTypeStorage DestroyedType);
- /// Note that the vtable for the given class was used at the
- /// given location.
- void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
- bool DefinitionRequired = false);
+ ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ UnqualifiedId &FirstTypeName,
+ SourceLocation CCLoc,
+ SourceLocation TildeLoc,
+ UnqualifiedId &SecondTypeName);
- /// Mark the exception specifications of all virtual member functions
- /// in the given class as needed.
- void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
- const CXXRecordDecl *RD);
-
- /// MarkVirtualMembersReferenced - Will mark all members of the given
- /// CXXRecordDecl referenced.
- void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD,
- bool ConstexprOnly = false);
-
- /// 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();
+ ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ SourceLocation TildeLoc,
+ const DeclSpec& DS);
- void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+ /// 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);
- void ActOnMemInitializers(Decl *ConstructorDecl,
- SourceLocation ColonLoc,
- ArrayRef<CXXCtorInitializer*> MemInits,
- bool AnyErrors);
+ 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);
- /// 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);
+ ExprResult ActOnDecltypeExpression(Expr *E);
- void referenceDLLExportedClassMethods();
+ bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
+ bool IsUDSuffix);
- void propagateDLLAttrToBaseClassTemplate(
- CXXRecordDecl *Class, Attr *ClassAttr,
- ClassTemplateSpecializationDecl *BaseTemplateSpec,
- SourceLocation BaseLoc);
+ bool isUsualDeallocationFunction(const CXXMethodDecl *FD);
- /// 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);
+ ConditionResult ActOnConditionVariable(Decl *ConditionVar,
+ SourceLocation StmtLoc,
+ ConditionKind CK);
- /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
- void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
+ ExprResult CheckConditionVariable(VarDecl *ConditionVar,
+ SourceLocation StmtLoc,
+ ConditionKind CK);
- /// Add [[gsl::Pointer]] attributes for std:: types.
- void inferGslPointerAttribute(TypedefNameDecl *TD);
+ /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
+ ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false);
- void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
+ bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
- /// 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);
- void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
- Decl *TagDecl, SourceLocation LBrac,
- SourceLocation RBrac,
- const ParsedAttributesView &AttrList);
- void ActOnFinishCXXMemberDecls();
- void ActOnFinishCXXNonNestedClass();
+ 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 ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
- unsigned ActOnReenterTemplateScope(Decl *Template,
- llvm::function_ref<Scope *()> 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();
+ bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
- 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);
+ /// Parsed one of the type trait support pseudo-functions.
+ ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+ ArrayRef<ParsedType> Args,
+ SourceLocation RParenLoc);
+ ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+ ArrayRef<TypeSourceInfo *> Args,
+ SourceLocation RParenLoc);
- Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
- MultiTemplateParamsArg TemplateParams);
- NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
- MultiTemplateParamsArg TemplateParams);
+ /// ActOnArrayTypeTrait - Parsed one of the binary type trait support
+ /// pseudo-functions.
+ ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
+ SourceLocation KWLoc,
+ ParsedType LhsTy,
+ Expr *DimExpr,
+ SourceLocation RParen);
- 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);
+ ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *TSInfo,
+ Expr *DimExpr,
+ SourceLocation RParen);
- void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
+ /// ActOnExpressionTrait - Parsed one of the unary type trait support
+ /// pseudo-functions.
+ ExprResult ActOnExpressionTrait(ExpressionTrait OET,
+ SourceLocation KWLoc,
+ Expr *Queried,
+ SourceLocation RParen);
- bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
- CXXSpecialMember CSM,
- SourceLocation DefaultLoc);
- void CheckDelayedMemberExceptionSpecs();
+ ExprResult BuildExpressionTrait(ExpressionTrait OET,
+ SourceLocation KWLoc,
+ Expr *Queried,
+ SourceLocation RParen);
- bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
- DefaultedComparisonKind DCK);
- void DeclareImplicitEqualityComparison(CXXRecordDecl *RD,
- FunctionDecl *Spaceship);
- void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
- DefaultedComparisonKind DCK);
+ 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 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);
+ QualType CheckSizelessVectorConditionalTypes(ExprResult &Cond,
+ ExprResult &LHS, ExprResult &RHS,
+ SourceLocation QuestionLoc);
- //===--------------------------------------------------------------------===//
- // C++ Derived Classes
- //
+ QualType CXXCheckConditionalOperands( // C++ 5.16
+ ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
- /// ActOnBaseSpecifier - Parsed a base specifier
- CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
- SourceRange SpecifierRange,
- bool Virtual, AccessSpecifier Access,
- TypeSourceInfo *TInfo,
- SourceLocation EllipsisLoc);
+ 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;
+ }
- BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
- const ParsedAttributesView &Attrs, bool Virtual,
- AccessSpecifier Access, ParsedType basetype,
- SourceLocation BaseLoc,
- SourceLocation EllipsisLoc);
+ /// 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);
- bool AttachBaseSpecifiers(CXXRecordDecl *Class,
- MutableArrayRef<CXXBaseSpecifier *> Bases);
- void ActOnBaseSpecifiers(Decl *ClassDecl,
- MutableArrayRef<CXXBaseSpecifier *> Bases);
+ /// IgnoredValueConversions - Given that an expression's result is
+ /// syntactically ignored, perform any conversions that are
+ /// required.
+ ExprResult IgnoredValueConversions(Expr *E);
- bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
- bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
- CXXBasePaths &Paths);
+ ExprResult CheckUnevaluatedOperand(Expr *E);
- // FIXME: I don't like this name.
- void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
+ /// 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<ExprResult(Expr *)> Filter =
+ [](Expr *E) -> ExprResult { return E; });
- 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);
-
- std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
+ ExprResult CorrectDelayedTyposInExpr(
+ ExprResult ER, VarDecl *InitDecl = nullptr,
+ bool RecoverUncorrectedTypos = false,
+ llvm::function_ref<ExprResult(Expr *)> Filter =
+ [](Expr *E) -> ExprResult { return E; }) {
+ return ER.isInvalid()
+ ? ER
+ : CorrectDelayedTyposInExpr(ER.get(), InitDecl,
+ RecoverUncorrectedTypos, Filter);
+ }
- bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
- const CXXMethodDecl *Old);
+ /// Describes the result of an "if-exists" condition check.
+ enum IfExistsResult {
+ /// The symbol exists.
+ IER_Exists,
- /// CheckOverridingFunctionReturnType - Checks whether the return types are
- /// covariant, according to C++ [class.virtual]p5.
- bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
- const CXXMethodDecl *Old);
+ /// The symbol does not exist.
+ IER_DoesNotExist,
- // Check that the overriding method has no explicit object parameter.
- bool CheckExplicitObjectOverride(CXXMethodDecl *New,
- const CXXMethodDecl *Old);
+ /// The name is a dependent name, so the results will differ
+ /// from one instantiation to the next.
+ IER_Dependent,
- /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
- /// spec is a subset of base spec.
- bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
- const CXXMethodDecl *Old);
+ /// An error occurred.
+ IER_Error
+ };
- bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+ IfExistsResult
+ CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
+ const DeclarationNameInfo &TargetNameInfo);
- /// CheckOverrideControl - Check C++11 override control semantics.
- void CheckOverrideControl(NamedDecl *D);
+ IfExistsResult
+ CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
+ bool IsIfExists, CXXScopeSpec &SS,
+ UnqualifiedId &Name);
+
+ RequiresExprBodyDecl *
+ ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
+ ArrayRef<ParmVarDecl *> 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<ParmVarDecl *> LocalParameters,
+ SourceLocation RParenLoc,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation ClosingBraceLoc);
- /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
- /// not used in the declaration of an overriding method.
- void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent);
+private:
+ ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+ bool IsDelete);
- /// 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);
+ void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
+ void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
+ bool DeleteWasArrayForm);
+ /// @}
- //===--------------------------------------------------------------------===//
- // C++ Access Control
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
//
- enum AccessResult {
- AR_accessible,
- AR_inaccessible,
- AR_dependent,
- AR_delayed
- };
+ /// \name Member Access Expressions
+ /// Implementations are in SemaExprMember.cpp
+ /// @{
- bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
- NamedDecl *PrevMemberDecl,
- AccessSpecifier LexicalAS);
+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);
- 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<Expr *> 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());
- }
+ ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType,
+ bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierInScope,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
- void HandleDependentAccessCheck(const DependentDiagnostic &DD,
- const MultiLevelTemplateArgumentList &TemplateArgs);
- void PerformDependentDiagnostics(const DeclContext *Pattern,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ UnqualifiedId &Member,
+ Decl *ObjCImpDecl);
- void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+ 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);
- /// When true, access checking violations are treated as SFINAE
- /// failures rather than hard errors.
- bool AccessCheckingSFINAE;
+ bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+ const CXXScopeSpec &SS,
+ const LookupResult &R);
- enum AbstractDiagSelID {
- AbstractNone = -1,
- AbstractReturnType,
- AbstractParamType,
- AbstractVariableType,
- AbstractFieldType,
- AbstractIvarType,
- AbstractSynthesizedIvarType,
- AbstractArrayType
+ // 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;
};
- bool isAbstractType(SourceLocation Loc, QualType T);
- bool RequireNonAbstractType(SourceLocation Loc, QualType T,
- TypeDiagnoser &Diagnoser);
- template <typename... Ts>
- bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
- const Ts &...Args) {
- BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
- return RequireNonAbstractType(Loc, T, Diagnoser);
- }
+ 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);
- void DiagnoseAbstractType(const CXXRecordDecl *RD);
+ 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);
- //===--------------------------------------------------------------------===//
- // C++ Overloaded Operators [C++ 13.5]
- //
+ ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
+ SourceLocation OpLoc,
+ const CXXScopeSpec &SS, FieldDecl *Field,
+ DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo);
- bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+ ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
- bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
+ 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);
+
+ /// @}
- //===--------------------------------------------------------------------===//
- // 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 Initializers
+ /// Implementations are in SemaInit.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:
+ /// Stack of types that correspond to the parameter entities that are
+ /// currently being copy-initialized. Can be empty.
+ llvm::SmallVector<QualType, 4> CurrentParameterCopyTypes;
- private:
- std::optional<SourceLocation> TemplateKW;
- };
+ llvm::DenseMap<unsigned, CXXDeductionGuideDecl *>
+ AggregateDeductionCandidates;
- 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);
+ bool IsStringInit(Expr *Init, const ArrayType *AT);
- TemplateNameKind isTemplateName(Scope *S,
- CXXScopeSpec &SS,
- bool hasTemplateKeyword,
- const UnqualifiedId &Name,
- ParsedType ObjectType,
- bool EnteringContext,
- TemplateTy &Template,
- bool &MemberOfUnknownSpecialization,
- bool Disambiguation = false);
+ bool CanPerformAggregateInitializationForOverloadResolution(
+ const InitializedEntity &Entity, InitListExpr *From);
- /// 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);
+ ExprResult ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation EqualOrColonLoc,
+ bool GNUSyntax,
+ ExprResult Init);
- bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
- SourceLocation NameLoc,
- bool Diagnose = true);
+ /// 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);
- /// 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);
+ MaterializeTemporaryExpr *
+ CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
+ bool BoundToLvalueReference);
- bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
- const CXXScopeSpec *SS,
- TemplateTy &SuggestedTemplate,
- TemplateNameKind &SuggestedKind);
+ /// 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);
- bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
- NamedDecl *Instantiation,
- bool InstantiatedFromMember,
- const NamedDecl *Pattern,
- const NamedDecl *PatternDef,
- TemplateSpecializationKind TSK,
- bool Complain = true);
+ ExprResult PerformQualificationConversion(
+ Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
+ CheckedConversionKind CCK = CCK_ImplicitConversion);
- void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
- TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+ bool CanPerformCopyInitialization(const InitializedEntity &Entity,
+ ExprResult Init);
+ ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ ExprResult Init,
+ bool TopLevelOfInitList = false,
+ bool AllowExplicit = false);
- NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
- SourceLocation EllipsisLoc,
- SourceLocation KeyLoc,
- IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position,
- SourceLocation EqualLoc,
- ParsedType DefaultArg, bool HasTypeConstraint);
+ QualType DeduceTemplateSpecializationFromInitializer(
+ TypeSourceInfo *TInfo, const InitializedEntity &Entity,
+ const InitializationKind &Kind, MultiExprArg Init);
- bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
+ /// @}
- bool ActOnTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstraint,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc);
- bool BuildTypeConstraint(const CXXScopeSpec &SS,
- TemplateIdAnnotation *TypeConstraint,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc,
- bool AllowUnexpandedPack);
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
- DeclarationNameInfo NameInfo,
- ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs,
- TemplateTypeParmDecl *ConstrainedParameter,
- SourceLocation EllipsisLoc);
+ /// \name C++ Lambda Expressions
+ /// Implementations are in SemaLambda.cpp
+ /// @{
- bool AttachTypeConstraint(AutoTypeLoc TL,
- NonTypeTemplateParmDecl *NewConstrainedParm,
- NonTypeTemplateParmDecl *OrigConstrainedParm,
- SourceLocation EllipsisLoc);
+public:
+ /// Create a new lambda closure type.
+ CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
+ TypeSourceInfo *Info,
+ unsigned LambdaDependencyKind,
+ LambdaCaptureDefault CaptureDefault);
- bool RequireStructuralType(QualType T, SourceLocation Loc);
+ /// Number lambda for linkage purposes if necessary.
+ void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method,
+ std::optional<CXXRecordDecl::LambdaNumbering>
+ NumberingOverride = std::nullopt);
- QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
- SourceLocation Loc);
- QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+ /// 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);
- 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);
+ CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
+ CXXRecordDecl *Class);
- TemplateParameterList *
- ActOnTemplateParameterList(unsigned Depth,
- SourceLocation ExportLoc,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc,
- Expr *RequiresClause);
+ void AddTemplateParametersToLambdaCallOperator(
+ CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
+ TemplateParameterList *TemplateParams);
- /// 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
- };
-
- bool CheckTemplateParameterList(TemplateParameterList *NewParams,
- TemplateParameterList *OldParams,
- TemplateParamListContext TPC,
- SkipBodyInfo *SkipBody = nullptr);
- TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
- SourceLocation DeclStartLoc, SourceLocation DeclLoc,
- const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
- ArrayRef<TemplateParameterList *> ParamLists,
- bool IsFriend, bool &IsMemberSpecialization, bool &Invalid,
- bool SuppressDiagnostic = false);
+ void CompleteLambdaCallOperator(
+ CXXMethodDecl *Method, SourceLocation LambdaLoc,
+ SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
+ TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
+ StorageClass SC, ArrayRef<ParmVarDecl *> Params,
+ bool HasExplicitResultType);
- 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);
+ void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
- TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
- QualType NTTPType,
- SourceLocation Loc);
+ /// 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<unsigned> NumExpansions, IdentifierInfo *Id,
+ bool DirectInit, Expr *&Init);
- /// Get a template argument mapping the given template parameter to itself,
- /// e.g. for X in \c template<int X>, this would return an expression template
- /// argument referencing X.
- TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param,
- SourceLocation Location);
+ /// 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);
- void translateTemplateArguments(const ASTTemplateArgsPtr &In,
- TemplateArgumentListInfo &Out);
+ /// Add an init-capture to a lambda scope.
+ void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef);
- ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
+ /// Note that we have finished the explicit captures for the
+ /// given lambda.
+ void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
- void NoteAllFoundTemplates(TemplateName Name);
+ /// Deduce a block or lambda's return type based on the return
+ /// statements present in the body.
+ void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
- QualType CheckTemplateIdType(TemplateName Template,
- SourceLocation TemplateLoc,
- TemplateArgumentListInfo &TemplateArgs);
+ /// 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);
- 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);
+ /// 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<NamedDecl *> TParams,
+ SourceLocation RAngleLoc,
+ ExprResult RequiresClause);
- /// Parsed an elaborated-type-specifier that refers to a template-id,
- /// such as \c class T::template apply<U>.
- TypeResult ActOnTagTemplateIdType(TagUseKind TUK,
- TypeSpecifierType TagSpec,
- SourceLocation TagLoc,
- CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- TemplateTy TemplateD,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation RAngleLoc);
+ void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
+ SourceLocation MutableLoc);
- DeclResult ActOnVarTemplateSpecialization(
- Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
- SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
- StorageClass SC, bool IsPartialSpecialization);
+ void ActOnLambdaClosureParameters(
+ Scope *LambdaScope,
+ MutableArrayRef<DeclaratorChunk::ParamInfo> ParamInfo);
- /// 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);
+ /// 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);
- /// 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,
- SourceLocation TemplateLoc,
- const TemplateArgumentListInfo *TemplateArgs);
+ /// 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);
- ExprResult
- CheckConceptTemplateId(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &ConceptNameInfo,
- NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs);
+ /// ActOnLambdaExpr - This is called when the body of a lambda expression
+ /// was successfully completed.
+ ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body);
- void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
+ /// Does copying/destroying the captured variable have side effects?
+ bool CaptureHasSideEffects(const sema::Capture &From);
- ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- LookupResult &R,
- bool RequiresADL,
- const TemplateArgumentListInfo *TemplateArgs);
+ /// Diagnose if an explicit lambda capture is unused. Returns true if a
+ /// diagnostic is emitted.
+ bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+ const sema::Capture &From);
- ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
+ /// Build a FieldDecl suitable to hold the given capture.
+ FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture);
- TemplateNameKind ActOnTemplateName(
- Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
- TemplateTy &Template, bool AllowInjectedClassName = false);
+ /// Initialize the given capture with a suitable expression.
+ ExprResult BuildCaptureInit(const sema::Capture &Capture,
+ SourceLocation ImplicitCaptureLoc,
+ bool IsOpenMPMapping = false);
- DeclResult ActOnClassTemplateSpecialization(
- Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
- SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
- TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
- MultiTemplateParamsArg TemplateParameterLists,
- SkipBodyInfo *SkipBody = nullptr);
+ /// Complete a lambda-expression having processed and attached the
+ /// lambda body.
+ ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+ sema::LambdaScopeInfo *LSI);
- bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
- TemplateDecl *PrimaryTemplate,
- unsigned NumExplicitArgs,
- ArrayRef<TemplateArgument> Args);
- void CheckTemplatePartialSpecialization(
- ClassTemplatePartialSpecializationDecl *Partial);
- void CheckTemplatePartialSpecialization(
- VarTemplatePartialSpecializationDecl *Partial);
+ /// 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);
- Decl *ActOnTemplateDeclarator(Scope *S,
- MultiTemplateParamsArg TemplateParameterLists,
- Declarator &D);
+ ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
+ SourceLocation ConvLocation,
+ CXXConversionDecl *Conv,
+ Expr *Src);
- bool
- CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
- TemplateSpecializationKind NewTSK,
- NamedDecl *PrevDecl,
- TemplateSpecializationKind PrevTSK,
- SourceLocation PrevPtOfInstantiation,
- bool &SuppressNew);
+ class LambdaScopeForCallOperatorInstantiationRAII
+ : private FunctionScopeRAII {
+ public:
+ LambdaScopeForCallOperatorInstantiationRAII(
+ Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
+ LocalInstantiationScope &Scope,
+ bool ShouldAddDeclsFromParentScope = true);
+ };
- bool CheckDependentFunctionTemplateSpecialization(
- FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
- LookupResult &Previous);
+ /// 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<MangleNumberingContext *, Decl *>
+ getCurrentMangleNumberContext(const DeclContext *DC);
- bool CheckFunctionTemplateSpecialization(
- FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
- LookupResult &Previous, bool QualifiedFriend = false);
- bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
- void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+ /// @}
- 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);
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- unsigned TagSpec, SourceLocation KWLoc,
- CXXScopeSpec &SS, IdentifierInfo *Name,
- SourceLocation NameLoc,
- const ParsedAttributesView &Attr);
-
- DeclResult ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
- SourceLocation TemplateLoc,
- Declarator &D);
-
- TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable(
- TemplateDecl *Template, SourceLocation TemplateLoc,
- SourceLocation RAngleLoc, Decl *Param,
- ArrayRef<TemplateArgument> SugaredConverted,
- ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg);
-
- SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const;
-
- /// 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,
-
- /// The template argument was deduced via template argument
- /// deduction.
- CTAK_Deduced,
-
- /// The template argument was deduced from an array bound
- /// via template argument deduction.
- CTAK_DeducedFromArrayBound
- };
-
- bool
- CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg,
- NamedDecl *Template, SourceLocation TemplateLoc,
- SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
- SmallVectorImpl<TemplateArgument> &SugaredConverted,
- SmallVectorImpl<TemplateArgument> &CanonicalConverted,
- CheckTemplateArgumentKind CTAK);
-
- /// 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.
+ /// \name Name Lookup
///
- /// \param Converted Will receive the converted, canonicalized template
- /// arguments.
+ /// 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.
///
- /// \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.
+ /// 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.
///
- /// \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.
+ /// 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.
///
- /// \returns true if an error occurred, false otherwise.
- bool CheckTemplateArgumentList(
- TemplateDecl *Template, SourceLocation TemplateLoc,
- TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
- SmallVectorImpl<TemplateArgument> &SugaredConverted,
- SmallVectorImpl<TemplateArgument> &CanonicalConverted,
- bool UpdateArgsWithConversions = true,
- bool *ConstraintsNotSatisfied = nullptr);
-
- bool CheckTemplateTypeArgument(
- TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
- SmallVectorImpl<TemplateArgument> &SugaredConverted,
- SmallVectorImpl<TemplateArgument> &CanonicalConverted);
-
- 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 NoteTemplateLocation(const NamedDecl &Decl,
- std::optional<SourceRange> ParamRange = {});
- void NoteTemplateParameterLocation(const NamedDecl &Decl);
+ /// Implementations are in SemaLookup.cpp
+ /// @{
- ExprResult
- BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
- QualType ParamType,
- SourceLocation Loc);
- ExprResult
- BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
- SourceLocation Loc);
+public:
+ /// Tracks whether we are in a context where typo correction is
+ /// disabled.
+ bool DisableTypoCorrection;
- /// 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<typename T> struct X;
- /// template<typename T> struct X;
- /// \endcode
- TPL_TemplateMatch,
+ /// The number of typos corrected by CorrectTypo.
+ unsigned TyposCorrected;
- /// 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<template<int I> class TT> struct X;
- /// template<template<int Value> class Other> struct X;
- /// \endcode
- TPL_TemplateTemplateParmMatch,
+ typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet;
+ typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations;
- /// We are matching the template parameter lists of a template
- /// template argument against the template parameter lists of a template
- /// template parameter.
- ///
- /// \code
- /// template<template<int Value> class Metafun> struct X;
- /// template<int Value> struct integer_c;
- /// X<integer_c> xic;
- /// \endcode
- TPL_TemplateTemplateArgumentMatch,
+ /// 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;
- /// We are determining whether the template-parameters are equivalent
- /// according to C++ [temp.over.link]/6. This comparison does not consider
- /// constraints.
- ///
- /// \code
- /// template<C1 T> void f(T);
- /// template<C2 T> void f(T);
- /// \endcode
- TPL_TemplateParamsEquivalent,
- };
+ /// 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
+ };
- // 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;
+ private:
+ llvm::PointerIntPair<CXXMethodDecl *, 2> Pair;
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");
- }
+ SpecialMemberOverloadResult() {}
+ SpecialMemberOverloadResult(CXXMethodDecl *MD)
+ : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {}
- // 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; }
+ CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
+ void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
- const NamedDecl *getDecl() const { return ND; }
+ Kind getKind() const { return static_cast<Kind>(Pair.getInt()); }
+ void setKind(Kind K) { Pair.setInt(K); }
+ };
- bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
+ class SpecialMemberOverloadResultEntry
+ : public llvm::FastFoldingSetNode,
+ public SpecialMemberOverloadResult {
+ public:
+ SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
+ : FastFoldingSetNode(ID)
+ {}
+ };
- const DeclContext *getLexicalDeclContext() const {
- return ND ? ND->getLexicalDeclContext() : LexicalDC;
- }
+ /// A cache of special member function overload resolution results
+ /// for C++ records.
+ llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache;
- const DeclContext *getDeclContext() const {
- return ND ? ND->getDeclContext() : DC;
- }
+ /// 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<TypoExpr *, 2> TypoExprs;
- SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
- };
+ enum class AcceptableKind { Visible, Reachable };
- bool TemplateParameterListsAreEqual(
- const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
- const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
- TemplateParameterListEqualKind Kind,
- SourceLocation TemplateArgLoc = SourceLocation());
+ // Members have to be NamespaceDecl* or TranslationUnitDecl*.
+ // TODO: make this is a typesafe union.
+ typedef llvm::SmallSetVector<DeclContext *, 16> AssociatedNamespaceSet;
+ typedef llvm::SmallSetVector<CXXRecordDecl *, 16> AssociatedClassSet;
- bool TemplateParameterListsAreEqual(
- TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
- TemplateParameterListEqualKind Kind,
- SourceLocation TemplateArgLoc = SourceLocation()) {
- return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
- Kind, TemplateArgLoc);
- }
+ /// 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
+ };
- // 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);
+ /// 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 CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
+ SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D,
+ CXXSpecialMember SM,
+ bool ConstArg,
+ bool VolatileArg,
+ bool RValueThis,
+ bool ConstThis,
+ bool VolatileThis);
- /// 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);
+ typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
+ typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
+ TypoRecoveryCallback;
- /// Called when the parser has parsed a C++ typename
- /// specifier that ends in a template-id, e.g.,
- /// "typename MetaFun::template apply<T1, T2>".
- ///
- /// \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);
+ /// 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
+ };
- QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
- SourceLocation KeywordLoc,
- NestedNameSpecifierLoc QualifierLoc,
- const IdentifierInfo &II,
- SourceLocation IILoc,
- TypeSourceInfo **TSI,
- bool DeducedTSTContext);
+ 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<Decl>(CurContext)
+ ->getOwningModuleForLinkage(/*IgnoreLinkage*/ true))
+ return ForVisibleRedeclaration;
+ return ForExternalRedeclaration;
+ }
- QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
- SourceLocation KeywordLoc,
- NestedNameSpecifierLoc QualifierLoc,
- const IdentifierInfo &II,
- SourceLocation IILoc,
- bool DeducedTSTContext = true);
+ /// 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 LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+ UnresolvedSetImpl &Functions);
- TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
- SourceLocation Loc,
- DeclarationName Name);
- bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
+ LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
+ SourceLocation GnuLabelLoc = SourceLocation());
- ExprResult RebuildExprInCurrentInstantiation(Expr *E);
- bool RebuildTemplateParamsInCurrentInstantiation(
- TemplateParameterList *Params);
+ 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);
- std::string
- getTemplateArgumentBindingsText(const TemplateParameterList *Params,
- const TemplateArgumentList &Args);
+ /// Force the declaration of any implicitly-declared members of this
+ /// class.
+ void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
- std::string
- getTemplateArgumentBindingsText(const TemplateParameterList *Params,
- const TemplateArgument *Args,
- unsigned NumArgs);
+ /// Make a merged definition of an existing hidden definition \p ND
+ /// visible at the specified location.
+ void makeMergedDefinitionVisible(NamedDecl *ND);
- //===--------------------------------------------------------------------===//
- // C++ Concepts
- //===--------------------------------------------------------------------===//
- Decl *ActOnConceptDefinition(
- Scope *S, MultiTemplateParamsArg TemplateParameterLists,
- IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr);
+ /// 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<Module*> &getLookupModules();
- void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
- bool &AddToScope);
+ bool hasVisibleMergedDefinition(const NamedDecl *Def);
+ bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def);
- RequiresExprBodyDecl *
- ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
- ArrayRef<ParmVarDecl *> 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<ParmVarDecl *> LocalParameters,
- SourceLocation RParenLoc,
- ArrayRef<concepts::Requirement *> Requirements,
- SourceLocation ClosingBraceLoc);
+ /// Determine if the template parameter \p D has a visible default argument.
+ bool
+ hasVisibleDefaultArgument(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules = nullptr);
+ /// Determine if the template parameter \p D has a reachable default argument.
+ bool hasReachableDefaultArgument(
+ const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
+ /// Determine if the template parameter \p D has a reachable default argument.
+ bool hasAcceptableDefaultArgument(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules,
+ Sema::AcceptableKind Kind);
- //===--------------------------------------------------------------------===//
- // C++ Variadic Templates (C++0x [temp.variadic])
- //===--------------------------------------------------------------------===//
+ /// 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<Module *> *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<Module *> *Modules = nullptr);
- /// Determine whether an unexpanded parameter pack might be permitted in this
- /// location. Useful for error recovery.
- bool isUnexpandedParameterPackPermitted();
+ /// 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<Module *> *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<Module *> *Modules = nullptr);
- /// 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,
+ bool isModuleVisible(const Module *M, bool ModulePrivate = false);
- /// The base type of a class type.
- UPPC_BaseType,
+ /// 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);
- /// The type of an arbitrary declaration.
- UPPC_DeclarationType,
+ /// Determine whether any declaration of an entity is visible.
+ bool
+ hasVisibleDeclaration(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules = nullptr) {
+ return isVisible(D) || hasVisibleDeclarationSlow(D, Modules);
+ }
- /// The type of a data member.
- UPPC_DataMemberType,
+ bool hasVisibleDeclarationSlow(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules);
+ /// Determine whether any declaration of an entity is reachable.
+ bool
+ hasReachableDeclaration(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules = nullptr) {
+ return isReachable(D) || hasReachableDeclarationSlow(D, Modules);
+ }
+ bool hasReachableDeclarationSlow(
+ const NamedDecl *D, llvm::SmallVectorImpl<Module *> *Modules = nullptr);
- /// The size of a bit-field.
- UPPC_BitFieldWidth,
+ void diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ bool ErrorRecovery = true);
- /// The expression in a static assertion.
- UPPC_StaticAssertExpression,
+ void diagnoseTypo(const TypoCorrection &Correction,
+ const PartialDiagnostic &TypoDiag,
+ const PartialDiagnostic &PrevNote,
+ bool ErrorRecovery = true);
- /// The fixed underlying type of an enumeration.
- UPPC_FixedUnderlyingType,
+ void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
+ ArrayRef<Expr *> Args,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses);
- /// The enumerator value.
- UPPC_EnumeratorValue,
+ void DiagnoseAmbiguousLookup(LookupResult &Result);
- /// A using declaration.
- UPPC_UsingDeclaration,
+ LiteralOperatorLookupResult
+ LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys,
+ bool AllowRaw, bool AllowTemplate,
+ bool AllowStringTemplate, bool DiagnoseMissing,
+ StringLiteral *StringLit = nullptr);
- /// A friend declaration.
- UPPC_FriendDeclaration,
+ void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+ ArrayRef<Expr *> Args, ADLResult &Functions);
- /// A declaration qualifier.
- UPPC_DeclarationQualifier,
+ 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);
- /// An initializer.
- UPPC_Initializer,
+ enum CorrectTypoKind {
+ CTK_NonError, // CorrectTypo used in a non error recovery situation.
+ CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
+ };
- /// A default argument.
- UPPC_DefaultArgument,
+ 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);
- /// The type of a non-type template parameter.
- UPPC_NonTypeTemplateParameterType,
+ 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);
- /// The type of an exception.
- UPPC_ExceptionType,
+ /// Kinds of missing import. Note, the values of these enumerators correspond
+ /// to %select values in diagnostics.
+ enum class MissingImportKind {
+ Declaration,
+ Definition,
+ DefaultArgument,
+ ExplicitSpecialization,
+ PartialSpecialization
+ };
- /// Explicit specialization.
- UPPC_ExplicitSpecialization,
+ /// 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<Module *> Modules,
+ MissingImportKind MIK, bool Recover);
- /// Partial specialization.
- UPPC_PartialSpecialization,
+ struct TypoExprState {
+ std::unique_ptr<TypoCorrectionConsumer> Consumer;
+ TypoDiagnosticGenerator DiagHandler;
+ TypoRecoveryCallback RecoveryHandler;
+ TypoExprState();
+ TypoExprState(TypoExprState &&other) noexcept;
+ TypoExprState &operator=(TypoExprState &&other) noexcept;
+ };
- /// Microsoft __if_exists.
- UPPC_IfExists,
+ const TypoExprState &getTypoExprState(TypoExpr *TE) const;
- /// Microsoft __if_not_exists.
- UPPC_IfNotExists,
+ /// Clears the state of the given TypoExpr.
+ void clearDelayedTypo(TypoExpr *TE);
- /// Lambda expression.
- UPPC_Lambda,
+ /// Called on #pragma clang __debug dump II
+ void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
- /// Block expression.
- UPPC_Block,
+ /// Called on #pragma clang __debug dump E
+ void ActOnPragmaDump(Expr *E);
- /// A type constraint.
- UPPC_TypeConstraint,
+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<NamespaceDecl*, bool> KnownNamespaces;
- // A requirement in a requires-expression.
- UPPC_Requirement,
+ /// Whether we have already loaded known namespaces from an extenal
+ /// source.
+ bool LoadedExternalKnownNamespaces;
- // A requires-clause.
- UPPC_RequiresClause,
- };
+ bool CppLookupName(LookupResult &R, Scope *S);
- /// 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<UnexpandedParameterPack> Unexpanded);
+ bool isUsableModule(const Module *M);
- /// 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);
+ /// 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<TypoCorrectionConsumer>
+ makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo,
+ Sema::LookupNameKind LookupKind, Scope *S,
+ CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT,
+ bool ErrorRecovery);
- /// 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);
+ /// The set of unhandled TypoExprs and their associated state.
+ llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
- /// 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);
+ /// Creates a new TypoExpr AST node.
+ TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
+ TypoDiagnosticGenerator TDG,
+ TypoRecoveryCallback TRC, SourceLocation TypoLoc);
- /// 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);
+ /// Cache for module units which is usable for current module.
+ llvm::DenseSet<const Module *> UsableModuleUnitsCache;
- /// 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);
+ /// 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();
+ }
- /// 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);
+ bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
- /// 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<UnexpandedParameterPack> &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<UnexpandedParameterPack> &Unexpanded);
+ /// \name Modules
+ /// Implementations are in SemaModule.cpp
+ /// @{
- /// 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<UnexpandedParameterPack> &Unexpanded);
+public:
+ /// Get the module unit whose scope we are currently within.
+ Module *getCurrentModule() const {
+ return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
+ }
- /// 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<UnexpandedParameterPack> &Unexpanded);
+ /// Is the module scope we are an implementation unit?
+ bool currentModuleIsImplementation() const {
+ return ModuleScopes.empty()
+ ? false
+ : ModuleScopes.back().Module->isModuleImplementation();
+ }
- /// 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<UnexpandedParameterPack> &Unexpanded);
+ // When loading a non-modular PCH files, this is used to restore module
+ // visibility.
+ void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {
+ VisibleModules.setVisible(Mod, ImportLoc);
+ }
- /// 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<UnexpandedParameterPack> &Unexpanded);
+ enum class ModuleDeclKind {
+ Interface, ///< 'export module X;'
+ Implementation, ///< 'module X;'
+ PartitionInterface, ///< 'export module X:Y;'
+ PartitionImplementation, ///< 'module X:Y;'
+ };
- /// 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);
+ /// 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.
+ };
- /// 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);
+ /// 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);
- /// Construct a pack expansion type from the pattern of the pack
- /// expansion.
- TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
- SourceLocation EllipsisLoc,
- std::optional<unsigned> NumExpansions);
+ /// 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);
- /// Construct a pack expansion type from the pattern of the pack
- /// expansion.
- QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
- SourceLocation EllipsisLoc,
- std::optional<unsigned> NumExpansions);
+ /// 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);
- /// 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.
+ /// The parser has processed a module import declaration.
///
- /// \param EllipsisLoc The location of the ellipsis.
- ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc);
+ /// \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 = {});
- /// 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<unsigned> NumExpansions);
+ /// 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);
- /// 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<UnexpandedParameterPack> Unexpanded,
- const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand,
- bool &RetainExpansion, std::optional<unsigned> &NumExpansions);
+ /// The parsed has entered a submodule.
+ void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
+ /// The parser has left a submodule.
+ void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
- /// 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.
+ /// Create an implicit import of the given module at the given
+ /// source location, for error recovery, if possible.
///
- /// Returns an empty Optional if the type can't be expanded.
- std::optional<unsigned> getNumArgumentsInExpansion(
- QualType T, const MultiLevelTemplateArgumentList &TemplateArgs);
+ /// 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);
- /// 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);
+ Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl,
+ SourceLocation RBraceLoc);
- /// 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<unsigned> &NumExpansions) const;
+private:
+ /// The parser has begun a translation unit to be compiled as a C++20
+ /// Header Unit, helper for ActOnStartOfTranslationUnit() only.
+ void HandleStartOfHeaderUnit();
- /// 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<unsigned> getFullyPackExpandedSize(TemplateArgument Arg);
+ struct ModuleScope {
+ SourceLocation BeginLoc;
+ clang::Module *Module = nullptr;
+ VisibleModuleSet OuterVisibleModules;
+ };
+ /// The modules we're currently parsing.
+ llvm::SmallVector<ModuleScope, 16> ModuleScopes;
- //===--------------------------------------------------------------------===//
- // C++ Template Argument Deduction (C++ [temp.deduct])
- //===--------------------------------------------------------------------===//
+ /// For an interface unit, this is the implicitly imported interface unit.
+ clang::Module *ThePrimaryInterface = nullptr;
- /// 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);
+ /// 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;
- TemplateDeductionResult
- DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
- ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &Info);
+ /// 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;
- TemplateDeductionResult
- DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
- ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &Info);
+ /// Namespace definitions that we will export when they finish.
+ llvm::SmallPtrSet<const NamespaceDecl*, 8> DeferredExportedNamespaces;
- TemplateDeductionResult SubstituteExplicitTemplateArguments(
- FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo &ExplicitTemplateArgs,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
- sema::TemplateDeductionInfo &Info);
+ /// 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<const FunctionDecl *, 8> PendingInlineFuncDecls;
- /// 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) {}
+ /// Helper function to judge if we are in module purview.
+ /// Return false if we are not in a module.
+ bool isCurrentModulePurview() const;
- QualType OriginalParamType;
- bool DecomposedParam;
- unsigned ArgIdx;
- QualType OriginalArgType;
- };
+ /// Enter the scope of the explicit global module fragment.
+ Module *PushGlobalModuleFragment(SourceLocation BeginLoc);
+ /// Leave the scope of the explicit global module fragment.
+ void PopGlobalModuleFragment();
- TemplateDeductionResult FinishTemplateArgumentDeduction(
- FunctionTemplateDecl *FunctionTemplate,
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
- unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
- sema::TemplateDeductionInfo &Info,
- SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
- bool PartialOverloading = false,
- llvm::function_ref<bool()> CheckNonDependent = []{ return false; });
+ /// Enter the scope of an implicit global module fragment.
+ Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc);
+ /// Leave the scope of an implicit global module fragment.
+ void PopImplicitGlobalModuleFragment();
- TemplateDeductionResult DeduceTemplateArguments(
- FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
- FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
- bool PartialOverloading, bool AggregateDeductionCandidate,
- QualType ObjectType, Expr::Classification ObjectClassification,
- llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent);
+ VisibleModuleSet VisibleModules;
- TemplateDeductionResult
- DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- QualType ArgFunctionType,
- FunctionDecl *&Specialization,
- sema::TemplateDeductionInfo &Info,
- bool IsAddressOfFunction = false);
+ /// @}
- TemplateDeductionResult DeduceTemplateArguments(
- FunctionTemplateDecl *FunctionTemplate, QualType ObjectType,
- Expr::Classification ObjectClassification, QualType ToType,
- CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info);
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- TemplateDeductionResult
- DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- FunctionDecl *&Specialization,
- sema::TemplateDeductionInfo &Info,
- bool IsAddressOfFunction = false);
+ /// \name C++ Overloading
+ /// Implementations are in SemaOverload.cpp
+ /// @{
- /// 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);
+public:
+ /// Whether deferrable diagnostics should be deferred.
+ bool DeferDiags = false;
- // Substitute auto in TypeWithAuto for a Dependent auto type
- QualType SubstAutoTypeDependent(QualType TypeWithAuto);
+ /// RAII class to control scope of DeferDiags.
+ class DeferDiagsRAII {
+ Sema &S;
+ bool SavedDeferDiags = false;
- // Substitute auto in TypeWithAuto for a Dependent auto type
- TypeSourceInfo *
- SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
+ public:
+ DeferDiagsRAII(Sema &S, bool DeferDiags)
+ : S(S), SavedDeferDiags(S.DeferDiags) {
+ S.DeferDiags = DeferDiags;
+ }
+ ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
+ };
- /// 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);
+ /// 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;
- 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);
+ enum OverloadKind {
+ /// This is a legitimate overload: the existing declarations are
+ /// functions or function templates with different signatures.
+ Ovl_Overload,
- bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
- SourceLocation Loc);
+ /// This is not an overload because the signature exactly matches
+ /// an existing declaration.
+ Ovl_Match,
- /// 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<QualType> ParamTypes,
- SourceLocation Loc);
- llvm::DenseMap<unsigned, CXXDeductionGuideDecl *>
- AggregateDeductionCandidates;
-
- QualType DeduceTemplateSpecializationFromInitializer(
- TypeSourceInfo *TInfo, const InitializedEntity &Entity,
- const InitializationKind &Kind, MultiExprArg Init);
+ /// 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);
- QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
- QualType Type, TypeSourceInfo *TSI,
- SourceRange Range, bool DirectInit,
- Expr *Init);
+ // 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);
- TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
+ 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
+ };
- bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
- SourceLocation ReturnLoc, Expr *RetExpr,
- const AutoType *AT);
+ ImplicitConversionSequence
+ TryImplicitConversion(Expr *From, QualType ToType,
+ bool SuppressUserConversions,
+ AllowedExplicit AllowExplicit,
+ bool InOverloadResolution,
+ bool CStyle,
+ bool AllowObjCWritebackConversion);
- 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());
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit = false);
- ClassTemplatePartialSpecializationDecl *
- getMoreSpecializedPartialSpecialization(
- ClassTemplatePartialSpecializationDecl *PS1,
- ClassTemplatePartialSpecializationDecl *PS2,
- SourceLocation Loc);
+ 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);
- bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
- sema::TemplateDeductionInfo &Info);
+ bool FunctionParamTypesAreEqual(ArrayRef<QualType> Old,
+ ArrayRef<QualType> New,
+ unsigned *ArgPos = nullptr,
+ bool Reversed = false);
- VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
- VarTemplatePartialSpecializationDecl *PS1,
- VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+ bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType,
+ unsigned *ArgPos = nullptr,
+ bool Reversed = false);
- bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
- sema::TemplateDeductionInfo &Info);
+ bool FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction,
+ const FunctionDecl *NewFunction,
+ unsigned *ArgPos = nullptr,
+ bool Reversed = false);
- bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
- TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc);
+ void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
+ QualType FromType, QualType ToType);
- void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
- unsigned Depth, llvm::SmallBitVector &Used);
+ 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);
- 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);
+ ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
+ FunctionDecl *Fun);
+ ExprResult PerformImplicitObjectArgumentInitialization(
+ Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
- //===--------------------------------------------------------------------===//
- // C++ Template Instantiation
- //
+ ExprResult PerformContextuallyConvertToBool(Expr *From);
+ ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
- MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
- const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
- std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
- bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
- bool ForConstraintInstantiation = false,
- bool SkipForSpecialization = false);
+ /// 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.
+ };
- /// 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,
+ ExprResult BuildConvertedConstantExpression(Expr *From, QualType T,
+ CCEKind CCE,
+ NamedDecl *Dest = nullptr);
- /// 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,
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ llvm::APSInt &Value, CCEKind CCE);
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ APValue &Value, CCEKind CCE,
+ NamedDecl *Dest = nullptr);
- /// We are instantiating a default argument for a function.
- /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
- /// provides the template arguments as specified.
- DefaultFunctionArgumentInstantiation,
+ ExprResult
+ EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value,
+ CCEKind CCE, bool RequireInt,
+ const APValue &PreNarrowingValue);
- /// We are substituting explicit template arguments provided for
- /// a function template. The entity is a FunctionTemplateDecl.
- ExplicitTemplateArgumentSubstitution,
+ /// 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;
- /// 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,
+ ContextualImplicitConverter(bool Suppress = false,
+ bool SuppressConversion = false)
+ : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
- /// We are substituting into a lambda expression.
- LambdaExpressionSubstitution,
+ /// Determine whether the specified type is a valid destination type
+ /// for this conversion.
+ virtual bool match(QualType T) = 0;
- /// We are substituting prior template arguments into a new
- /// template parameter. The template parameter itself is either a
- /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
- PriorTemplateArgumentSubstitution,
+ /// Emits a diagnostic complaining that the expression does not have
+ /// integral or enumeration type.
+ virtual SemaDiagnosticBuilder
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
- /// We are checking the validity of a default template argument that
- /// has been used when naming a template-id.
- DefaultTemplateArgumentChecking,
+ /// Emits a diagnostic when the expression has incomplete class type.
+ virtual SemaDiagnosticBuilder
+ diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
- /// We are computing the exception specification for a defaulted special
- /// member function.
- ExceptionSpecEvaluation,
+ /// Emits a diagnostic when the only matching conversion function
+ /// is explicit.
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
- /// We are instantiating the exception specification for a function
- /// template which was deferred until it was needed.
- ExceptionSpecInstantiation,
+ /// Emits a note for the explicit conversion function.
+ virtual SemaDiagnosticBuilder
+ noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
- /// We are instantiating a requirement of a requires expression.
- RequirementInstantiation,
+ /// Emits a diagnostic when there are multiple possible conversion
+ /// functions.
+ virtual SemaDiagnosticBuilder
+ diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
- /// We are checking the satisfaction of a nested requirement of a requires
- /// expression.
- NestedRequirementConstraintsCheck,
+ /// Emits a note for one of the candidate conversions.
+ virtual SemaDiagnosticBuilder
+ noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
- /// We are declaring an implicit special member function.
- DeclaringSpecialMember,
-
- /// We are declaring an implicit 'operator==' for a defaulted
- /// 'operator<=>'.
- DeclaringImplicitEqualityComparison,
+ /// 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 defining a synthesized function (such as a defaulted special
- /// member).
- DefiningSynthesizedFunction,
+ virtual ~ContextualImplicitConverter() {}
+ };
- // 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,
+ class ICEConvertDiagnoser : public ContextualImplicitConverter {
+ bool AllowScopedEnumerations;
- // We are substituting template arguments into a constraint expression.
- ConstraintSubstitution,
+ public:
+ ICEConvertDiagnoser(bool AllowScopedEnumerations,
+ bool Suppress, bool SuppressConversion)
+ : ContextualImplicitConverter(Suppress, SuppressConversion),
+ AllowScopedEnumerations(AllowScopedEnumerations) {}
- // We are normalizing a constraint expression.
- ConstraintNormalization,
+ /// Match an integral or (possibly scoped) enumeration type.
+ bool match(QualType T) override;
- // Instantiating a Requires Expression parameter clause.
- RequirementParameterInstantiation,
+ SemaDiagnosticBuilder
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override {
+ return diagnoseNotInt(S, Loc, T);
+ }
- // We are substituting into the parameter mapping of an atomic constraint
- // during normalization.
- ParameterMappingSubstitution,
+ /// 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 rewriting a comparison operator in terms of an operator<=>.
- RewritingOperatorAsSpaceship,
+ /// Perform a contextual implicit conversion.
+ ExprResult PerformContextualImplicitConversion(
+ SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
- /// We are initializing a structured binding.
- InitializingStructuredBinding,
+ /// 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 marking a class as __dllexport.
- MarkingClassDllexported,
+ // 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 building an implied call from __builtin_dump_struct. The
- /// arguments are in CallArgs.
- BuildingBuiltinDumpStructCall,
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime)
+ };
+ };
+ using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions;
- /// 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,
+ ReferenceCompareResult
+ CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
+ ReferenceConversions *Conv = nullptr);
- /// We are building deduction guides for a class.
- BuildingDeductionGuides,
- } Kind;
+ void AddOverloadCandidate(
+ FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> 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<Expr *> 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<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversion = false,
+ OverloadCandidateParamOrder PO = {});
+ void
+ AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext, QualType ObjectType,
+ Expr::Classification ObjectClassification,
+ ArrayRef<Expr *> 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<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool PartialOverloading = false,
+ OverloadCandidateParamOrder PO = {});
+ void AddTemplateOverloadCandidate(
+ FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> 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<QualType> ParamTypes,
+ ArrayRef<Expr *> 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<Expr *> Args,
+ OverloadCandidateSet& CandidateSet);
+ void AddNonMemberOperatorCandidates(
+ const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+ void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ OverloadCandidateParamOrder PO = {});
+ void AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ bool IsAssignmentOperator = false,
+ unsigned NumContextualBoolArguments = 0);
+ void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc, ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet);
+ void AddArgumentDependentLookupCandidates(DeclarationName Name,
+ SourceLocation Loc,
+ ArrayRef<Expr *> Args,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool PartialOverloading = false);
- /// Was the enclosing context a non-instantiation SFINAE context?
- bool SavedInNonInstantiationSFINAEContext;
+ /// 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<Expr *> Args,
+ bool MissingImplicitThis = false);
- /// The point of instantiation or synthesis within the source code.
- SourceLocation PointOfInstantiation;
+ /// 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<const Expr *> Args,
+ SourceLocation Loc);
- /// The entity that is being synthesized.
- Decl *Entity;
+ /// 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);
- /// The template (or partial specialization) in which we are
- /// performing the instantiation, for substitutions of prior template
- /// arguments.
- NamedDecl *Template;
+ /// 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<const NamedDecl *> Equiv);
- union {
- /// The list of template arguments we are substituting, if they
- /// are not part of the entity.
- const TemplateArgument *TemplateArgs;
+ // 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);
- /// The list of argument expressions in a synthesized call.
- const Expr *const *CallArgs;
- };
+ // 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);
- // 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;
+ /// 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());
- /// The number of expressions in CallArgs.
- unsigned NumCallArgs;
+ // [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);
- /// The special member being declared or defined.
- CXXSpecialMember SpecialMember;
- };
+ FunctionDecl *
+ ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
+ QualType TargetType,
+ bool Complain,
+ DeclAccessPair &Found,
+ bool *pHadMultipleCandidates = nullptr);
- ArrayRef<TemplateArgument> template_arguments() const {
- assert(Kind != DeclaringSpecialMember);
- return {TemplateArgs, NumTemplateArgs};
- }
+ FunctionDecl *
+ resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult);
- /// The template deduction info object associated with the
- /// substitution or checking of explicit or deduced template arguments.
- sema::TemplateDeductionInfo *DeductionInfo;
+ bool resolveAndFixAddressOfSingleOverloadCandidate(
+ ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
- /// The source range that covers the construct that cause
- /// the instantiation, e.g., the template-id that causes a class
- /// template instantiation.
- SourceRange InstantiationRange;
+ FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
+ OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr,
+ TemplateSpecCandidateSet *FailedTSC = nullptr);
- CodeSynthesisContext()
- : Kind(TemplateInstantiation),
- SavedInNonInstantiationSFINAEContext(false), Entity(nullptr),
- Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0),
- DeductionInfo(nullptr) {}
+ bool ResolveAndFixSingleFunctionTemplateSpecialization(
+ ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
+ bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(),
+ QualType DestTypeForComplaining = QualType(),
+ unsigned DiagIDForComplaining = 0);
- /// Determines whether this template is an actual instantiation
- /// that should be counted toward the maximum instantiation depth.
- bool isInstantiationRecord() const;
+
+
+ void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet,
+ bool PartialOverloading = false);
+ void AddOverloadedCallCandidates(
+ LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs,
+ ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet);
+
+ // An enum used to represent the different possible results of building a
+ // range-based for loop.
+ enum ForRangeStatus {
+ FRS_Success,
+ FRS_NoViableFunction,
+ FRS_DiagnosticIssued
};
- /// 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<CodeSynthesisContext, 16> CodeSynthesisContexts;
+ ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
+ SourceLocation RangeLoc,
+ const DeclarationNameInfo &NameInfo,
+ LookupResult &MemberLookup,
+ OverloadCandidateSet *CandidateSet,
+ Expr *Range, ExprResult *CallExpr);
- /// Specializations whose definitions are currently being instantiated.
- llvm::DenseSet<std::pair<Decl *, unsigned>> InstantiatingSpecializations;
+ ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
+ UnresolvedLookupExpr *ULE,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc,
+ Expr *ExecConfig,
+ bool AllowTypoCorrection=true,
+ bool CalleesAddressIsTaken=false);
- /// Non-dependent types used in templates that have already been instantiated
- /// by some template instantiation.
- llvm::DenseSet<QualType> InstantiatedNonDependentTypes;
+ bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+ MultiExprArg Args, SourceLocation RParenLoc,
+ OverloadCandidateSet *CandidateSet,
+ ExprResult *Result);
- /// Extra modules inspected when performing a lookup during a template
- /// instantiation. Computed lazily.
- SmallVector<Module*, 16> CodeSynthesisContextLookupModules;
+ ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc NNSLoc,
+ DeclarationNameInfo DNI,
+ const UnresolvedSetImpl &Fns,
+ bool PerformADL = true);
- /// 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<Module*> LookupModulesCache;
+ ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *input, bool RequiresADL = true);
- /// 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<Module*> &getLookupModules();
+ void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
+ OverloadedOperatorKind Op,
+ const UnresolvedSetImpl &Fns,
+ ArrayRef<Expr *> 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);
- /// Map from the most recent declaration of a namespace to the most
- /// recent visible declaration of that namespace.
- llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache;
+ ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc, Expr *Base,
+ MultiExprArg Args);
- /// 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;
+ 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);
- /// 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;
+ ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool *NoArrowOperatorFound = nullptr);
- /// 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;
+ ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+ CXXConversionDecl *Method,
+ bool HadMultipleCandidates);
- /// 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<std::unique_ptr<TemplateInstantiationCallback>>
- TemplateInstCallbacks;
+ ExprResult BuildLiteralOperatorCall(LookupResult &R,
+ DeclarationNameInfo &SuffixInfo,
+ ArrayRef<Expr *> Args,
+ SourceLocation LitEndLoc,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
- /// 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;
+ ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+ ExprResult FixOverloadedFunctionReference(ExprResult,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
- /// 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;
+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<ObjCMethodDecl*>& Methods);
- public:
- ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
- : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
- Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
- }
+ /// @}
- ~ArgumentPackSubstitutionIndexRAII() {
- Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
- }
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
+
+ /// \name Pseudo-Object
+ /// Implementations are in SemaPseudoObject.cpp
+ /// @{
+
+public:
+ void maybeExtendBlockObject(ExprResult &E);
+ CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
+
+ enum ObjCSubscriptKind {
+ OS_Array,
+ OS_Dictionary,
+ OS_Error
};
+ ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
- friend class ArgumentPackSubstitutionRAII;
+ 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);
- /// 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<Decl *, SmallVector<PartialDiagnosticAt, 1> >
- SuppressedDiagnosticsMap;
- SuppressedDiagnosticsMap SuppressedDiagnostics;
+ /// @}
- /// 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());
-
- 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());
-
- /// Note that we are instantiating a default argument in a
- /// template-id.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateParameter Param, TemplateDecl *Template,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange = SourceRange());
-
- /// 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<TemplateArgument> TemplateArgs,
- CodeSynthesisContext::SynthesisKind Kind,
- sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange = SourceRange());
-
- /// Note that we are instantiating as part of template
- /// argument deduction for a class template declaration.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateDecl *Template,
- ArrayRef<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange = SourceRange());
-
- /// 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<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange = SourceRange());
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- /// 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<TemplateArgument> TemplateArgs,
- sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange = SourceRange());
+ /// \name Statements
+ /// Implementations are in SemaStmt.cpp
+ /// @{
- /// Note that we are instantiating a default argument for a function
- /// parameter.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ParmVarDecl *Param,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange = SourceRange());
+public:
+ /// Stack of active SEH __finally scopes. Can be empty.
+ SmallVector<Scope*, 2> CurrentSEHFinally;
- /// Note that we are substituting prior template arguments into a
- /// non-type parameter.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- NamedDecl *Template,
- NonTypeTemplateParmDecl *Param,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange);
+ StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
+ StmtResult ActOnExprStmtError();
- /// Note that we are substituting prior template arguments into a
- /// template template parameter.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- NamedDecl *Template,
- TemplateTemplateParmDecl *Param,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange);
+ StmtResult ActOnNullStmt(SourceLocation SemiLoc,
+ bool HasLeadingEmptyMacro = false);
- /// 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<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange);
+ StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
- 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<TemplateArgument> TemplateArgs,
- SourceRange InstantiationRange);
+ /// DiagnoseUnusedExprResult - If the statement passed in is an expression
+ /// whose result is unused, warn.
+ void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID);
- 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);
+ void ActOnStartOfCompoundStmt(bool IsStmtExpr);
+ void ActOnAfterCompoundStatementLeadingPragmas();
+ void ActOnFinishOfCompoundStmt();
+ StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ ArrayRef<Stmt *> Elts, bool isStmtExpr);
- struct ConstraintNormalization {};
- /// \brief Note that we are normalizing a constraint expression.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintNormalization, NamedDecl *Template,
- SourceRange InstantiationRange);
+ sema::CompoundScopeInfo &getCurCompoundScope() const;
- 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);
+ ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val);
+ StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS,
+ SourceLocation DotDotDotLoc, ExprResult RHS,
+ SourceLocation ColonLoc);
+ void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
- /// \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());
+ StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt, Scope *CurScope);
+ StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+ SourceLocation ColonLoc, Stmt *SubStmt);
- /// \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());
+ StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
+ ArrayRef<const Attr *> Attrs, Stmt *SubStmt);
+ StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList,
+ Stmt *SubStmt);
- /// \brief Note that we are checking a requires clause.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- const RequiresExpr *E,
- sema::TemplateDeductionInfo &DeductionInfo,
- SourceRange InstantiationRange);
+ /// 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);
- struct BuildingDeductionGuidesTag {};
- /// \brief Note that we are building deduction guides.
- InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- TemplateDecl *Entity, BuildingDeductionGuidesTag,
- SourceRange InstantiationRange = SourceRange());
+ 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 have finished instantiating this template.
- void Clear();
+ ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond);
- ~InstantiatingTemplate() { Clear(); }
+ StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
+ SourceLocation LParenLoc, Stmt *InitStmt,
+ ConditionResult Cond,
+ SourceLocation RParenLoc);
+ StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+ Stmt *Switch, Stmt *Body);
- /// Determines whether we have exceeded the maximum
- /// recursive template instantiations.
- bool isInvalid() const { return Invalid; }
+ /// 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);
- /// Determine whether we are already instantiating this
- /// specialization in some surrounding active instantiation.
- bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
+ 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);
- private:
- Sema &SemaRef;
- bool Invalid;
- bool AlreadyInstantiating;
- bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
- SourceRange InstantiationRange);
+ StmtResult ActOnForStmt(SourceLocation ForLoc,
+ SourceLocation LParenLoc,
+ Stmt *First,
+ ConditionResult Second,
+ FullExprArg Third,
+ SourceLocation RParenLoc,
+ Stmt *Body);
- InstantiatingTemplate(
- Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
- SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
- Decl *Entity, NamedDecl *Template = nullptr,
- ArrayRef<TemplateArgument> TemplateArgs = std::nullopt,
- sema::TemplateDeductionInfo *DeductionInfo = nullptr);
+ StmtResult ActOnForEachLValueExpr(Expr *E);
- InstantiatingTemplate(const InstantiatingTemplate&) = delete;
+ ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
+ Expr *collection);
+ StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
+ Stmt *First, Expr *collection,
+ SourceLocation RParenLoc);
+ StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
- InstantiatingTemplate&
- operator=(const InstantiatingTemplate&) = delete;
+ 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
};
- void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
- void popCodeSynthesisContext();
+ StmtResult ActOnCXXForRangeStmt(
+ Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc,
+ Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection,
+ SourceLocation RParenLoc, BuildForRangeKind Kind,
+ ArrayRef<MaterializeTemporaryExpr *> 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<MaterializeTemporaryExpr *> LifetimeExtendTemps = {});
+ StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
- /// Determine whether we are currently performing template instantiation.
- bool inTemplateInstantiation() const {
- return CodeSynthesisContexts.size() > NonInstantiationEntries;
- }
+ 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);
- void PrintContextStack() {
- if (!CodeSynthesisContexts.empty() &&
- CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
- PrintInstantiationStack();
- LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
- }
- if (PragmaAttributeCurrentTargetDecl)
- PrintPragmaAttributeInstantiationPoint();
- }
- void PrintInstantiationStack();
+ struct NamedReturnInfo {
+ const VarDecl *Candidate;
- void PrintPragmaAttributeInstantiationPoint();
+ enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
+ Status S;
- /// 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<sema::TemplateDeductionInfo *> isSFINAEContext() const;
+ 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);
- /// 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;
+ ExprResult
+ PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+ const NamedReturnInfo &NRInfo, Expr *Value,
+ bool SupressSimplerImplicitMoves = false);
- /// Used to change context to isConstantEvaluated without pushing a heavy
- /// ExpressionEvaluationContextRecord object.
- bool isConstantEvaluatedOverride = false;
+ TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
- const ExpressionEvaluationContextRecord ¤tEvaluationContext() const {
- assert(!ExprEvalContexts.empty() &&
- "Must be in an expression evaluation context");
- return ExprEvalContexts.back();
- };
+ bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
+ SourceLocation ReturnLoc, Expr *RetExpr,
+ const AutoType *AT);
- bool isConstantEvaluatedContext() const {
- return currentEvaluationContext().isConstantEvaluated() ||
- isConstantEvaluatedOverride;
- }
+ 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 isAlwaysConstantEvaluatedContext() const {
- const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
- return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) &&
- !Ctx.InConditionallyConstantEvaluateContext;
- }
+ StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
+ Decl *Parm, Stmt *Body);
- /// Determines whether we are currently in a context that
- /// is not evaluated as per C++ [expr] p5.
- bool isUnevaluatedContext() const {
- return currentEvaluationContext().isUnevaluated();
- }
+ StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
- bool isImmediateFunctionContext() const {
- return currentEvaluationContext().isImmediateFunctionContext();
- }
+ StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+ MultiStmtArg Catch, Stmt *Finally);
- bool isInLifetimeExtendingContext() const {
- assert(!ExprEvalContexts.empty() &&
- "Must be in an expression evaluation context");
- return ExprEvalContexts.back().InLifetimeExtendingContext;
- }
+ 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);
- bool isInMaterializeTemporaryObjectContext() const {
- assert(!ExprEvalContexts.empty() &&
- "Must be in an expression evaluation context");
- return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
- }
+ StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
- bool isCheckingDefaultArgumentOrInitializer() const {
- const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
- return (Ctx.Context ==
- ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
- Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
- }
+ StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+ Decl *ExDecl, Stmt *HandlerBlock);
+ StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+ ArrayRef<Stmt *> Handlers);
- std::optional<ExpressionEvaluationContextRecord::InitializationContext>
- 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;
- }
+ 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);
- std::optional<ExpressionEvaluationContextRecord::InitializationContext>
- OutermostDeclarationWithDelayedImmediateInvocations() const {
- assert(!ExprEvalContexts.empty() &&
- "Must be in an expression evaluation context");
- std::optional<ExpressionEvaluationContextRecord::InitializationContext> 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;
- }
+ StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
+ bool IsIfExists,
+ NestedNameSpecifierLoc QualifierLoc,
+ DeclarationNameInfo NameInfo,
+ Stmt *Nested);
+ StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
+ bool IsIfExists,
+ CXXScopeSpec &SS, UnqualifiedId &Name,
+ Stmt *Nested);
- /// 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;
- }
- }
+ void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+ CapturedRegionKind Kind, unsigned NumParams);
+ typedef std::pair<StringRef, QualType> CapturedParamNameType;
+ void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+ CapturedRegionKind Kind,
+ ArrayRef<CapturedParamNameType> Params,
+ unsigned OpenMPCaptureLevel = 0);
+ StmtResult ActOnCapturedRegionEnd(Stmt *S);
+ void ActOnCapturedRegionError();
+ RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
+ SourceLocation Loc,
+ unsigned NumParams);
- /// 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;
- }
- }
+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);
- /// 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;
+ /// Check if the given expression contains 'break' or 'continue'
+ /// statement that produces control flow different from GCC.
+ void CheckBreakContinueBinding(Expr *E);
- 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;
- }
+ /// @}
- ~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;
- }
- };
+ /// \name `inline asm` Statement
+ /// Implementations are in SemaStmtAsm.cpp
+ /// @{
- /// 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;
- public:
- explicit TentativeAnalysisScope(Sema &SemaRef)
- : SemaRef(SemaRef), Trap(SemaRef, true),
- PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) {
- SemaRef.DisableTypoCorrection = true;
- }
- ~TentativeAnalysisScope() {
- SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection;
- }
- };
+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);
- /// The current instantiation scope used to store local
- /// variables.
- LocalInstantiationScope *CurrentInstantiationScope;
+ 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<Token> AsmToks,
+ StringRef AsmString,
+ unsigned NumOutputs, unsigned NumInputs,
+ ArrayRef<StringRef> Constraints,
+ ArrayRef<StringRef> Clobbers,
+ ArrayRef<Expr*> Exprs,
+ SourceLocation EndLoc);
+ LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+ SourceLocation Location,
+ bool AlwaysCreate);
- /// Tracks whether we are in a context where typo correction is
- /// disabled.
- bool DisableTypoCorrection;
+ /// @}
- /// The number of typos corrected by CorrectTypo.
- unsigned TyposCorrected;
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet;
- typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations;
+ /// \name Statement Attribute Handling
+ /// Implementations are in SemaStmtAttr.cpp
+ /// @{
- /// 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;
+public:
+ bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
+ const AttributeCommonInfo &A);
+ bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
+ const AttributeCommonInfo &A);
- /// Worker object for performing CFG-based warnings.
- sema::AnalysisBasedWarnings AnalysisWarnings;
- threadSafety::BeforeSet *ThreadSafetyDeclCache;
+ CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
+ bool CheckRebuiltStmtAttributes(ArrayRef<const Attr *> Attrs);
- /// 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<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
+ /// Process the attributes before creating an attributed statement. Returns
+ /// the semantic attributes that have been processed.
+ void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs,
+ SmallVectorImpl<const Attr *> &OutAttrs);
- /// The queue of implicit template instantiations that are required
- /// but have not yet been performed.
- std::deque<PendingImplicitInstantiation> PendingInstantiations;
+ /// @}
- /// Queue of implicit template instantiations that cannot be performed
- /// eagerly.
- SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations;
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- SmallVector<SmallVector<VTableUse, 16>, 8> SavedVTableUses;
- SmallVector<std::deque<PendingImplicitInstantiation>, 8>
- SavedPendingInstantiations;
+ /// \name C++ Templates
+ /// Implementations are in SemaTemplate.cpp
+ /// @{
- class GlobalEagerInstantiationScope {
+public:
+ // Saves the current floating-point pragma stack and clear it in this Sema.
+ class FpPragmaStackSaveRAII {
public:
- GlobalEagerInstantiationScope(Sema &S, bool Enabled)
- : S(S), Enabled(Enabled) {
- if (!Enabled) return;
+ FpPragmaStackSaveRAII(Sema &S)
+ : S(S), SavedStack(std::move(S.FpPragmaStack)) {
+ S.FpPragmaStack.Stack.clear();
+ }
+ ~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); }
- S.SavedPendingInstantiations.emplace_back();
- S.SavedPendingInstantiations.back().swap(S.PendingInstantiations);
+ private:
+ Sema &S;
+ PragmaStack<FPOptionsOverride> SavedStack;
+ };
- S.SavedVTableUses.emplace_back();
- S.SavedVTableUses.back().swap(S.VTableUses);
- }
+ void resetFPOptions(FPOptions FPO) {
+ CurFPFeatures = FPO;
+ FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
+ }
- void perform() {
- if (Enabled) {
- S.DefineUsedVTables();
- S.PerformPendingInstantiations();
- }
- }
+ ArrayRef<InventedTemplateParameterInfo> getInventedParameterInfos() const {
+ return llvm::ArrayRef(InventedParameterInfos.begin() +
+ InventedParameterInfosStart,
+ InventedParameterInfos.end());
+ }
- ~GlobalEagerInstantiationScope() {
- if (!Enabled) return;
+ /// The number of SFINAE diagnostics that have been trapped.
+ unsigned NumSFINAEErrors;
- // 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();
+ ArrayRef<sema::FunctionScopeInfo*> getFunctionScopes() const {
+ return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
+ FunctionScopes.end());
+ }
- // 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();
- }
- }
+ typedef llvm::MapVector<const FunctionDecl *,
+ std::unique_ptr<LateParsedTemplate>>
+ LateParsedTemplateMapT;
+ LateParsedTemplateMapT LateParsedTemplateMap;
- private:
- Sema &S;
- bool Enabled;
- };
+ /// 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;
- /// The queue of implicit template instantiations that are required
- /// and must be performed within the current local scope.
+ 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.
///
- /// 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<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
+ /// \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 LocalEagerInstantiationScope {
+ enum TemplateNameIsRequiredTag { TemplateNameIsRequired };
+ /// Whether and why a template name is required in this lookup.
+ class RequiredTemplateKind {
public:
- LocalEagerInstantiationScope(Sema &S) : S(S) {
- SavedPendingLocalImplicitInstantiations.swap(
- S.PendingLocalImplicitInstantiations);
- }
-
- void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
+ /// Template name is required if TemplateKWLoc is valid.
+ RequiredTemplateKind(SourceLocation TemplateKWLoc = SourceLocation())
+ : TemplateKW(TemplateKWLoc) {}
+ /// Template name is unconditionally required.
+ RequiredTemplateKind(TemplateNameIsRequiredTag) {}
- ~LocalEagerInstantiationScope() {
- assert(S.PendingLocalImplicitInstantiations.empty() &&
- "there shouldn't be any pending local implicit instantiations");
- SavedPendingLocalImplicitInstantiations.swap(
- S.PendingLocalImplicitInstantiations);
+ 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(); }
private:
- Sema &S;
- std::deque<PendingImplicitInstantiation>
- SavedPendingLocalImplicitInstantiations;
+ std::optional<SourceLocation> TemplateKW;
};
- /// A helper class for building up ExtParameterInfos.
- class ExtParameterInfoBuilder {
- SmallVector<FunctionProtoType::ExtParameterInfo, 16> Infos;
- bool HasInteresting = false;
-
- 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);
-
- if (!HasInteresting)
- HasInteresting = (info != FunctionProtoType::ExtParameterInfo());
- }
-
- /// 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();
- }
+ 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);
- void PerformPendingInstantiations(bool LocalOnly = false);
+ TemplateNameKind isTemplateName(Scope *S,
+ CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
+ const UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template,
+ bool &MemberOfUnknownSpecialization,
+ bool Disambiguation = false);
- TypeSourceInfo *SubstType(TypeSourceInfo *T,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SourceLocation Loc, DeclarationName Entity,
- bool AllowDeducedTST = false);
+ /// 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);
- QualType SubstType(QualType T,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SourceLocation Loc, DeclarationName Entity);
+ bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
+ SourceLocation NameLoc,
+ bool Diagnose = true);
- TypeSourceInfo *SubstType(TypeLoc TL,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SourceLocation Loc, DeclarationName Entity);
+ /// 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);
- 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<QualType> &ExceptionStorage,
- const MultiLevelTemplateArgumentList &Args);
- ParmVarDecl *
- SubstParmVarDecl(ParmVarDecl *D,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- int indexAdjustment, std::optional<unsigned> NumExpansions,
- bool ExpectParameterPack, bool EvaluateConstraints = true);
- bool SubstParmTypes(SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
- const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SmallVectorImpl<QualType> &ParamTypes,
- SmallVectorImpl<ParmVarDecl *> *OutParams,
- ExtParameterInfoBuilder &ParamInfos);
- bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool ForCallExpr = false);
- ExprResult SubstExpr(Expr *E,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind);
- // A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator
- // to disable constraint evaluation, then restore the state.
- template <typename InstTy> struct ConstraintEvalRAII {
- InstTy &TI;
- bool OldValue;
+ bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+ NamedDecl *Instantiation,
+ bool InstantiatedFromMember,
+ const NamedDecl *Pattern,
+ const NamedDecl *PatternDef,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
- ConstraintEvalRAII(InstTy &TI)
- : TI(TI), OldValue(TI.getEvaluateConstraints()) {
- TI.setEvaluateConstraints(false);
- }
- ~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); }
- };
+ void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
+ TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
- // 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);
+ NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
+ SourceLocation EllipsisLoc,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedType DefaultArg, bool HasTypeConstraint);
- /// 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<Expr *> Exprs, bool IsCall,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- SmallVectorImpl<Expr *> &Outputs);
+ bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
- StmtResult SubstStmt(Stmt *S,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool ActOnTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstraint,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc);
+ bool BuildTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstraint,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc,
+ bool AllowUnexpandedPack);
- TemplateParameterList *
- SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool EvaluateConstraints = true);
+ bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
+ DeclarationNameInfo NameInfo,
+ ConceptDecl *NamedConcept,
+ const TemplateArgumentListInfo *TemplateArgs,
+ TemplateTypeParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc);
- bool
- SubstTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- TemplateArgumentListInfo &Outputs);
+ bool AttachTypeConstraint(AutoTypeLoc TL,
+ NonTypeTemplateParmDecl *NewConstrainedParm,
+ NonTypeTemplateParmDecl *OrigConstrainedParm,
+ SourceLocation EllipsisLoc);
- Decl *SubstDecl(Decl *D, DeclContext *Owner,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ bool RequireStructuralType(QualType T, SourceLocation Loc);
- /// Substitute the name and return type of a defaulted 'operator<=>' to form
- /// an implicit 'operator=='.
- FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
- FunctionDecl *Spaceship);
+ QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+ SourceLocation Loc);
+ QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
- ExprResult SubstInitializer(Expr *E,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool CXXDirectInit);
+ 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);
- bool
- SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
- CXXRecordDecl *Pattern,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ TemplateParameterList *
+ ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> Params,
+ SourceLocation RAngleLoc,
+ Expr *RequiresClause);
- bool
- InstantiateClass(SourceLocation PointOfInstantiation,
- CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- TemplateSpecializationKind TSK,
- bool Complain = true);
+ /// 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
+ };
- bool InstantiateEnum(SourceLocation PointOfInstantiation,
- EnumDecl *Instantiation, EnumDecl *Pattern,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- TemplateSpecializationKind TSK);
+ bool CheckTemplateParameterList(TemplateParameterList *NewParams,
+ TemplateParameterList *OldParams,
+ TemplateParamListContext TPC,
+ SkipBodyInfo *SkipBody = nullptr);
+ TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
+ SourceLocation DeclStartLoc, SourceLocation DeclLoc,
+ const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
+ ArrayRef<TemplateParameterList *> ParamLists,
+ bool IsFriend, bool &IsMemberSpecialization, bool &Invalid,
+ bool SuppressDiagnostic = false);
- bool InstantiateInClassInitializer(
- SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
- FieldDecl *Pattern, 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);
- struct LateInstantiatedAttribute {
- const Attr *TmplAttr;
- LocalInstantiationScope *Scope;
- Decl *NewDecl;
+ void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+ TemplateArgumentListInfo &Out);
- LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
- Decl *D)
- : TmplAttr(A), Scope(S), NewDecl(D)
- { }
- };
- typedef SmallVector<LateInstantiatedAttribute, 16> LateInstantiatedAttrVec;
+ ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
- void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
- const Decl *Pattern, Decl *Inst,
- LateInstantiatedAttrVec *LateAttrs = nullptr,
- LocalInstantiationScope *OuterMostScope = nullptr);
- void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst);
+ void NoteAllFoundTemplates(TemplateName Name);
- void
- InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs,
- const Decl *Pattern, Decl *Inst,
- LateInstantiatedAttrVec *LateAttrs = nullptr,
- LocalInstantiationScope *OuterMostScope = nullptr);
+ QualType CheckTemplateIdType(TemplateName Template,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs);
- void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor);
+ 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);
- bool usesPartialOrExplicitSpecialization(
- SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec);
+ /// Parsed an elaborated-type-specifier that refers to a template-id,
+ /// such as \c class T::template apply<U>.
+ TypeResult ActOnTagTemplateIdType(TagUseKind TUK,
+ TypeSpecifierType TagSpec,
+ SourceLocation TagLoc,
+ CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ TemplateTy TemplateD,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation RAngleLoc);
- bool
- InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *ClassTemplateSpec,
- TemplateSpecializationKind TSK,
- bool Complain = true);
+ DeclResult ActOnVarTemplateSpecialization(
+ Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
+ SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+ StorageClass SC, bool IsPartialSpecialization);
- void InstantiateClassMembers(SourceLocation PointOfInstantiation,
- CXXRecordDecl *Instantiation,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- TemplateSpecializationKind TSK);
+ /// 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 InstantiateClassTemplateSpecializationMembers(
- SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *ClassTemplateSpec,
- TemplateSpecializationKind TSK);
+ /// 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,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
- NestedNameSpecifierLoc
- SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ ExprResult
+ CheckConceptTemplateId(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &ConceptNameInfo,
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const TemplateArgumentListInfo *TemplateArgs);
- DeclarationNameInfo
- SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
- const MultiLevelTemplateArgumentList &TemplateArgs);
- TemplateName
- SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name,
- SourceLocation Loc,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
- bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool EvaluateConstraint);
+ ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo *TemplateArgs);
- bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
- ParmVarDecl *Param);
- void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
- FunctionDecl *Function);
- bool CheckInstantiatedFunctionTemplateConstraints(
- SourceLocation PointOfInstantiation, FunctionDecl *Decl,
- ArrayRef<TemplateArgument> 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<TemplateArgument> &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);
+ ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
- void InstantiateVariableInitializer(
- VarDecl *Var, VarDecl *OldVar,
- const MultiLevelTemplateArgumentList &TemplateArgs);
- void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
- VarDecl *Var, bool Recursive = false,
- bool DefinitionRequired = false,
- bool AtEndOfTU = false);
+ TemplateNameKind ActOnTemplateName(
+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
+ TemplateTy &Template, bool AllowInjectedClassName = false);
- void InstantiateMemInitializers(CXXConstructorDecl *New,
- const CXXConstructorDecl *Tmpl,
- 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);
- ExplicitSpecifier instantiateExplicitSpecifier(
- const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES);
+ bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
+ TemplateDecl *PrimaryTemplate,
+ unsigned NumExplicitArgs,
+ ArrayRef<TemplateArgument> Args);
+ void CheckTemplatePartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *Partial);
+ void CheckTemplatePartialSpecialization(
+ VarTemplatePartialSpecializationDecl *Partial);
- NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool FindingInstantiatedContext = false);
- DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ Decl *ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
- // Objective-C declarations.
- enum ObjCContainerKind {
- OCK_None = -1,
- OCK_Interface = 0,
- OCK_Protocol,
- OCK_Category,
- OCK_ClassExtension,
- OCK_Implementation,
- OCK_CategoryImplementation
- };
- ObjCContainerKind getObjCContainerKind() const;
+ bool
+ CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind ActOnExplicitInstantiationNewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPtOfInstantiation,
+ bool &SuppressNew);
- DeclResult actOnObjCTypeParam(Scope *S,
- ObjCTypeParamVariance variance,
- SourceLocation varianceLoc,
- unsigned index,
- IdentifierInfo *paramName,
- SourceLocation paramLoc,
- SourceLocation colonLoc,
- ParsedType typeBound);
+ bool CheckDependentFunctionTemplateSpecialization(
+ FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous);
- ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
- ArrayRef<Decl *> typeParams,
- SourceLocation rAngleLoc);
- void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
+ bool CheckFunctionTemplateSpecialization(
+ FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous, bool QualifiedFriend = false);
+ bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+ void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
- ObjCInterfaceDecl *ActOnStartClassInterface(
- Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
- SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
- IdentifierInfo *SuperName, SourceLocation SuperLoc,
- ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,
- Decl *const *ProtoRefs, unsigned NumProtoRefs,
- const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
- const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody);
+ 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);
- void ActOnSuperClassOfClassInterface(Scope *S,
- SourceLocation AtInterfaceLoc,
- ObjCInterfaceDecl *IDecl,
- IdentifierInfo *ClassName,
- SourceLocation ClassLoc,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc,
- ArrayRef<ParsedType> SuperTypeArgs,
- SourceRange SuperTypeArgsRange);
+ DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ unsigned TagSpec, SourceLocation KWLoc,
+ CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ const ParsedAttributesView &Attr);
- void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
- SmallVectorImpl<SourceLocation> &ProtocolLocs,
- IdentifierInfo *SuperName,
- SourceLocation SuperLoc);
+ DeclResult ActOnExplicitInstantiation(Scope *S,
+ SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
+ Declarator &D);
- Decl *ActOnCompatibilityAlias(
- SourceLocation AtCompatibilityAliasLoc,
- IdentifierInfo *AliasName, SourceLocation AliasLocation,
- IdentifierInfo *ClassName, SourceLocation ClassLocation);
+ TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable(
+ TemplateDecl *Template, SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc, Decl *Param,
+ ArrayRef<TemplateArgument> SugaredConverted,
+ ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg);
- bool CheckForwardProtocolDeclarationForCircularDependency(
- IdentifierInfo *PName,
- SourceLocation &PLoc, SourceLocation PrevLoc,
- const ObjCList<ObjCProtocolDecl> &PList);
+ SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const;
- ObjCProtocolDecl *ActOnStartProtocolInterface(
- SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
- SourceLocation ProtocolLoc, Decl *const *ProtoRefNames,
- unsigned NumProtoRefs, const SourceLocation *ProtoLocs,
- SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList,
- SkipBodyInfo *SkipBody);
+ /// 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,
- 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);
+ /// The template argument was deduced via template argument
+ /// deduction.
+ CTAK_Deduced,
- ObjCImplementationDecl *ActOnStartClassImplementation(
- SourceLocation AtClassImplLoc, IdentifierInfo *ClassName,
- SourceLocation ClassLoc, IdentifierInfo *SuperClassname,
- SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList);
+ /// The template argument was deduced from an array bound
+ /// via template argument deduction.
+ CTAK_DeducedFromArrayBound
+ };
- ObjCCategoryImplDecl *ActOnStartCategoryImplementation(
- SourceLocation AtCatImplLoc, IdentifierInfo *ClassName,
- SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc,
- const ParsedAttributesView &AttrList);
+ bool
+ CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg,
+ NamedDecl *Template, SourceLocation TemplateLoc,
+ SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted,
+ CheckTemplateArgumentKind CTAK);
- DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl,
- ArrayRef<Decl *> Decls);
+ /// 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<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted,
+ bool UpdateArgsWithConversions = true,
+ bool *ConstraintsNotSatisfied = nullptr);
- DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
- IdentifierInfo **IdentList,
- SourceLocation *IdentLocs,
- ArrayRef<ObjCTypeParamList *> TypeParamLists,
- unsigned NumElts);
+ bool CheckTemplateTypeArgument(
+ TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
+ SmallVectorImpl<TemplateArgument> &SugaredConverted,
+ SmallVectorImpl<TemplateArgument> &CanonicalConverted);
- DeclGroupPtrTy
- ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
- ArrayRef<IdentifierLocPair> IdentList,
- const ParsedAttributesView &attrList);
+ 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 FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
- ArrayRef<IdentifierLocPair> ProtocolId,
- SmallVectorImpl<Decl *> &Protocols);
+ void NoteTemplateLocation(const NamedDecl &Decl,
+ std::optional<SourceRange> ParamRange = {});
+ void NoteTemplateParameterLocation(const NamedDecl &Decl);
- void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId,
- SourceLocation ProtocolLoc,
- IdentifierInfo *TypeArgId,
- SourceLocation TypeArgLoc,
- bool SelectProtocolFirst = false);
+ ExprResult
+ BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
+ QualType ParamType,
+ SourceLocation Loc);
+ ExprResult
+ BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
+ SourceLocation Loc);
- /// 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<IdentifierInfo *> identifiers,
- ArrayRef<SourceLocation> identifierLocs,
- SourceLocation rAngleLoc,
- SourceLocation &typeArgsLAngleLoc,
- SmallVectorImpl<ParsedType> &typeArgs,
- SourceLocation &typeArgsRAngleLoc,
- SourceLocation &protocolLAngleLoc,
- SmallVectorImpl<Decl *> &protocols,
- SourceLocation &protocolRAngleLoc,
- bool warnOnIncompleteProtocols);
+ /// 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<typename T> struct X;
+ /// template<typename T> struct X;
+ /// \endcode
+ TPL_TemplateMatch,
- /// Build a an Objective-C protocol-qualified 'id' type where no
- /// base type was specified.
- TypeResult actOnObjCProtocolQualifierType(
- SourceLocation lAngleLoc,
- ArrayRef<Decl *> protocols,
- ArrayRef<SourceLocation> protocolLocs,
- SourceLocation rAngleLoc);
+ /// 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<template<int I> class TT> struct X;
+ /// template<template<int Value> class Other> struct X;
+ /// \endcode
+ TPL_TemplateTemplateParmMatch,
- /// Build a specialized and/or protocol-qualified Objective-C type.
- TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
- Scope *S,
- SourceLocation Loc,
- ParsedType BaseType,
- SourceLocation TypeArgsLAngleLoc,
- ArrayRef<ParsedType> TypeArgs,
- SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<Decl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc);
+ /// We are matching the template parameter lists of a template
+ /// template argument against the template parameter lists of a template
+ /// template parameter.
+ ///
+ /// \code
+ /// template<template<int Value> class Metafun> struct X;
+ /// template<int Value> struct integer_c;
+ /// X<integer_c> xic;
+ /// \endcode
+ TPL_TemplateTemplateArgumentMatch,
- /// Build an Objective-C type parameter type.
- QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<ObjCProtocolDecl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc,
- bool FailOnError = false);
+ /// We are determining whether the template-parameters are equivalent
+ /// according to C++ [temp.over.link]/6. This comparison does not consider
+ /// constraints.
+ ///
+ /// \code
+ /// template<C1 T> void f(T);
+ /// template<C2 T> void f(T);
+ /// \endcode
+ TPL_TemplateParamsEquivalent,
+ };
- /// Build an Objective-C object pointer type.
- QualType BuildObjCObjectType(
- QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
- ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
- bool FailOnError, bool Rebuilding);
+ // 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;
- /// 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);
+ public:
+ TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
+ TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
+ const DeclContext *LexicalDeclCtx,
+ 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);
+ : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
+ assert(DC && LexicalDC &&
+ "Constructor only for cases where we have the information to put "
+ "in here");
+ }
+ // 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 DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
- ObjCPropertyDecl *SuperProperty,
- const IdentifierInfo *Name,
- bool OverridingProtocolProperty);
-
- void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
- ObjCInterfaceDecl *ID);
+ const NamedDecl *getDecl() const { return ND; }
- Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
- ArrayRef<Decl *> allMethods = std::nullopt,
- ArrayRef<DeclGroupPtrTy> 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<SourceLocation> 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);
+ /// 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);
- bool CheckARCMethodDecl(ObjCMethodDecl *method);
- bool inferObjCARCLifetime(ValueDecl *decl);
+ /// Called when the parser has parsed a C++ typename
+ /// specifier that ends in a template-id, e.g.,
+ /// "typename MetaFun::template apply<T1, T2>".
+ ///
+ /// \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 deduceOpenCLAddressSpace(ValueDecl *decl);
+ QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ SourceLocation KeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo &II,
+ SourceLocation IILoc,
+ TypeSourceInfo **TSI,
+ bool DeducedTSTContext);
- 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,
+ bool DeducedTSTContext = true);
- ExprResult
- ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation receiverNameLoc,
- SourceLocation propertyNameLoc);
- 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<SourceLocation> 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<SourceLocation> 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<SourceLocation> 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<SourceLocation> 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<QualType> ParamTypes,
+ SourceLocation Loc);
- ExprResult ActOnInstanceMessage(Scope *S,
- Expr *Receiver,
- Selector Sel,
- SourceLocation LBracLoc,
- ArrayRef<SourceLocation> SelectorLocs,
- SourceLocation RBracLoc,
- MultiExprArg Args);
+ /// Find the failed Boolean condition within a given Boolean
+ /// constant expression, and describe it with a string.
+ std::pair<Expr *, std::string> 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();
-
- /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma
- /// strict_gs_check.
- void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation,
- PragmaMsStackAction Action,
- bool Value);
-
- /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
- void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
+ /// 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<Decl *, SmallVector<PartialDiagnosticAt, 1>>
+ SuppressedDiagnosticsMap;
+ SuppressedDiagnosticsMap SuppressedDiagnostics;
- /// ActOnPragmaMSComment - Called on well formed
- /// \#pragma comment(kind, "arg").
- void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
- StringRef Arg);
+ bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg);
- /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
- /// pointers_to_members(representation method[, general purpose
- /// representation]).
- void ActOnPragmaMSPointersToMembers(
- LangOptions::PragmaMSPointersToMembersKind Kind,
- SourceLocation PragmaLoc);
+ TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
+ QualType NTTPType,
+ SourceLocation Loc);
- /// Called on well formed \#pragma vtordisp().
- void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
- SourceLocation PragmaLoc,
- MSVtorDispMode Value);
+ /// Get a template argument mapping the given template parameter to itself,
+ /// e.g. for X in \c template<int X>, this would return an expression template
+ /// argument referencing X.
+ TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param,
+ SourceLocation Location);
- enum PragmaSectionKind {
- PSK_DataSeg,
- PSK_BSSSeg,
- PSK_ConstSeg,
- PSK_CodeSeg,
- };
+ /// 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);
- bool UnifySection(StringRef SectionName, int SectionFlags,
- NamedDecl *TheDecl);
- bool UnifySection(StringRef SectionName,
- int SectionFlags,
- SourceLocation PragmaSectionLocation);
+ TemplateDeductionResult
+ DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ 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);
+ TemplateDeductionResult
+ DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
- /// Called on well formed \#pragma section().
- void ActOnPragmaMSSection(SourceLocation PragmaLocation,
- int SectionFlags, StringLiteral *SegmentName);
+ TemplateDeductionResult SubstituteExplicitTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo &ExplicitTemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
+ sema::TemplateDeductionInfo &Info);
- /// Called on well-formed \#pragma init_seg().
- void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
- StringLiteral *SegmentName);
+ /// 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 alloc_text().
- void ActOnPragmaMSAllocText(
- SourceLocation PragmaLocation, StringRef Section,
- const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>>
- &Functions);
+ QualType OriginalParamType;
+ bool DecomposedParam;
+ unsigned ArgIdx;
+ QualType OriginalArgType;
+ };
- /// Called on #pragma clang __debug dump II
- void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
-
- /// Called on #pragma clang __debug dump E
- void ActOnPragmaDump(Expr *E);
-
- /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
- void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
- StringRef Value);
+ TemplateDeductionResult FinishTemplateArgumentDeduction(
+ FunctionTemplateDecl *FunctionTemplate,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
+ bool PartialOverloading = false,
+ llvm::function_ref<bool()> CheckNonDependent = []{ return false; });
- /// Are precise floating point semantics currently enabled?
- bool isPreciseFPEnabled() {
- return !CurFPFeatures.getAllowFPReassociate() &&
- !CurFPFeatures.getNoSignedZero() &&
- !CurFPFeatures.getAllowReciprocal() &&
- !CurFPFeatures.getAllowApproxFunc();
- }
+ TemplateDeductionResult DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
+ bool PartialOverloading, bool AggregateDeductionCandidate,
+ QualType ObjectType, Expr::Classification ObjectClassification,
+ llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent);
- void ActOnPragmaFPEvalMethod(SourceLocation Loc,
- LangOptions::FPEvalMethodKind Value);
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ QualType ArgFunctionType,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction = false);
- /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
- void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
- PragmaFloatControlKind Value);
+ TemplateDeductionResult DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate, QualType ObjectType,
+ Expr::Classification ObjectClassification, QualType ToType,
+ CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info);
- /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
- void ActOnPragmaUnused(const Token &Identifier,
- Scope *curScope,
- SourceLocation PragmaLoc);
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction = false);
- /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
- void ActOnPragmaVisibility(const IdentifierInfo* VisType,
- SourceLocation PragmaLoc);
+ /// 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);
- NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
- SourceLocation Loc);
- void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W);
+ // Substitute auto in TypeWithAuto for a Dependent auto type
+ QualType SubstAutoTypeDependent(QualType TypeWithAuto);
- /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
- void ActOnPragmaWeakID(IdentifierInfo* WeakName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc);
+ // Substitute auto in TypeWithAuto for a Dependent auto type
+ TypeSourceInfo *
+ SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
- /// ActOnPragmaRedefineExtname - Called on well formed
- /// \#pragma redefine_extname oldname newname.
- void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName,
- IdentifierInfo* AliasName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc,
- SourceLocation AliasNameLoc);
+ /// 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);
- /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident.
- void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
- IdentifierInfo* AliasName,
- SourceLocation PragmaLoc,
- SourceLocation WeakNameLoc,
- SourceLocation AliasNameLoc);
+ 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);
- /// ActOnPragmaFPContract - Called on well formed
- /// \#pragma {STDC,OPENCL} FP_CONTRACT and
- /// \#pragma clang fp contract
- void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
+ bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
+ SourceLocation Loc);
- /// Called on well formed
- /// \#pragma clang fp reassociate
- /// or
- /// \#pragma clang fp reciprocal
- void ActOnPragmaFPValueChangingOption(SourceLocation Loc, PragmaFPKind Kind,
- bool IsEnabled);
+ ClassTemplatePartialSpecializationDecl *
+ getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc);
- /// ActOnPragmaFenvAccess - Called on well formed
- /// \#pragma STDC FENV_ACCESS
- void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
+ bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
+ sema::TemplateDeductionInfo &Info);
- /// ActOnPragmaCXLimitedRange - Called on well formed
- /// \#pragma STDC CX_LIMITED_RANGE
- void ActOnPragmaCXLimitedRange(SourceLocation Loc,
- LangOptions::ComplexRangeKind Range);
+ VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
+ VarTemplatePartialSpecializationDecl *PS1,
+ VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
- /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
- void ActOnPragmaFPExceptions(SourceLocation Loc,
- LangOptions::FPExceptionModeKind);
+ bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
+ sema::TemplateDeductionInfo &Info);
- /// Called to set constant rounding mode for floating point operations.
- void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
+ bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
+ TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc);
- /// Called to set exception behavior for floating point operations.
- void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
+ void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
+ unsigned Depth, llvm::SmallBitVector &Used);
- /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
- /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
- void AddAlignmentAttributesForRecord(RecordDecl *RD);
+ 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);
- /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
- void AddMsStructLayoutForRecord(RecordDecl *RD);
+ 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());
- /// PushNamespaceVisibilityAttr - Note that we've entered a
- /// namespace with a visibility attribute.
- void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
- SourceLocation Loc);
+ /// @}
- /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used,
- /// add an appropriate visibility attribute.
- void AddPushedVisibilityAttribute(Decl *RD);
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- /// 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);
+ /// \name C++ Template Instantiation
+ /// Implementations are in SemaTemplateInstantiate.cpp
+ /// @{
- /// FreeVisContext - Deallocate and null out VisContext.
- void FreeVisContext();
+public:
+ /// A helper class for building up ExtParameterInfos.
+ class ExtParameterInfoBuilder {
+ SmallVector<FunctionProtoType::ExtParameterInfo, 16> Infos;
+ bool HasInteresting = false;
- /// 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);
+ 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);
- void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
- SourceLocation PragmaLoc,
- attr::ParsedSubjectMatchRuleSet Rules);
- void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
- const IdentifierInfo *Namespace);
+ if (!HasInteresting)
+ HasInteresting = (info != FunctionProtoType::ExtParameterInfo());
+ }
- /// Called on well-formed '\#pragma clang attribute pop'.
- void ActOnPragmaAttributePop(SourceLocation PragmaLoc,
- const IdentifierInfo *Namespace);
+ /// 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();
+ }
+ };
- /// Adds the attributes that have been specified using the
- /// '\#pragma clang attribute push' directives to the given declaration.
- void AddPragmaAttributes(Scope *S, Decl *D);
+ /// The current instantiation scope used to store local
+ /// variables.
+ LocalInstantiationScope *CurrentInstantiationScope;
- void DiagnoseUnterminatedPragmaAttribute();
+ typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>>
+ UnparsedDefaultArgInstantiationsMap;
- /// Called on well formed \#pragma clang optimize.
- void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
+ /// 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;
- /// #pragma optimize("[optimization-list]", on | off).
- void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn);
+ /// 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,
- /// Call on well formed \#pragma function.
- void
- ActOnPragmaMSFunction(SourceLocation Loc,
- const llvm::SmallVectorImpl<StringRef> &NoBuiltins);
-
- /// 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 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,
- /// 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 instantiating a default argument for a function.
+ /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
+ /// provides the template arguments as specified.
+ DefaultFunctionArgumentInstantiation,
- /// 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 substituting explicit template arguments provided for
+ /// a function template. The entity is a FunctionTemplateDecl.
+ ExplicitTemplateArgumentSubstitution,
- /// 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 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,
- /// 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 substituting into a lambda expression.
+ LambdaExpressionSubstitution,
- /// 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 substituting prior template arguments into a new
+ /// template parameter. The template parameter itself is either a
+ /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+ PriorTemplateArgumentSubstitution,
- /// 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 checking the validity of a default template argument that
+ /// has been used when naming a template-id.
+ DefaultTemplateArgumentChecking,
- /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
- /// declaration.
- void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
- Expr *OE);
+ /// We are computing the exception specification for a defaulted special
+ /// member function.
+ ExceptionSpecEvaluation,
- /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
- /// declaration.
- void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
- Expr *ParamExpr);
+ /// We are instantiating the exception specification for a function
+ /// template which was deferred until it was needed.
+ ExceptionSpecInstantiation,
- /// AddAlignValueAttr - Adds an align_value attribute to a particular
- /// declaration.
- void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
+ /// We are instantiating a requirement of a requires expression.
+ RequirementInstantiation,
- /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
- void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
- StringRef Annot, MutableArrayRef<Expr *> Args);
+ /// We are checking the satisfaction of a nested requirement of a requires
+ /// expression.
+ NestedRequirementConstraintsCheck,
- /// 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<Expr *> Args);
+ /// We are declaring an implicit special member function.
+ DeclaringSpecialMember,
- /// Create an CUDALaunchBoundsAttr attribute.
- CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI,
- Expr *MaxThreads,
- Expr *MinBlocks,
- Expr *MaxBlocks);
+ /// We are declaring an implicit 'operator==' for a defaulted
+ /// 'operator<=>'.
+ DeclaringImplicitEqualityComparison,
- /// 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 defining a synthesized function (such as a defaulted special
+ /// member).
+ DefiningSynthesizedFunction,
- /// AddModeAttr - Adds a mode attribute to a particular declaration.
- void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,
- bool InInstantiation = false);
+ // 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 AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
- ParameterABI ABI);
+ // We are substituting template arguments into a constraint expression.
+ ConstraintSubstitution,
- enum class RetainOwnershipKind {NS, CF, OS};
- void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
- RetainOwnershipKind K, bool IsTemplateInstantiation);
+ // We are normalizing a constraint expression.
+ ConstraintNormalization,
- /// Create an AMDGPUWavesPerEUAttr attribute.
- AMDGPUFlatWorkGroupSizeAttr *
- CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,
- Expr *Max);
+ // Instantiating a Requires Expression parameter clause.
+ RequirementParameterInstantiation,
- /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
- /// attribute to a particular declaration.
- void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
- Expr *Min, Expr *Max);
+ // We are substituting into the parameter mapping of an atomic constraint
+ // during normalization.
+ ParameterMappingSubstitution,
- /// Create an AMDGPUWavesPerEUAttr attribute.
- AMDGPUWavesPerEUAttr *
- CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min,
- Expr *Max);
+ /// We are rewriting a comparison operator in terms of an operator<=>.
+ RewritingOperatorAsSpaceship,
- /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
- /// particular declaration.
- void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
- Expr *Min, Expr *Max);
+ /// We are initializing a structured binding.
+ InitializingStructuredBinding,
- bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
+ /// We are marking a class as __dllexport.
+ MarkingClassDllexported,
- //===--------------------------------------------------------------------===//
- // 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);
+ /// We are building an implied call from __builtin_dump_struct. The
+ /// arguments are in CallArgs.
+ BuildingBuiltinDumpStructCall,
- 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);
+ /// 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,
- // 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);
+ /// We are building deduction guides for a class.
+ BuildingDeductionGuides,
+ } Kind;
- // 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);
+ /// Was the enclosing context a non-instantiation SFINAE context?
+ bool SavedInNonInstantiationSFINAEContext;
- //===--------------------------------------------------------------------===//
- // OpenMP directives and clauses.
- //
-private:
- void *VarDataSharingAttributesStack;
+ /// The point of instantiation or synthesis within the source code.
+ SourceLocation PointOfInstantiation;
- struct DeclareTargetContextInfo {
- struct MapInfo {
- OMPDeclareTargetDeclAttr::MapTypeTy MT;
- SourceLocation Loc;
- };
- /// Explicitly listed variables and functions in a 'to' or 'link' clause.
- llvm::DenseMap<NamedDecl *, MapInfo> ExplicitlyMapped;
+ /// The entity that is being synthesized.
+ Decl *Entity;
- /// The 'device_type' as parsed from the clause.
- OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
+ /// The template (or partial specialization) in which we are
+ /// performing the instantiation, for substitutions of prior template
+ /// arguments.
+ NamedDecl *Template;
- /// The directive kind, `begin declare target` or `declare target`.
- OpenMPDirectiveKind Kind;
+ union {
+ /// The list of template arguments we are substituting, if they
+ /// are not part of the entity.
+ const TemplateArgument *TemplateArgs;
- /// The directive with indirect clause.
- std::optional<Expr *> Indirect;
+ /// The list of argument expressions in a synthesized call.
+ const Expr *const *CallArgs;
+ };
- /// The directive location.
- SourceLocation Loc;
+ // 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;
- DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc)
- : Kind(Kind), Loc(Loc) {}
- };
+ /// The number of expressions in CallArgs.
+ unsigned NumCallArgs;
- /// Number of nested '#pragma omp declare target' directives.
- SmallVector<DeclareTargetContextInfo, 4> DeclareTargetNesting;
+ /// The special member being declared or defined.
+ CXXSpecialMember SpecialMember;
+ };
- /// Initialization of data-sharing attributes stack.
- void InitDataSharingAttributesStack();
- void DestroyDataSharingAttributesStack();
-
- /// Returns OpenMP nesting level for current directive.
- unsigned getOpenMPNestingLevel() const;
+ ArrayRef<TemplateArgument> template_arguments() const {
+ assert(Kind != DeclaringSpecialMember);
+ return {TemplateArgs, NumTemplateArgs};
+ }
- /// Adjusts the function scopes index for the target-based regions.
- void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
- unsigned Level) const;
+ /// The template deduction info object associated with the
+ /// substitution or checking of explicit or deduced template arguments.
+ sema::TemplateDeductionInfo *DeductionInfo;
- /// Returns the number of scopes associated with the construct on the given
- /// OpenMP level.
- int getNumberOfConstructScopes(unsigned Level) const;
+ /// The source range that covers the construct that cause
+ /// the instantiation, e.g., the template-id that causes a class
+ /// template instantiation.
+ SourceRange InstantiationRange;
- /// Push new OpenMP function region for non-capturing function.
- void pushOpenMPFunctionRegion();
+ CodeSynthesisContext()
+ : Kind(TemplateInstantiation),
+ SavedInNonInstantiationSFINAEContext(false), Entity(nullptr),
+ Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0),
+ DeductionInfo(nullptr) {}
- /// Pop OpenMP function region for non-capturing function.
- void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI);
+ /// Determines whether this template is an actual instantiation
+ /// that should be counted toward the maximum instantiation depth.
+ bool isInstantiationRecord() const;
+ };
- /// Analyzes and checks a loop nest for use by a loop transformation.
+ /// A stack object to be created when performing template
+ /// instantiation.
///
- /// \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.
+ /// 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.
///
- /// \return Whether there was any error.
- bool checkTransformableLoopNest(
- OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
- SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
- Stmt *&Body,
- SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
- &OriginalInits);
+ /// 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());
- /// Helper to keep information about the current `omp begin/end declare
- /// variant` nesting.
- struct OMPDeclareVariantScope {
- /// The associated OpenMP context selector.
- OMPTraitInfo *TI;
+ 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());
- /// The associated OpenMP context selector mangling.
- std::string NameSuffix;
+ /// Note that we are instantiating a default argument in a
+ /// template-id.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateParameter Param, TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
- OMPDeclareVariantScope(OMPTraitInfo &TI);
- };
+ /// 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<TemplateArgument> TemplateArgs,
+ CodeSynthesisContext::SynthesisKind Kind,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
- /// Return the OMPTraitInfo for the surrounding scope, if any.
- OMPTraitInfo *getOMPTraitInfoForSurroundingScope() {
- return OMPDeclareVariantScopes.empty() ? nullptr
- : OMPDeclareVariantScopes.back().TI;
- }
+ /// Note that we are instantiating as part of template
+ /// argument deduction for a class template declaration.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Template,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
- /// The current `omp begin/end declare variant` scopes.
- SmallVector<OMPDeclareVariantScope, 4> OMPDeclareVariantScopes;
+ /// 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<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
- /// The current `omp begin/end assumes` scopes.
- SmallVector<AssumptionAttr *, 4> OMPAssumeScoped;
+ /// 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<TemplateArgument> TemplateArgs,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange = SourceRange());
- /// All `omp assumes` we encountered so far.
- SmallVector<AssumptionAttr *, 4> OMPAssumeGlobal;
+ /// Note that we are instantiating a default argument for a function
+ /// parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ParmVarDecl *Param,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange = SourceRange());
- /// 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<OMPClause *> 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<OMPClause *> &ClausesWithoutBind,
- ArrayRef<OMPClause *> Clauses,
- OpenMPBindClauseKind &BindKind,
- OpenMPDirectiveKind &Kind,
- OpenMPDirectiveKind &PrevMappedDirective,
- SourceLocation StartLoc, SourceLocation EndLoc,
- const DeclarationNameInfo &DirName,
- OpenMPDirectiveKind CancelRegion);
+ /// Note that we are substituting prior template arguments into a
+ /// non-type parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ NonTypeTemplateParmDecl *Param,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ 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<FunctionDecl *> &Bases);
+ /// Note that we are substituting prior template arguments into a
+ /// template template parameter.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ NamedDecl *Template,
+ TemplateTemplateParmDecl *Param,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange);
- /// 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<FunctionDecl *> &Bases);
+ /// 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<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange);
- /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`.
- void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D);
+ 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<TemplateArgument> TemplateArgs,
+ SourceRange InstantiationRange);
- /// Can we exit an OpenMP declare variant scope at the moment.
- bool isInOpenMPDeclareVariantScope() const {
- return !OMPDeclareVariantScopes.empty();
- }
+ 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);
- ExprResult
- VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
- bool StrictlyPositive = true,
- bool SuppressExprDiags = false);
+ struct ConstraintNormalization {};
+ /// \brief Note that we are normalizing a constraint expression.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ConstraintNormalization, NamedDecl *Template,
+ SourceRange InstantiationRange);
- /// 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);
+ 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);
- /// Handle a `omp begin declare variant`.
- void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI);
+ /// \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());
- /// Handle a `omp end declare variant`.
- void ActOnOpenMPEndDeclareVariant();
+ /// \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());
- /// 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);
+ /// \brief Note that we are checking a requires clause.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ const RequiresExpr *E,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange);
- /// Function tries to capture lambda's captured variables in the OpenMP region
- /// before the original lambda is captured.
- void tryCaptureOpenMPLambdas(ValueDecl *V);
+ struct BuildingDeductionGuidesTag {};
+ /// \brief Note that we are building deduction guides.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ TemplateDecl *Entity, BuildingDeductionGuidesTag,
+ SourceRange InstantiationRange = SourceRange());
- /// 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;
+ /// Note that we have finished instantiating this template.
+ void Clear();
- /// 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() { Clear(); }
- /// 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);
+ /// Determines whether we have exceeded the maximum
+ /// recursive template instantiations.
+ bool isInvalid() const { return Invalid; }
- ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
- ExprObjectKind OK, SourceLocation Loc);
+ /// Determine whether we are already instantiating this
+ /// specialization in some surrounding active instantiation.
+ bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
- /// If the current region is a loop-based region, mark the start of the loop
- /// construct.
- void startOpenMPLoop();
+ private:
+ Sema &SemaRef;
+ bool Invalid;
+ bool AlreadyInstantiating;
+ bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange);
- /// If the current region is a range loop-based region, mark the start of the
- /// loop construct.
- void startOpenMPCXXRangeFor();
+ InstantiatingTemplate(
+ Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
+ SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
+ Decl *Entity, NamedDecl *Template = nullptr,
+ ArrayRef<TemplateArgument> TemplateArgs = std::nullopt,
+ sema::TemplateDeductionInfo *DeductionInfo = nullptr);
- /// 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;
+ InstantiatingTemplate(const InstantiatingTemplate&) = delete;
- /// 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);
+ InstantiatingTemplate&
+ operator=(const InstantiatingTemplate&) = delete;
+ };
- /// 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;
+ bool
+ SubstTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateArgumentListInfo &Outputs);
- /// 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;
+ MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
+ const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
+ std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
+ bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
+ bool ForConstraintInstantiation = false,
+ bool SkipForSpecialization = false);
- 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);
+ /// RAII object to handle the state changes required to synthesize
+ /// a function body.
+ class SynthesizedFunctionScope {
+ Sema &S;
+ Sema::ContextRAII SavedContext;
+ bool PushedCodeSynthesisContext = false;
- /// 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:
+ SynthesizedFunctionScope(Sema &S, DeclContext *DC)
+ : S(S), SavedContext(S, DC) {
+ auto *FD = dyn_cast<FunctionDecl>(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.back().InImmediateEscalatingFunctionContext =
+ S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
+ } else
+ assert(isa<ObjCMethodDecl>(DC));
+ }
- /// Called on well-formed '\#pragma omp metadirective' after parsing
- /// of the associated statement.
- StmtResult ActOnOpenMPMetaDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
+ void addContextNote(SourceLocation UseLoc) {
+ assert(!PushedCodeSynthesisContext);
- // 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<Expr *> VarList);
- /// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
- OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
- ArrayRef<Expr *> VarList);
- /// Called on well-formed '#pragma omp allocate'.
- DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc,
- ArrayRef<Expr *> VarList,
- ArrayRef<OMPClause *> Clauses,
- DeclContext *Owner = nullptr);
+ Sema::CodeSynthesisContext Ctx;
+ Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction;
+ Ctx.PointOfInstantiation = UseLoc;
+ Ctx.Entity = cast<Decl>(S.CurContext);
+ S.pushCodeSynthesisContext(Ctx);
- /// Called on well-formed '#pragma omp [begin] assume[s]'.
- void ActOnOpenMPAssumesDirective(SourceLocation Loc,
- OpenMPDirectiveKind DKind,
- ArrayRef<std::string> Assumptions,
- bool SkippedClauses);
+ PushedCodeSynthesisContext = true;
+ }
- /// Check if there is an active global `omp begin assumes` directive.
- bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); }
+ ~SynthesizedFunctionScope() {
+ if (PushedCodeSynthesisContext)
+ S.popCodeSynthesisContext();
+ if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext)) {
+ FD->setWillHaveBody(false);
+ S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction());
+ }
+ S.PopExpressionEvaluationContext();
+ S.PopFunctionScopeInfo();
+ }
+ };
- /// Check if there is an active global `omp assumes` directive.
- bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); }
+ /// 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<CodeSynthesisContext, 16> CodeSynthesisContexts;
- /// Called on well-formed '#pragma omp end assumes'.
- void ActOnOpenMPEndAssumesDirective();
+ /// Specializations whose definitions are currently being instantiated.
+ llvm::DenseSet<std::pair<Decl *, unsigned>> InstantiatingSpecializations;
- /// Called on well-formed '#pragma omp requires'.
- DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc,
- ArrayRef<OMPClause *> ClauseList);
- /// Check restrictions on Requires directive
- OMPRequiresDecl *CheckOMPRequiresDecl(SourceLocation Loc,
- ArrayRef<OMPClause *> 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<std::pair<QualType, SourceLocation>> 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);
+ /// Non-dependent types used in templates that have already been instantiated
+ /// by some template instantiation.
+ llvm::DenseSet<QualType> InstantiatedNonDependentTypes;
- /// 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<OMPClause *> 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;
+ /// Extra modules inspected when performing a lookup during a template
+ /// instantiation. Computed lazily.
+ SmallVector<Module*, 16> CodeSynthesisContextLookupModules;
- /// Called on the start of target region i.e. '#pragma omp declare target'.
- bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
+ /// 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<Module*> LookupModulesCache;
- /// Called at the end of target region i.e. '#pragma omp end declare target'.
- const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective();
+ /// Map from the most recent declaration of a namespace to the most
+ /// recent visible declaration of that namespace.
+ llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache;
- /// 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);
+ /// 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;
- /// Report unterminated 'omp declare target' or 'omp begin declare target' at
- /// the end of a compilation unit.
- void DiagnoseUnterminatedOpenMPDeclareTarget();
+ /// 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;
- /// Searches for the provided declaration name for OpenMP declare target
- /// directive.
- NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope,
- CXXScopeSpec &ScopeSpec,
- const DeclarationNameInfo &Id);
+ /// 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;
- /// Called on correct id-expression from the '#pragma omp declare target'.
- void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
- OMPDeclareTargetDeclAttr::MapTypeTy MT,
- DeclareTargetContextInfo &DTCI);
+ /// 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<std::unique_ptr<TemplateInstantiationCallback>>
+ TemplateInstCallbacks;
- /// Check declaration inside target region.
- void
- checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
- SourceLocation IdLoc = SourceLocation());
+ /// 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;
- /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
- /// directive.
- void ActOnOpenMPDeclareTargetInitializer(Decl *D);
+ /// 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;
- /// 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);
+ public:
+ ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
+ : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+ Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
+ }
- /// Return true if currently in OpenMP task with untied clause context.
- bool isInOpenMPTaskUntiedContext() const;
+ ~ArgumentPackSubstitutionIndexRAII() {
+ Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
+ }
+ };
- /// Return true inside OpenMP declare target region.
- bool isInOpenMPDeclareTargetContext() const {
- return !DeclareTargetNesting.empty();
+ friend class ArgumentPackSubstitutionRAII;
+
+ void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
+ void popCodeSynthesisContext();
+
+ void PrintContextStack() {
+ if (!CodeSynthesisContexts.empty() &&
+ CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
+ PrintInstantiationStack();
+ LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
+ }
+ if (PragmaAttributeCurrentTargetDecl)
+ PrintPragmaAttributeInstantiationPoint();
}
- /// Return true inside OpenMP target region.
- bool isInOpenMPTargetExecutionDirective() const;
+ void PrintInstantiationStack();
- /// Return the number of captured regions created for an OpenMP directive.
- static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
+ /// 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<sema::TemplateDeductionInfo *> isSFINAEContext() const;
- /// Initialization of captured region for OpenMP region.
- void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
+ TypeSourceInfo *SubstType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity,
+ bool AllowDeducedTST = false);
- /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
- /// an OpenMP loop directive.
- StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
+ QualType SubstType(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
- /// 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);
+ TypeSourceInfo *SubstType(TypeLoc TL,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
- /// End of OpenMP region.
+ 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<QualType> &ExceptionStorage,
+ const MultiLevelTemplateArgumentList &Args);
+ ParmVarDecl *
+ SubstParmVarDecl(ParmVarDecl *D,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ int indexAdjustment, std::optional<unsigned> NumExpansions,
+ bool ExpectParameterPack, bool EvaluateConstraints = true);
+ bool SubstParmTypes(SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
+ const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<QualType> &ParamTypes,
+ SmallVectorImpl<ParmVarDecl *> *OutParams,
+ ExtParameterInfoBuilder &ParamInfos);
+ bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool ForCallExpr = false);
+ ExprResult SubstExpr(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ // A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator
+ // to disable constraint evaluation, then restore the state.
+ template <typename InstTy> struct ConstraintEvalRAII {
+ InstTy &TI;
+ bool OldValue;
+
+ ConstraintEvalRAII(InstTy &TI)
+ : TI(TI), OldValue(TI.getEvaluateConstraints()) {
+ TI.setEvaluateConstraints(false);
+ }
+ ~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); }
+ };
+
+ // 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 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<OMPClause *> Clauses);
- StmtResult ActOnOpenMPExecutableDirective(
- OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
- OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> 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<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- using VarsWithInheritedDSAType =
- llvm::SmallDenseMap<const ValueDecl *, const Expr *, 4>;
- /// Called on well-formed '\#pragma omp simd' after parsing
- /// of the associated statement.
- StmtResult
- ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp for' after parsing
- /// of the associated statement.
- StmtResult
- ActOnOpenMPForDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp single' after parsing of the
- /// associated statement.
- StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> 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<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp parallel for' after parsing
- /// of the associated statement.
- StmtResult ActOnOpenMPParallelForDirective(
- ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp parallel masked' after
- /// parsing of the associated statement.
- StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp parallel sections' after
- /// parsing of the associated statement.
- StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp task' after parsing of the
- /// associated statement.
- StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp taskgroup'.
- StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp flush'.
- StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp depobj'.
- StmtResult ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp scan'.
- StmtResult ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp ordered' after parsing of the
- /// associated statement.
- StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp atomic' after parsing of the
- /// associated statement.
- StmtResult ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp target' after parsing of the
- /// associated statement.
- StmtResult ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp target data' after parsing of
- /// the associated statement.
- StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- Stmt *AStmt);
- /// Called on well-formed '\#pragma omp target parallel' after
- /// parsing of the associated statement.
- StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp teams loop' after parsing of the
- /// associated statement.
- StmtResult ActOnOpenMPTeamsGenericLoopDirective(
- ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
- SourceLocation StartLoc,
- SourceLocation EndLoc,
- OpenMPDirectiveKind CancelRegion);
- /// Called on well-formed '\#pragma omp taskloop' after parsing of the
- /// associated statement.
- StmtResult
- ActOnOpenMPTaskLoopDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses, Stmt *AStmt,
- SourceLocation StartLoc, SourceLocation EndLoc,
- VarsWithInheritedDSAType &VarsWithImplicitDSA);
- /// Called on well-formed '\#pragma omp target update'.
- StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
- /// Called on well-formed '\#pragma omp interop'.
- StmtResult ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp dispatch' after parsing of the
- // /associated statement.
- StmtResult ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc);
- /// Called on well-formed '\#pragma omp masked' after parsing of the
- // /associated statement.
- StmtResult ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> 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<Expr *> Exprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<Expr *> &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<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
+
+ /// The queue of implicit template instantiations that are required
+ /// but have not yet been performed.
+ std::deque<PendingImplicitInstantiation> PendingInstantiations;
+
+ /// Queue of implicit template instantiations that cannot be performed
+ /// eagerly.
+ SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations;
+
+ SmallVector<SmallVector<VTableUse, 16>, 8> SavedVTableUses;
+ SmallVector<std::deque<PendingImplicitInstantiation>, 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<PendingImplicitInstantiation> 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<PendingImplicitInstantiation>
+ 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<LateInstantiatedAttribute, 16> 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<TemplateArgument> &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<UnexpandedParameterPack> 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<UnexpandedParameterPack> &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<UnexpandedParameterPack> &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<UnexpandedParameterPack> &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<UnexpandedParameterPack> &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<UnexpandedParameterPack> &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<UnexpandedParameterPack> &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<unsigned> NumExpansions);
+
+ /// Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
+ SourceLocation EllipsisLoc,
+ std::optional<unsigned> 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<unsigned> 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<UnexpandedParameterPack> Unexpanded,
+ const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand,
+ bool &RetainExpansion, std::optional<unsigned> &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<unsigned> 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<unsigned> &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<unsigned> 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<Expr *> 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<unsigned> 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<NamedDecl>(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<NamedDecl>(D->getCanonicalDecl());
+ return llvm::find(SatisfactionStack,
+ SatisfactionStackEntryTy{Can, ID}) !=
+ SatisfactionStack.end();
+ }
+
+ using SatisfactionStackEntryTy =
+ std::pair<const NamedDecl *, llvm::FoldingSetNodeID>;
+
+ // 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<SatisfactionStackEntryTy, 10>
+ BackupSatisfactionStack;
+ Sema &SemaRef;
+
+ public:
+ SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
+ SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+ }
+
+ ~SatisfactionStackResetRAII() {
+ SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+ }
+ };
+
+ void SwapSatisfactionStack(
+ llvm::SmallVectorImpl<SatisfactionStackEntryTy> &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<const Expr *> ConstraintExprs,
+ const MultiLevelTemplateArgumentList &TemplateArgLists,
+ SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
+ llvm::SmallVector<Expr *, 4> 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<const Expr *> ConstraintExprs,
+ llvm::SmallVectorImpl<Expr *> &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<TemplateArgument> 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<const Expr *> 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<const Expr *> AC1,
+ NamedDecl *D2, MutableArrayRef<const Expr *> 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<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> 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<std::pair<NamedDecl *, NamedDecl *>, 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<NamedDecl *, NormalizedConstraint *>
+ NormalizationCache;
+
+ llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
+ SatisfactionCache;
+
+ // The current stack of constraint satisfactions, so we can exit-early.
+ llvm::SmallVector<SatisfactionStackEntryTy, 10>
+ 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<ArrayRef<TemplateArgument>> 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<MultiLevelTemplateArgumentList>
+ SetupConstraintCheckingTemplateArgumentsAndScope(
+ FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> 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<Decl *> protocols,
+ ArrayRef<SourceLocation> protocolLocs,
+ SourceLocation rAngleLoc);
+
+ /// Build a specialized and/or protocol-qualified Objective-C type.
+ TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
+ Scope *S,
+ SourceLocation Loc,
+ ParsedType BaseType,
+ SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<ParsedType> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<Decl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc);
+
+ /// Build an Objective-C type parameter type.
+ QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+ SourceLocation ProtocolLAngleLoc,
+ ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc,
+ bool FailOnError = false);
+
+ /// Build an Objective-C object pointer type.
+ QualType BuildObjCObjectType(
+ QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
+ bool FailOnError, bool Rebuilding);
+
+ 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);
- /// Called on well-formed '\#pragma omp loop' after parsing of the
- /// associated statement.
- StmtResult ActOnOpenMPGenericLoopDirective(
- ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
- SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
+ SourceLocation AttrLoc);
- /// 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);
+ /// Same as above, but constructs the AddressSpace index if not provided.
+ QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
+ SourceLocation AttrLoc);
- /// 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<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
- ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
- ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR);
+ bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
- /// 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<std::pair<FunctionDecl *, Expr *>>
- checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef,
- OMPTraitInfo &TI, unsigned NumAppendArgs,
- SourceRange SR);
+ bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
- /// 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<Expr *> AdjustArgsNothing,
- ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
- ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
- SourceLocation AppendArgsLoc, SourceRange SR);
+ /// 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<QualType> ParamTypes,
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionProtoType::ExtProtoInfo &EPI);
- 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<Expr *> 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);
+ 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<unsigned> Arguments, Expr *Expr,
- SourceLocation StartLoc, SourceLocation LParenLoc,
- ArrayRef<SourceLocation> 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 <typename... Ts>
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> 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<QualType> 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 <typename... Ts>
+ bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID,
+ const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> 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 <typename... Ts>
+ bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID,
+ const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> 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<NamedDecl*>(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<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
- MapTypeModifiers;
- SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
- MapTypeModifiersLoc;
- SmallVector<OpenMPMotionModifierKind, NumberOfOMPMotionModifiers>
- MotionModifiers;
- SmallVector<SourceLocation, NumberOfOMPMotionModifiers> 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<Expr *> Vars,
- const OMPVarListLocTy &Locs,
- OpenMPVarListDataTy &Data);
- /// Called on well-formed 'inclusive' clause.
- OMPClause *ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'exclusive' clause.
- OMPClause *ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'allocate' clause.
- OMPClause *
- ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef<Expr *> VarList,
- SourceLocation StartLoc, SourceLocation ColonLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc);
- /// Called on well-formed 'private' clause.
- OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'firstprivate' clause.
- OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'lastprivate' clause.
- OMPClause *ActOnOpenMPLastprivateClause(
- ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
- SourceLocation LPKindLoc, SourceLocation ColonLoc,
- SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
- /// Called on well-formed 'shared' clause.
- OMPClause *ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'reduction' clause.
- OMPClause *ActOnOpenMPReductionClause(
- ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
- SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation ModifierLoc, SourceLocation ColonLoc,
- SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
- const DeclarationNameInfo &ReductionId,
- ArrayRef<Expr *> UnresolvedReductions = std::nullopt);
- /// Called on well-formed 'task_reduction' clause.
- OMPClause *ActOnOpenMPTaskReductionClause(
- ArrayRef<Expr *> VarList, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
- CXXScopeSpec &ReductionIdScopeSpec,
- const DeclarationNameInfo &ReductionId,
- ArrayRef<Expr *> UnresolvedReductions = std::nullopt);
- /// Called on well-formed 'in_reduction' clause.
- OMPClause *ActOnOpenMPInReductionClause(
- ArrayRef<Expr *> VarList, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
- CXXScopeSpec &ReductionIdScopeSpec,
- const DeclarationNameInfo &ReductionId,
- ArrayRef<Expr *> UnresolvedReductions = std::nullopt);
- /// Called on well-formed 'linear' clause.
- OMPClause *ActOnOpenMPLinearClause(
- ArrayRef<Expr *> 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<Expr *> VarList,
- Expr *Alignment,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'copyin' clause.
- OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'copyprivate' clause.
- OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
- /// Called on well-formed 'flush' pseudo clause.
- OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr *> 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<Expr *> 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<OpenMPMapModifierKind> MapTypeModifiers,
- ArrayRef<SourceLocation> MapTypeModifiersLoc,
- CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
- OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
- SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
- const OMPVarListLocTy &Locs, bool NoDiagnose = false,
- ArrayRef<Expr *> 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<OpenMPMotionModifierKind> MotionModifiers,
- ArrayRef<SourceLocation> MotionModifiersLoc,
- CXXScopeSpec &MapperIdScopeSpec,
- DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
- ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
- ArrayRef<Expr *> UnresolvedMappers = std::nullopt);
- /// Called on well-formed 'from' clause.
- OMPClause *
- ActOnOpenMPFromClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
- ArrayRef<SourceLocation> MotionModifiersLoc,
- CXXScopeSpec &MapperIdScopeSpec,
- DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
- ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
- ArrayRef<Expr *> UnresolvedMappers = std::nullopt);
- /// Called on well-formed 'use_device_ptr' clause.
- OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
- const OMPVarListLocTy &Locs);
- /// Called on well-formed 'use_device_addr' clause.
- OMPClause *ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
- const OMPVarListLocTy &Locs);
- /// Called on well-formed 'is_device_ptr' clause.
- OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
- const OMPVarListLocTy &Locs);
- /// Called on well-formed 'has_device_addr' clause.
- OMPClause *ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
- const OMPVarListLocTy &Locs);
- /// Called on well-formed 'nontemporal' clause.
- OMPClause *ActOnOpenMPNontemporalClause(ArrayRef<Expr *> 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<UsesAllocatorsData> Data);
- /// Called on well-formed 'affinity' clause.
- OMPClause *ActOnOpenMPAffinityClause(SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc, Expr *Modifier,
- ArrayRef<Expr *> 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<Selector, SourceLocation> ReferencedSelectors;
- /// Called on well-formed 'doacross' clause.
- OMPClause *
- ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,
- SourceLocation DepLoc, SourceLocation ColonLoc,
- ArrayRef<Expr *> VarList, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc);
+ class GlobalMethodPool {
+ public:
+ using Lists = std::pair<ObjCMethodList, ObjCMethodList>;
+ using iterator = llvm::DenseMap<Selector, Lists>::iterator;
+ iterator begin() { return Methods.begin(); }
+ iterator end() { return Methods.end(); }
+ iterator find(Selector Sel) { return Methods.find(Sel); }
+ std::pair<iterator, bool> insert(std::pair<Selector, Lists> &&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<const Attr *> Attrs,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation EndLoc);
+ private:
+ llvm::DenseMap<Selector, Lists> 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 <typename T,
+ typename = std::enable_if_t<std::is_base_of<NamedDecl, T>::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<Selector, 8> 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);
+
+ ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
+ ArrayRef<Decl *> 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<ParsedType> 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<ParsedType> SuperTypeArgs,
+ SourceRange SuperTypeArgsRange);
+
+ void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
+ SmallVectorImpl<SourceLocation> &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<ObjCProtocolDecl> &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<Decl *> Decls);
+
+ DeclGroupPtrTy
+ ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+ ArrayRef<IdentifierLocPair> IdentList,
+ const ParsedAttributesView &attrList);
+
+ void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
+ ArrayRef<IdentifierLocPair> ProtocolId,
+ SmallVectorImpl<Decl *> &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<IdentifierInfo *> identifiers,
+ ArrayRef<SourceLocation> identifierLocs,
+ SourceLocation rAngleLoc,
+ SourceLocation &typeArgsLAngleLoc,
+ SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc,
+ SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols,
+ SourceLocation &protocolRAngleLoc,
+ bool warnOnIncompleteProtocols);
+
+ void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+ ObjCInterfaceDecl *ID);
+
+ Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
+ ArrayRef<Decl *> allMethods = std::nullopt,
+ ArrayRef<DeclGroupPtrTy> allTUVars = std::nullopt);
- /// 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
+ 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;
};
- static bool isCast(CheckedConversionKind CCK) {
- return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
- CCK == CCK_OtherCast;
- }
+ Decl *ActOnMethodDeclaration(
+ Scope *S,
+ SourceLocation BeginLoc, // location of the + or -.
+ SourceLocation EndLoc, // location of the ; or {.
+ tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ ArrayRef<SourceLocation> 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);
- /// 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);
+ bool CheckARCMethodDecl(ObjCMethodDecl *method);
- /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
- /// to the conversion from scalar type ScalarTy to the Boolean type.
- static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
+ bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
- /// IgnoredValueConversions - Given that an expression's result is
- /// syntactically ignored, perform any conversions that are
- /// required.
- ExprResult IgnoredValueConversions(Expr *E);
+ /// 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);
- // 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);
+ /// Describes the compatibility of a result type with its method.
+ enum ResultTypeCompatibilityKind {
+ RTC_Compatible,
+ RTC_Incompatible,
+ RTC_Unknown
+ };
- /// CallExprUnaryConversions - a special case of an unary conversion
- /// performed on a function designator of a call expression.
- ExprResult CallExprUnaryConversions(Expr *E);
+ void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
+ ObjCMethodDecl *overridden);
- // DefaultFunctionArrayConversion - converts functions and arrays
- // to their respective pointers (C99 6.3.2.1).
- ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
+ void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
+ ObjCInterfaceDecl *CurrentClass,
+ ResultTypeCompatibilityKind RTC);
- // DefaultFunctionArrayLvalueConversion - converts functions and
- // arrays to their respective pointers and performs the
- // lvalue-to-rvalue conversion.
- ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
- bool Diagnose = true);
+ /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
+ /// pool.
+ void AddAnyMethodToGlobalPool(Decl *D);
- // 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);
+ void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+ bool isObjCMethodDecl(Decl *D) {
+ return D && isa<ObjCMethodDecl>(D);
+ }
- // 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);
+ /// 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);
- /// 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);
+ void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
- // Used for emitting the right warning by DefaultVariadicArgumentPromotion
- enum VariadicCallType {
- VariadicFunction,
- VariadicBlock,
- VariadicMethod,
- VariadicConstructor,
- VariadicDoesNotApply
- };
+ void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
+ ObjCMethodDecl *Overridden,
+ bool IsProtocolMethodDecl);
- VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
- const FunctionProtoType *Proto,
- Expr *Fn);
+ /// WarnExactTypedMethods - This routine issues a warning if method
+ /// implementation declaration matches exactly that of its declaration.
+ void WarnExactTypedMethods(ObjCMethodDecl *Method,
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
- // 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
- };
+ /// 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);
- // Determines which VarArgKind fits an expression.
- VarArgKind isValidVarArgType(const QualType &Ty);
+ /// 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);
- /// 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);
+ /// 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);
- /// 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);
+ DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ ArrayRef<ObjCTypeParamList *> TypeParamLists,
+ unsigned NumElts);
-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);
+ /// 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);
-public:
- /// Check to see if a given expression could have '.c_str()' called on it.
- bool hasCStrMethod(const Expr *E);
+ /// Add the given method to the list of globally-known methods.
+ void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
- /// GatherArgumentsForCall - Collector argument expressions for various
- /// form of call prototypes.
- bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
- const FunctionProtoType *Proto,
- unsigned FirstParam, ArrayRef<Expr *> Args,
- SmallVectorImpl<Expr *> &AllArgs,
- VariadicCallType CallType = VariadicDoesNotApply,
- bool AllowExplicit = false,
- bool IsListInitialization = false);
+ void ReadMethodPool(Selector Sel);
+ void updateOutOfDateSelector(Selector Sel);
- // 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);
+ /// - 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<ObjCMethodDecl*>& Methods,
+ bool InstanceFirst, bool CheckTheOther,
+ const ObjCObjectType *TypeBound = nullptr);
- /// 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,
- };
+ bool
+ AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+ SourceRange R, bool receiverIdOrClass,
+ SmallVectorImpl<ObjCMethodDecl*>& Methods);
- // 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);
+ void
+ DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+ Selector Sel, SourceRange R,
+ bool receiverIdOrClass);
- /// 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,
+ const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
+ QualType ObjectType=QualType());
+ /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+ /// implementation.
+ ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
- /// PointerToInt - The assignment converts a pointer to an int, which we
- /// accept as an extension.
- PointerToInt,
+ void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
- /// IntToPointer - The assignment converts an int to a pointer, which we
- /// accept as an extension.
- IntToPointer,
+ /// 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);
- /// FunctionVoidPointer - The assignment is between a function pointer and
- /// void*, which the standard doesn't allow, but we accept as an extension.
- FunctionVoidPointer,
+ void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+ IdentifierInfo *ClassName,
+ SmallVectorImpl<Decl *> &Decls);
- /// IncompatiblePointer - The assignment is between two pointers types that
- /// are not compatible, but we accept them as an extension.
- IncompatiblePointer,
+ VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ bool Invalid = false);
- /// IncompatibleFunctionPointer - The assignment is between two function
- /// pointers types that are not compatible, but we accept them as an
- /// extension.
- IncompatibleFunctionPointer,
+ Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
- /// 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,
+ /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+ /// initialization.
+ void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+ SmallVectorImpl<ObjCIvarDecl*> &Ivars);
- /// 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,
+ void DiagnoseUseOfUnimplementedSelectors();
- /// CompatiblePointerDiscardsQualifiers - The assignment discards
- /// c/v/r qualifiers, which we accept as an extension.
- CompatiblePointerDiscardsQualifiers,
+ /// 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);
- /// IncompatiblePointerDiscardsQualifiers - The assignment
- /// discards qualifiers that we don't permit to be discarded,
- /// like address spaces.
- IncompatiblePointerDiscardsQualifiers,
+ /// 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;
- /// 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,
+ /// 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);
+ }
- /// 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,
+ /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+ void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/false);
+ }
- /// IncompatibleVectors - The assignment is between two vector types that
- /// have the same size, which we accept as an extension.
- IncompatibleVectors,
+private:
+ /// AddMethodToGlobalPool - Add an instance or factory method to the global
+ /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
+ void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
- /// IntToBlockPointer - The assignment converts an int to a block
- /// pointer. We disallow this.
- IntToBlockPointer,
+ /// 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);
- /// IncompatibleBlockPointer - The assignment is between two block
- /// pointers types that are not compatible.
- IncompatibleBlockPointer,
+ /// @}
- /// IncompatibleObjCQualifiedId - The assignment is between a qualified
- /// id type and something else (that is incompatible with it). For example,
- /// "id <XXX>" = "Foo *", where "Foo *" doesn't implement the XXX protocol.
- IncompatibleObjCQualifiedId,
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
- /// object with __weak qualifier.
- IncompatibleObjCWeakRef,
+ /// \name ObjC Expressions
+ /// Implementations are in SemaExprObjC.cpp
+ /// @{
- /// Incompatible - We reject this conversion outright, it is invalid to
- /// represent it in the AST.
- Incompatible
- };
+public:
+ /// Caches identifiers/selectors for NSFoundation APIs.
+ std::unique_ptr<NSAPI> NSAPIObj;
- /// 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 Objective-C NSNumber class.
+ ObjCInterfaceDecl *NSNumberDecl;
- /// 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 Objective-C NSValue class.
+ ObjCInterfaceDecl *NSValueDecl;
- /// 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);
+ /// Pointer to NSNumber type (NSNumber *).
+ QualType NSNumberPointer;
- /// 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);
+ /// Pointer to NSValue type (NSValue *).
+ QualType NSValuePointer;
- /// 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 Objective-C NSNumber methods used to create NSNumber literals.
+ ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
- /// 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 Objective-C NSString class.
+ ObjCInterfaceDecl *NSStringDecl;
- // 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);
+ /// Pointer to NSString type (NSString *).
+ QualType NSStringPointer;
- bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+ /// The declaration of the stringWithUTF8String: method.
+ ObjCMethodDecl *StringWithUTF8StringMethod;
- bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+ /// The declaration of the valueWithBytes:objCType: method.
+ ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
- 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);
+ /// The declaration of the Objective-C NSArray class.
+ ObjCInterfaceDecl *NSArrayDecl;
- ExprResult PerformQualificationConversion(
- Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
- CheckedConversionKind CCK = CCK_ImplicitConversion);
+ /// The declaration of the arrayWithObjects:count: method.
+ ObjCMethodDecl *ArrayWithObjectsMethod;
- /// the following "Check" methods will return a valid/converted QualType
- /// or a null QualType (indicating an error diagnostic was issued).
+ /// The declaration of the Objective-C NSDictionary class.
+ ObjCInterfaceDecl *NSDictionaryDecl;
- /// 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);
+ /// The declaration of the dictionaryWithObjects:forKeys:count: method.
+ ObjCMethodDecl *DictionaryWithObjectsMethod;
- 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);
+ /// id<NSCopying> type.
+ QualType QIDNSCopying;
- 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);
+ /// will hold 'respondsToSelector:'
+ Selector RespondsToSelectorSel;
- 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
+ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+ Expr *BaseExpr,
+ SourceLocation OpLoc,
+ DeclarationName MemberName,
+ SourceLocation MemberLoc,
+ SourceLocation SuperLoc, QualType SuperType,
+ bool Super);
- QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
- SourceLocation QuestionLoc);
+ ExprResult
+ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc);
- bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
- SourceLocation QuestionLoc);
+ // ParseObjCStringLiteral - Parse Objective-C string literals.
+ ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ ArrayRef<Expr *> Strings);
- void DiagnoseAlwaysNonNullPointer(Expr *E,
- Expr::NullPointerConstantKind NullType,
- bool IsEqual, SourceRange Range);
+ ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
- /// 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);
+ /// 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);
- // type checking for sizeless vector binary operators.
- QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
- SourceLocation Loc, bool IsCompAssign,
- ArithConvKind OperationKind);
+ /// 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);
- /// 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);
+ ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
+ Expr *IndexExpr,
+ ObjCMethodDecl *getterMethod,
+ ObjCMethodDecl *setterMethod);
- bool isValidSveBitcast(QualType srcType, QualType destType);
- bool isValidRVVBitcast(QualType srcType, QualType destType);
+ ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
+ MutableArrayRef<ObjCDictionaryElement> Elements);
- bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
+ ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
+ TypeSourceInfo *EncodedTypeInfo,
+ SourceLocation RParenLoc);
- 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 ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncodeLoc,
+ SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc);
- /// type checking declaration initializers (C99 6.7.8)
- bool CheckForConstantInitializer(Expr *e, QualType t);
+ /// ParseObjCSelectorExpression - Build selector expression for \@selector
+ ExprResult ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ bool WarnMultipleSelectors);
- // type checking C++ declaration initializers (C++ [dcl.init]).
+ /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
+ ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ProtoIdLoc,
+ SourceLocation RParenLoc);
- /// 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
+ ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc);
+
+ /// 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
};
- // 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,
+ ObjCMessageKind getObjCMessageKind(Scope *S,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsSuper,
+ bool HasTrailingDot,
+ ParsedType &ReceiverType);
- LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime)
- };
- };
- using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions;
+ ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
- ReferenceCompareResult
- CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
- ReferenceConversions *Conv = nullptr);
+ ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args,
+ bool isImplicit = false);
- ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
- Expr *CastExpr, CastKind &CastKind,
- ExprValueKind &VK, CXXCastPath &Path);
+ ExprResult BuildClassMessageImplicit(QualType ReceiverType,
+ bool isSuperReceiver,
+ SourceLocation Loc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ MultiExprArg Args);
- /// Force an expression with unknown-type to an expression of the
- /// given type.
- ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
+ ExprResult ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
- /// Type-check an expression that's being passed to an
- /// __unknown_anytype parameter.
- ExprResult checkUnknownAnyArg(SourceLocation callLoc,
- Expr *result, QualType ¶mType);
+ ExprResult BuildInstanceMessage(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation SuperLoc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args,
+ bool isImplicit = false);
+
+ ExprResult BuildInstanceMessageImplicit(Expr *Receiver,
+ QualType ReceiverType,
+ SourceLocation Loc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ MultiExprArg Args);
+
+ ExprResult ActOnInstanceMessage(Scope *S,
+ Expr *Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc,
+ ObjCBridgeCastKind Kind,
+ SourceLocation BridgeKeywordLoc,
+ TypeSourceInfo *TSInfo,
+ Expr *SubExpr);
+
+ ExprResult ActOnObjCBridgedCast(Scope *S,
+ SourceLocation LParenLoc,
+ ObjCBridgeCastKind Kind,
+ SourceLocation BridgeKeywordLoc,
+ ParsedType Type,
+ SourceLocation RParenLoc,
+ Expr *SubExpr);
+
+ void CheckTollFreeBridgeCast(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);
+ void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr);
- // 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 CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
+ CastKind &Kind);
- /// Prepare `SplattedExpr` for a vector splat operation, adding
- /// implicit casts if necessary.
- ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
+ bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ ObjCInterfaceDecl *&RelatedClass,
+ ObjCMethodDecl *&ClassMethod,
+ ObjCMethodDecl *&InstanceMethod,
+ TypedefNameDecl *&TDNDecl,
+ bool CfToNs, 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);
+ bool CheckObjCBridgeRelatedConversions(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ Expr *&SrcExpr, bool Diagnose = true);
- ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type,
- SourceLocation LParenLoc,
- Expr *CastExpr,
- SourceLocation RParenLoc);
+ /// Private Helper predicate to check for 'self'.
+ bool isSelfExpr(Expr *RExpr);
+ bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method);
+
+ 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 };
@@ -13292,20 +12905,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.
@@ -13334,142 +12933,405 @@ 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<bool> 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<llvm::APSInt> 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<VarDecl *, Expr *> get() const {
- return std::make_pair(cast_or_null<VarDecl>(ConditionVar),
- Condition.get());
- }
- std::optional<bool> 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.
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
+
+ /// \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);
+
+ /// @}
+
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
+
+ /// \name Code Completion
+ /// Implementations are in SemaCodeComplete.cpp
+ /// @{
+
+public:
+ /// Code-completion consumer.
+ CodeCompleteConsumer *CodeCompleter;
+
+ /// 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,
};
- QualType PreferredConditionType(ConditionKind K) const {
- return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy;
- }
-
- ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr,
- ConditionKind CK, bool MissingOK = false);
-
- ConditionResult ActOnConditionVariable(Decl *ConditionVar,
- SourceLocation StmtLoc,
- ConditionKind CK);
-
- DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
- ExprResult CheckConditionVariable(VarDecl *ConditionVar,
- SourceLocation StmtLoc,
- ConditionKind CK);
- ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond);
+ void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
+ void CodeCompleteOrdinaryName(Scope *S,
+ ParserCompletionContext CompletionContext);
+ void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers);
- /// 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.
+ 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);
-
- /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
- /// found in an explicit(bool) specifier.
- ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
-
- /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
- /// Returns true if the explicit specifier is now resolved.
- bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
+ /// 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<Expr *> Args,
+ SourceLocation OpenParLoc);
+ QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc,
+ ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc,
+ bool Braced);
+ QualType ProduceCtorInitMemberSignatureHelp(
+ Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
+ ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc,
+ bool Braced);
+ QualType ProduceTemplateArgumentSignatureHelp(
+ TemplateTy, ArrayRef<ParsedTemplateArgument>, 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<Expr *> InitExprs,
+ const Designation &D);
+ void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
- /// DiagnoseAssignmentAsCondition - Given that an expression is
- /// being used as a boolean condition, warn if it's an assignment.
- void DiagnoseAssignmentAsCondition(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<CXXCtorInitializer *> Initializers);
- /// Redundant parentheses over an equality comparison can indicate
- /// that the user intended an assignment used as condition.
- void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
+ void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
+ bool AfterAmpersand);
+ void CodeCompleteAfterFunctionEquals(Declarator &D);
- /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
- ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false);
+ 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<IdentifierInfo *> SelIdents,
+ bool AtArgumentExpression);
+ void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+ ArrayRef<IdentifierInfo *> SelIdents,
+ bool AtArgumentExpression,
+ bool IsSuper = false);
+ void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
+ ArrayRef<IdentifierInfo *> SelIdents,
+ bool AtArgumentExpression,
+ ObjCInterfaceDecl *Super = nullptr);
+ void CodeCompleteObjCForCollection(Scope *S,
+ DeclGroupPtrTy IterationVar);
+ void CodeCompleteObjCSelector(Scope *S,
+ ArrayRef<IdentifierInfo *> SelIdents);
+ void CodeCompleteObjCProtocolReferences(
+ ArrayRef<IdentifierLocPair> 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<bool> IsInstanceMethod,
+ ParsedType ReturnType);
+ void CodeCompleteObjCMethodDeclSelector(Scope *S,
+ bool IsInstanceMethod,
+ bool AtParameterName,
+ ParsedType ReturnType,
+ ArrayRef<IdentifierInfo *> 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<CodeCompletionResult> &Results);
- /// 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);
+ /// @}
- /// Abstract base class used for diagnosing integer constant
- /// expression violations.
- class VerifyICEDiagnoser {
- public:
- bool Suppress;
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { }
+ /// \name FixIt Helpers
+ /// Implementations are in SemaFixItUtils.cpp
+ /// @{
- 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() {}
- };
+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;
- enum AllowFoldKind {
- NoFold,
- AllowFold,
- };
+ /// @}
- /// 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);
- }
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
- /// 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<sema::RISCVIntrinsicManager> RVIntrinsicManager;
+
+ /// @}
+
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
+
+ /// \name CUDA
+ /// Implementations are in SemaCUDA.cpp
+ /// @{
public:
/// Increments our count of the number of times we've seen a pragma forcing
@@ -13482,6 +13344,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.
@@ -13536,54 +13402,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.
///
@@ -13674,7 +13492,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
@@ -13750,712 +13567,1465 @@ class Sema final {
/// 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;
+ /// 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);
+
+ /// @}
+
+ //
+ //
+ // -------------------------------------------------------------------------
+ //
+ //
+
+ /// \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<FunctionDecl *> &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;
+
+ /// 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);
+
+ /// 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);
+
+ ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
+ ExprObjectKind OK, SourceLocation Loc);
+
+ /// If the current region is a loop-based region, mark the start of the loop
+ /// construct.
+ void startOpenMPLoop();
+
+ /// If the current region is a range loop-based region, mark the start of the
+ /// loop construct.
+ void startOpenMPCXXRangeFor();
+
+ /// 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;
+
+ /// 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);
- /// \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,
- };
+ /// 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 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 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;
- 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<Expr *> Args,
- SourceLocation OpenParLoc);
- QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc,
- ArrayRef<Expr *> Args,
- SourceLocation OpenParLoc,
- bool Braced);
- QualType ProduceCtorInitMemberSignatureHelp(
- Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
- ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc,
- bool Braced);
- QualType ProduceTemplateArgumentSignatureHelp(
- TemplateTy, ArrayRef<ParsedTemplateArgument>, 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<Expr *> InitExprs,
- const Designation &D);
- void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
+ 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);
- 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<CXXCtorInitializer *> Initializers);
+ /// 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);
- void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
- bool AfterAmpersand);
- void CodeCompleteAfterFunctionEquals(Declarator &D);
+ /// Called on well-formed '\#pragma omp metadirective' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPMetaDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
- 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<IdentifierInfo *> SelIdents,
- bool AtArgumentExpression);
- void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
- ArrayRef<IdentifierInfo *> SelIdents,
- bool AtArgumentExpression,
- bool IsSuper = false);
- void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
- ArrayRef<IdentifierInfo *> SelIdents,
- bool AtArgumentExpression,
- ObjCInterfaceDecl *Super = nullptr);
- void CodeCompleteObjCForCollection(Scope *S,
- DeclGroupPtrTy IterationVar);
- void CodeCompleteObjCSelector(Scope *S,
- ArrayRef<IdentifierInfo *> SelIdents);
- void CodeCompleteObjCProtocolReferences(
- ArrayRef<IdentifierLocPair> 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<bool> IsInstanceMethod,
- ParsedType ReturnType);
- void CodeCompleteObjCMethodDeclSelector(Scope *S,
- bool IsInstanceMethod,
- bool AtParameterName,
- ParsedType ReturnType,
- ArrayRef<IdentifierInfo *> 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<CodeCompletionResult> &Results);
- //@}
+ // 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<Expr *> VarList);
+ /// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
+ OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
+ /// Called on well-formed '#pragma omp allocate'.
+ DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc,
+ ArrayRef<Expr *> VarList,
+ ArrayRef<OMPClause *> Clauses,
+ DeclContext *Owner = nullptr);
- //===--------------------------------------------------------------------===//
- // Extra semantic analysis beyond the C type system
+ /// Called on well-formed '#pragma omp [begin] assume[s]'.
+ void ActOnOpenMPAssumesDirective(SourceLocation Loc,
+ OpenMPDirectiveKind DKind,
+ ArrayRef<std::string> Assumptions,
+ bool SkippedClauses);
-public:
- SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
- unsigned ByteNo) const;
+ /// Check if there is an active global `omp begin assumes` directive.
+ bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); }
- 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
- };
+ /// Check if there is an active global `omp assumes` directive.
+ bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); }
- // 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 end assumes'.
+ void ActOnOpenMPEndAssumesDirective();
- static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
- bool IsVariadic, FormatStringInfo *FSI);
+ /// Called on well-formed '#pragma omp requires'.
+ DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc,
+ ArrayRef<OMPClause *> ClauseList);
+ /// Check restrictions on Requires directive
+ OMPRequiresDecl *CheckOMPRequiresDecl(SourceLocation Loc,
+ ArrayRef<OMPClause *> 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<std::pair<QualType, SourceLocation>> 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);
-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 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<OMPClause *> 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;
- bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto);
- bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
- ArrayRef<const Expr *> Args);
- bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
- const FunctionProtoType *Proto);
- bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto);
- void CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
- ArrayRef<const Expr *> Args,
- const FunctionProtoType *Proto, SourceLocation Loc);
+ struct DeclareTargetContextInfo {
+ struct MapInfo {
+ OMPDeclareTargetDeclAttr::MapTypeTy MT;
+ SourceLocation Loc;
+ };
+ /// Explicitly listed variables and functions in a 'to' or 'link' clause.
+ llvm::DenseMap<NamedDecl *, MapInfo> ExplicitlyMapped;
- void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
+ /// The 'device_type' as parsed from the clause.
+ OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
- void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
- StringRef ParamName, QualType ArgTy, QualType ParamTy);
+ /// The directive kind, `begin declare target` or `declare target`.
+ OpenMPDirectiveKind Kind;
- void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
- const Expr *ThisArg, ArrayRef<const Expr *> Args,
- bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
- VariadicCallType CallType);
+ /// The directive with indirect clause.
+ std::optional<Expr *> Indirect;
- bool CheckObjCString(Expr *Arg);
- ExprResult CheckOSLogFormatStringArg(Expr *Arg);
+ /// The directive location.
+ SourceLocation Loc;
- ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
- unsigned BuiltinID, CallExpr *TheCall);
+ DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc)
+ : Kind(Kind), Loc(Loc) {}
+ };
- bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
- CallExpr *TheCall);
+ /// Called on the start of target region i.e. '#pragma omp declare target'.
+ bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
- void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
+ /// Called at the end of target region i.e. '#pragma omp end declare target'.
+ const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective();
- 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<std::tuple<int, int, int>, 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);
+ /// 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);
- 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<int> ArgNums);
- bool CheckX86BuiltinTileDuplicate(CallExpr *TheCall, ArrayRef<int> ArgNums);
- bool CheckX86BuiltinTileRangeAndDuplicate(CallExpr *TheCall,
- ArrayRef<int> 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);
+ /// Report unterminated 'omp declare target' or 'omp begin declare target' at
+ /// the end of a compilation unit.
+ void DiagnoseUnterminatedOpenMPDeclareTarget();
- 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);
+ /// Searches for the provided declaration name for OpenMP declare target
+ /// directive.
+ NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id);
-public:
- // Used by C++ template instantiation.
- ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
- ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
- SourceLocation BuiltinLoc,
- SourceLocation RParenLoc);
+ /// Called on correct id-expression from the '#pragma omp declare target'.
+ void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
+ OMPDeclareTargetDeclAttr::MapTypeTy MT,
+ DeclareTargetContextInfo &DTCI);
-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);
+ /// Check declaration inside target region.
+ void
+ checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+ SourceLocation IdLoc = SourceLocation());
- bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
+ /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
+ /// directive.
+ void ActOnOpenMPDeclareTargetInitializer(Decl *D);
- bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
- bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall);
- bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
- bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);
+ /// 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);
- bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall);
+ /// Return true if currently in OpenMP task with untied clause context.
+ bool isInOpenMPTaskUntiedContext() const;
- // Matrix builtin handling.
- ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
- ExprResult CallResult);
- ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
- ExprResult CallResult);
- ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
- ExprResult CallResult);
+ /// Return true inside OpenMP declare target region.
+ bool isInOpenMPDeclareTargetContext() const {
+ return !DeclareTargetNesting.empty();
+ }
+ /// Return true inside OpenMP target region.
+ bool isInOpenMPTargetExecutionDirective() const;
- // 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 the number of captured regions created for an OpenMP directive.
+ static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
-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);
+ /// Initialization of captured region for OpenMP region.
+ void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
- bool FormatStringHasSArg(const StringLiteral *FExpr);
+ /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
+ /// an OpenMP loop directive.
+ StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
- static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
+ /// 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);
-private:
- bool CheckFormatArguments(const FormatAttr *Format,
- ArrayRef<const Expr *> Args, bool IsCXXMember,
- VariadicCallType CallType, SourceLocation Loc,
- SourceRange Range,
- llvm::SmallBitVector &CheckedVarArgs);
- bool CheckFormatArguments(ArrayRef<const Expr *> Args,
- FormatArgumentPassingKind FAPK, unsigned format_idx,
- unsigned firstDataArg, FormatStringType Type,
- VariadicCallType CallType, SourceLocation Loc,
- SourceRange range,
- llvm::SmallBitVector &CheckedVarArgs);
+ /// 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<OMPClause *> Clauses);
+ StmtResult ActOnOpenMPExecutableDirective(
+ OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+ OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> 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<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ using VarsWithInheritedDSAType =
+ llvm::SmallDenseMap<const ValueDecl *, const Expr *, 4>;
+ /// Called on well-formed '\#pragma omp simd' after parsing
+ /// of the associated statement.
+ StmtResult
+ ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp for' after parsing
+ /// of the associated statement.
+ StmtResult
+ ActOnOpenMPForDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp single' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> 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<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp parallel for' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPParallelForDirective(
+ ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp parallel masked' after
+ /// parsing of the associated statement.
+ StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp parallel sections' after
+ /// parsing of the associated statement.
+ StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp task' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp taskgroup'.
+ StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp flush'.
+ StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp depobj'.
+ StmtResult ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp scan'.
+ StmtResult ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp ordered' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp atomic' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp target' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp target data' after parsing of
+ /// the associated statement.
+ StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ Stmt *AStmt);
+ /// Called on well-formed '\#pragma omp target parallel' after
+ /// parsing of the associated statement.
+ StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp teams loop' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPTeamsGenericLoopDirective(
+ ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ OpenMPDirectiveKind CancelRegion);
+ /// Called on well-formed '\#pragma omp taskloop' after parsing of the
+ /// associated statement.
+ StmtResult
+ ActOnOpenMPTaskLoopDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses, Stmt *AStmt,
+ SourceLocation StartLoc, SourceLocation EndLoc,
+ VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp target update'.
+ StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> 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<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+ /// Called on well-formed '\#pragma omp interop'.
+ StmtResult ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp dispatch' after parsing of the
+ // /associated statement.
+ StmtResult ActOnOpenMPDispatchDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp masked' after parsing of the
+ // /associated statement.
+ StmtResult ActOnOpenMPMaskedDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
- void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
+ /// Called on well-formed '\#pragma omp loop' after parsing of the
+ /// associated statement.
+ StmtResult ActOnOpenMPGenericLoopDirective(
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
- void CheckAbsoluteValueFunction(const CallExpr *Call,
- const FunctionDecl *FDecl);
+ /// 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 CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
+ /// 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<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
+ ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
+ ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR);
- void CheckMemaccessArguments(const CallExpr *Call,
- unsigned BId,
- 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<std::pair<FunctionDecl *, Expr *>>
+ checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef,
+ OMPTraitInfo &TI, unsigned NumAppendArgs,
+ SourceRange SR);
- void CheckStrlcpycatArguments(const CallExpr *Call,
- IdentifierInfo *FnName);
+ /// 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<Expr *> AdjustArgsNothing,
+ ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
+ ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
+ SourceLocation AppendArgsLoc, SourceRange SR);
- void CheckStrncatArguments(const CallExpr *Call,
- IdentifierInfo *FnName);
+ 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<Expr *> 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);
- void CheckFreeArguments(const CallExpr *E);
+ 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);
- void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
- SourceLocation ReturnLoc,
- bool isObjCMethod = false,
- const AttrVec *Attrs = nullptr,
- const FunctionDecl *FD = nullptr);
+ OMPClause *ActOnOpenMPSingleExprWithArgClause(
+ OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ ArrayRef<SourceLocation> 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);
-public:
- void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
- BinaryOperatorKind Opcode);
+ 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);
-private:
- void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
- void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
- void CheckForIntOverflow(const Expr *E);
- void CheckUnsequencedOperations(const Expr *E);
+ /// 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);
- /// 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);
+ /// Called on well-formed 'init' clause.
+ OMPClause *
+ ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation VarLoc, SourceLocation EndLoc);
- void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
- Expr *Init);
+ /// Called on well-formed 'use' clause.
+ OMPClause *ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc, 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 '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);
- /// 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 'unified_address' clause.
+ OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
+ 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 'reverse_offload' clause.
+ OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
- void CheckTCBEnforcement(const SourceLocation CallExprLoc,
- const NamedDecl *Callee);
+ /// Called on well-formed 'dynamic_allocators' clause.
+ OMPClause *ActOnOpenMPDynamicAllocatorsClause(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 'atomic_default_mem_order' clause.
+ OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause(
+ OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
- struct TypeTagData {
- TypeTagData() {}
+ /// Called on well-formed 'at' clause.
+ OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
- TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) :
- Type(Type), LayoutCompatible(LayoutCompatible),
- MustBeNull(MustBeNull)
- {}
+ /// Called on well-formed 'severity' clause.
+ OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
- QualType Type;
+ /// Called on well-formed 'message' clause.
+ /// passing string for message.
+ OMPClause *ActOnOpenMPMessageClause(Expr *MS, 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;
+ /// 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<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
+ MapTypeModifiers;
+ SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
+ MapTypeModifiersLoc;
+ SmallVector<OpenMPMotionModifierKind, NumberOfOMPMotionModifiers>
+ MotionModifiers;
+ SmallVector<SourceLocation, NumberOfOMPMotionModifiers> MotionModifiersLoc;
+ bool IsMapTypeImplicit = false;
+ SourceLocation ExtraModifierLoc;
+ SourceLocation OmpAllMemoryLoc;
+ SourceLocation
+ StepModifierLoc; /// 'step' modifier location for linear clause
};
- /// A pair of ArgumentKind identifier and magic value. This uniquely
- /// identifies the magic value.
- typedef std::pair<const IdentifierInfo *, uint64_t> TypeTagMagicValue;
-
-private:
- /// A map from magic value to type information.
- std::unique_ptr<llvm::DenseMap<TypeTagMagicValue, TypeTagData>>
- TypeTagForDatatypeMagicValues;
-
- /// 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<const Expr *> ExprArgs,
- SourceLocation CallSiteLoc);
+ OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
+ ArrayRef<Expr *> Vars,
+ const OMPVarListLocTy &Locs,
+ OpenMPVarListDataTy &Data);
+ /// Called on well-formed 'inclusive' clause.
+ OMPClause *ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'exclusive' clause.
+ OMPClause *ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'allocate' clause.
+ OMPClause *
+ ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation ColonLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc);
+ /// Called on well-formed 'private' clause.
+ OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'firstprivate' clause.
+ OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'lastprivate' clause.
+ OMPClause *ActOnOpenMPLastprivateClause(
+ ArrayRef<Expr *> VarList, OpenMPLastprivateModifier LPKind,
+ SourceLocation LPKindLoc, SourceLocation ColonLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+ /// Called on well-formed 'shared' clause.
+ OMPClause *ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'reduction' clause.
+ OMPClause *ActOnOpenMPReductionClause(
+ ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ModifierLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions = std::nullopt);
+ /// Called on well-formed 'task_reduction' clause.
+ OMPClause *ActOnOpenMPTaskReductionClause(
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions = std::nullopt);
+ /// Called on well-formed 'in_reduction' clause.
+ OMPClause *ActOnOpenMPInReductionClause(
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions = std::nullopt);
+ /// Called on well-formed 'linear' clause.
+ OMPClause *ActOnOpenMPLinearClause(
+ ArrayRef<Expr *> 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<Expr *> VarList,
+ Expr *Alignment,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'copyin' clause.
+ OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'copyprivate' clause.
+ OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'flush' pseudo clause.
+ OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr *> 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<Expr *> 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<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
+ CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
+ OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
+ SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs, bool NoDiagnose = false,
+ ArrayRef<Expr *> 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<OpenMPMotionModifierKind> MotionModifiers,
+ ArrayRef<SourceLocation> MotionModifiersLoc,
+ CXXScopeSpec &MapperIdScopeSpec,
+ DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
+ ArrayRef<Expr *> UnresolvedMappers = std::nullopt);
+ /// Called on well-formed 'from' clause.
+ OMPClause *
+ ActOnOpenMPFromClause(ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
+ ArrayRef<SourceLocation> MotionModifiersLoc,
+ CXXScopeSpec &MapperIdScopeSpec,
+ DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
+ ArrayRef<Expr *> UnresolvedMappers = std::nullopt);
+ /// Called on well-formed 'use_device_ptr' clause.
+ OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs);
+ /// Called on well-formed 'use_device_addr' clause.
+ OMPClause *ActOnOpenMPUseDeviceAddrClause(ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs);
+ /// Called on well-formed 'is_device_ptr' clause.
+ OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs);
+ /// Called on well-formed 'has_device_addr' clause.
+ OMPClause *ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
+ const OMPVarListLocTy &Locs);
+ /// Called on well-formed 'nontemporal' clause.
+ OMPClause *ActOnOpenMPNontemporalClause(ArrayRef<Expr *> 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<UsesAllocatorsData> Data);
+ /// Called on well-formed 'affinity' clause.
+ OMPClause *ActOnOpenMPAffinityClause(SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation EndLoc, Expr *Modifier,
+ ArrayRef<Expr *> 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<Expr *> 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<const Attr *> 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<DeclareTargetContextInfo, 4> 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<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
+ Stmt *&Body,
+ SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 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<ObjCCategoryDecl>(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<CXXRecordDecl*, 4> DelayedDllExportClasses;
- SmallVector<CXXMethodDecl*, 4> 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<OMPDeclareVariantScope, 4> OMPDeclareVariantScopes;
- private:
- Sema &S;
- decltype(DelayedOverridingExceptionSpecChecks)
- SavedOverridingExceptionSpecChecks;
- decltype(DelayedEquivalentExceptionSpecChecks)
- SavedEquivalentExceptionSpecChecks;
+ /// The current `omp begin/end assumes` scopes.
+ SmallVector<AssumptionAttr *, 4> OMPAssumeScoped;
- void swapSavedState() {
- SavedOverridingExceptionSpecChecks.swap(
- S.DelayedOverridingExceptionSpecChecks);
- SavedEquivalentExceptionSpecChecks.swap(
- S.DelayedEquivalentExceptionSpecChecks);
- }
- };
+ /// All `omp assumes` we encountered so far.
+ SmallVector<AssumptionAttr *, 4> 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<OMPClause *> 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<OMPClause *> &ClausesWithoutBind,
+ ArrayRef<OMPClause *> 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<MisalignedMember, 4> 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<void(Expr *, RecordDecl *, FieldDecl *, CharUnits)>
- 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".
///
@@ -14480,6 +15050,8 @@ class Sema final {
void deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
llvm::DenseSet<QualType> Visited,
ValueDecl *DeclToCheck);
+
+ /// @}
};
DeductionFailureInfo
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index cfb653e665ea03..720d5fd5f0428d 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<unsigned>(ComparisonCategoryType::Last) + 1),
+ StdSourceLocationImplDecl(nullptr), CXXTypeInfoDecl(nullptr),
+ GlobalNewDeleteDeclared(false), DisableTypoCorrection(false),
+ TyposCorrected(0), IsBuildingRecoveryCallExpr(false), NumSFINAEErrors(0),
+ AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr),
+ InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
+ 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<unsigned>(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;
>From c8019507fc535683101f04ea33215f04635bff1c Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Feb 2024 09:52:19 +0300
Subject: [PATCH 2/8] Run clang-format
---
clang/include/clang/Sema/Sema.h | 2074 +++++++++++++------------------
1 file changed, 875 insertions(+), 1199 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 48ffffa791d8da..e039f9719826d3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -452,7 +452,8 @@ class Sema final {
// 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)
+ // 28. C++ Template Declaration Instantiation
+ // (SemaTemplateInstantiateDecl.cpp)
// 29. C++ Variadic Templates (SemaTemplateVariadic.cpp)
// 30. Constraints and Concepts (SemaConcept.cpp)
// 31. Types (SemaType.cpp)
@@ -491,7 +492,7 @@ class Sema final {
const LangOptions &getLangOpts() const { return LangOpts; }
OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
- FPOptions &getCurFPFeatures() { return CurFPFeatures; }
+ FPOptions &getCurFPFeatures() { return CurFPFeatures; }
DiagnosticsEngine &getDiagnostics() const { return Diags; }
SourceManager &getSourceManager() const { return SourceMgr; }
@@ -541,7 +542,8 @@ class Sema final {
~ImmediateDiagBuilder() {
// If we aren't active, there is nothing to do.
- if (!isActive()) return;
+ if (!isActive())
+ return;
// Otherwise, we need to emit the diagnostic. First clear the diagnostic
// builder itself so it won't emit the diagnostic in its own destructor.
@@ -725,7 +727,7 @@ class Sema final {
/// Obtain a sorted list of functions that are undefined but ODR-used.
void getUndefinedButUsed(
- SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
+ SmallVectorImpl<std::pair<NamedDecl *, SourceLocation>> &Undefined);
typedef std::pair<SourceLocation, bool> DeleteExprLoc;
typedef llvm::SmallVector<DeleteExprLoc, 4> DeleteLocs;
@@ -1037,9 +1039,7 @@ class Sema final {
S.ActOnStartOfCompoundStmt(IsStmtExpr);
}
- ~CompoundScopeRAII() {
- S.ActOnFinishOfCompoundStmt();
- }
+ ~CompoundScopeRAII() { S.ActOnFinishOfCompoundStmt(); }
private:
Sema &S;
@@ -1226,13 +1226,11 @@ class Sema final {
CXXRecordDecl *NamingClass,
DeclAccessPair FoundDecl,
bool Diagnose = true);
- AccessResult CheckConstructorAccess(SourceLocation Loc,
- CXXConstructorDecl *D,
+ AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D,
DeclAccessPair FoundDecl,
const InitializedEntity &Entity,
bool IsCopyBindingRefToTemp = false);
- AccessResult CheckConstructorAccess(SourceLocation Loc,
- CXXConstructorDecl *D,
+ AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D,
DeclAccessPair FoundDecl,
const InitializedEntity &Entity,
const PartialDiagnostic &PDiag);
@@ -1251,8 +1249,7 @@ class Sema final {
AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
const SourceRange &,
DeclAccessPair FoundDecl);
- AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
- Expr *ObjectExpr,
+ AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
Expr *ArgExpr,
DeclAccessPair FoundDecl);
AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
@@ -1260,11 +1257,9 @@ class Sema final {
DeclAccessPair FoundDecl);
AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
DeclAccessPair FoundDecl);
- AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
- QualType Base, QualType Derived,
- const CXXBasePath &Path,
- unsigned DiagID,
- bool ForceCheck = false,
+ 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,
@@ -1280,8 +1275,9 @@ class Sema final {
SourceLocation(), PDiag());
}
- void HandleDependentAccessCheck(const DependentDiagnostic &DD,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ void HandleDependentAccessCheck(
+ const DependentDiagnostic &DD,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
/// @}
@@ -1308,39 +1304,36 @@ class Sema final {
/// pragma clang section kind
enum PragmaClangSectionKind {
- PCSK_Invalid = 0,
- PCSK_BSS = 1,
- PCSK_Data = 2,
- PCSK_Rodata = 3,
- PCSK_Text = 4,
- PCSK_Relro = 5
- };
-
- enum PragmaClangSectionAction {
- PCSA_Set = 0,
- PCSA_Clear = 1
+ PCSK_Invalid = 0,
+ PCSK_BSS = 1,
+ PCSK_Data = 2,
+ PCSK_Rodata = 3,
+ PCSK_Text = 4,
+ PCSK_Relro = 5
};
+ enum PragmaClangSectionAction { PCSA_Set = 0, PCSA_Clear = 1 };
+
struct PragmaClangSection {
std::string SectionName;
bool Valid = false;
SourceLocation PragmaLocation;
};
- PragmaClangSection PragmaClangBSSSection;
- PragmaClangSection PragmaClangDataSection;
- PragmaClangSection PragmaClangRodataSection;
- PragmaClangSection PragmaClangRelroSection;
- PragmaClangSection PragmaClangTextSection;
+ PragmaClangSection PragmaClangBSSSection;
+ PragmaClangSection PragmaClangDataSection;
+ PragmaClangSection PragmaClangRodataSection;
+ PragmaClangSection PragmaClangRelroSection;
+ PragmaClangSection PragmaClangTextSection;
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)
+ 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)
};
struct PragmaPackInfo {
@@ -1451,8 +1444,7 @@ class Sema final {
static constexpr uint32_t PackNumMask{0x0000'01F0};
};
- template<typename ValueType>
- struct PragmaStack {
+ template <typename ValueType> struct PragmaStack {
struct Slot {
llvm::StringRef StackSlotLabel;
ValueType Value;
@@ -1636,7 +1628,6 @@ class Sema final {
return OptimizeOffPragmaLocation;
}
-
/// 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
@@ -1677,7 +1668,8 @@ class Sema final {
/// ActOnPragmaClangSection - Called on well formed \#pragma clang section
void ActOnPragmaClangSection(SourceLocation PragmaLoc,
PragmaClangSectionAction Action,
- PragmaClangSectionKind SecKind, StringRef SecName);
+ PragmaClangSectionKind SecKind,
+ StringRef SecName);
/// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
@@ -1739,25 +1731,22 @@ class Sema final {
/// Called on well formed \#pragma vtordisp().
void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
- SourceLocation PragmaLoc,
- MSVtorDispMode Value);
+ SourceLocation PragmaLoc, MSVtorDispMode Value);
bool UnifySection(StringRef SectionName, int SectionFlags,
NamedDecl *TheDecl);
- bool UnifySection(StringRef SectionName,
- int SectionFlags,
+ bool UnifySection(StringRef SectionName, int SectionFlags,
SourceLocation PragmaSectionLocation);
/// 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);
+ StringLiteral *SegmentName, llvm::StringRef PragmaName);
/// Called on well formed \#pragma section().
- void ActOnPragmaMSSection(SourceLocation PragmaLocation,
- int SectionFlags, StringLiteral *SegmentName);
+ void ActOnPragmaMSSection(SourceLocation PragmaLocation, int SectionFlags,
+ StringLiteral *SegmentName);
/// Called on well-formed \#pragma init_seg().
void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
@@ -1776,8 +1765,7 @@ class Sema final {
bool Value);
/// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
- void ActOnPragmaUnused(const Token &Identifier,
- Scope *curScope,
+ void ActOnPragmaUnused(const Token &Identifier, Scope *curScope,
SourceLocation PragmaLoc);
/// AddCFAuditedAttribute - Check whether we're currently within
@@ -1847,7 +1835,7 @@ class Sema final {
void FreeVisContext();
/// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
- void ActOnPragmaVisibility(const IdentifierInfo* VisType,
+ void ActOnPragmaVisibility(const IdentifierInfo *VisType,
SourceLocation PragmaLoc);
/// ActOnPragmaFPContract - Called on well formed
@@ -1947,21 +1935,15 @@ class Sema final {
/// ActOnCXXNamedCast - Parse
/// {dynamic,static,reinterpret,const,addrspace}_cast's.
- ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc,
- Declarator &D,
+ ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ SourceLocation LAngleBracketLoc, Declarator &D,
SourceLocation RAngleBracketLoc,
- SourceLocation LParenLoc,
- Expr *E,
+ SourceLocation LParenLoc, Expr *E,
SourceLocation RParenLoc);
- ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
- tok::TokenKind Kind,
- TypeSourceInfo *Ty,
- Expr *E,
- SourceRange AngleBrackets,
- SourceRange Parens);
+ ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+ TypeSourceInfo *Ty, Expr *E,
+ SourceRange AngleBrackets, SourceRange Parens);
ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
ExprResult Operand,
@@ -1987,10 +1969,8 @@ class Sema final {
bool CheckAltivecInitFromScalar(SourceRange R, QualType VecTy,
QualType SrcTy);
- ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
- TypeSourceInfo *Ty,
- SourceLocation RParenLoc,
- Expr *Op);
+ ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
+ SourceLocation RParenLoc, Expr *Op);
ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type,
SourceLocation LParenLoc,
@@ -2074,10 +2054,9 @@ class Sema final {
struct TypeTagData {
TypeTagData() {}
- TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) :
- Type(Type), LayoutCompatible(LayoutCompatible),
- MustBeNull(MustBeNull)
- {}
+ TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull)
+ : Type(Type), LayoutCompatible(LayoutCompatible),
+ MustBeNull(MustBeNull) {}
QualType Type;
@@ -2152,14 +2131,12 @@ class Sema final {
/// This helps prevent bugs due to typos, such as:
/// if (condition);
/// do_stuff();
- void DiagnoseEmptyStmtBody(SourceLocation StmtLoc,
- const Stmt *Body,
+ void DiagnoseEmptyStmtBody(SourceLocation StmtLoc, const Stmt *Body,
unsigned DiagID);
/// 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 DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody);
/// Warn if a value is moved to itself.
void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
@@ -2204,8 +2181,8 @@ class Sema final {
bool CheckObjCString(Expr *Arg);
ExprResult CheckOSLogFormatStringArg(Expr *Arg);
- ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
- unsigned BuiltinID, CallExpr *TheCall);
+ ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
+ CallExpr *TheCall);
bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall);
@@ -2349,21 +2326,17 @@ class Sema final {
void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
- void CheckMemaccessArguments(const CallExpr *Call,
- unsigned BId,
+ void CheckMemaccessArguments(const CallExpr *Call, unsigned BId,
IdentifierInfo *FnName);
- void CheckStrlcpycatArguments(const CallExpr *Call,
- IdentifierInfo *FnName);
+ void CheckStrlcpycatArguments(const CallExpr *Call, IdentifierInfo *FnName);
- void CheckStrncatArguments(const CallExpr *Call,
- IdentifierInfo *FnName);
+ void CheckStrncatArguments(const CallExpr *Call, IdentifierInfo *FnName);
void CheckFreeArguments(const CallExpr *E);
void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
- SourceLocation ReturnLoc,
- bool isObjCMethod = false,
+ SourceLocation ReturnLoc, bool isObjCMethod = false,
const AttrVec *Attrs = nullptr,
const FunctionDecl *FD = nullptr);
@@ -2545,22 +2518,19 @@ class Sema final {
/// 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) {
- }
+ SourceLocation ColonColonLoc,
+ ParsedType ObjectType = ParsedType())
+ : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc),
+ CCLoc(ColonColonLoc) {}
NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
SourceLocation ColonColonLoc, QualType ObjectType)
- : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
- IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {
- }
+ : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
+ IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {}
};
- bool BuildCXXNestedNameSpecifier(Scope *S,
- NestedNameSpecInfo &IdInfo,
- bool EnteringContext,
- CXXScopeSpec &SS,
+ bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
+ bool EnteringContext, CXXScopeSpec &SS,
NamedDecl *ScopeLookupResult,
bool ErrorRecoveryLookup,
bool *IsCorrectedToColon = nullptr,
@@ -2588,10 +2558,8 @@ class Sema final {
/// \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 ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
+ bool EnteringContext, CXXScopeSpec &SS,
bool *IsCorrectedToColon = nullptr,
bool OnlyNamespace = false);
@@ -2618,19 +2586,13 @@ class Sema final {
///
///
/// \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);
-
- bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
- const DeclSpec &DS,
+ bool ActOnCXXNestedNameSpecifier(
+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ TemplateTy TemplateName, SourceLocation TemplateNameLoc,
+ SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc, SourceLocation CCLoc, bool EnteringContext);
+
+ bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, const DeclSpec &DS,
SourceLocation ColonColonLoc);
bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
@@ -2714,12 +2676,11 @@ class Sema final {
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)
- {
+ : 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)
@@ -2730,7 +2691,8 @@ class Sema final {
}
void pop() {
- if (!SavedContext) return;
+ if (!SavedContext)
+ return;
S.CurContext = SavedContext;
S.DelayedDiagnostics.popUndelayed(SavedContextState);
S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
@@ -2739,9 +2701,7 @@ class Sema final {
SavedContext = nullptr;
}
- ~ContextRAII() {
- pop();
- }
+ ~ContextRAII() { pop(); }
};
void DiagnoseInvalidJumps(Stmt *Body);
@@ -2754,7 +2714,7 @@ class Sema final {
/// A cache of the flags available in enumerations with the flag_bits
/// attribute.
- mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache;
+ mutable llvm::DenseMap<const EnumDecl *, llvm::APInt> FlagBitsCache;
/// WeakUndeclaredIdentifiers - Identifiers contained in \#pragma weak before
/// declared. Rare. May alias another identifier, declared or undeclared.
@@ -2775,7 +2735,7 @@ class Sema final {
/// \#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<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers;
+ llvm::DenseMap<IdentifierInfo *, AsmLabelAttr *> ExtnameUndeclaredIdentifiers;
/// Set containing all typedefs that are likely unused.
llvm::SmallSetVector<const TypedefNameDecl *, 4>
@@ -2783,7 +2743,7 @@ class Sema final {
typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2>
- UnusedFileScopedDeclsType;
+ UnusedFileScopedDeclsType;
/// 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.
@@ -2791,7 +2751,7 @@ class Sema final {
typedef LazyVector<VarDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadTentativeDefinitions, 2, 2>
- TentativeDefinitionsType;
+ TentativeDefinitionsType;
/// All the tentative definitions encountered in the TU.
TentativeDefinitionsType TentativeDefinitions;
@@ -3320,8 +3280,7 @@ class Sema final {
bool IsExplicitInstantiation,
RecordDecl *&AnonRecord);
- Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
- AccessSpecifier AS,
+ Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS,
RecordDecl *Record,
const PrintingPolicy &Policy);
@@ -3391,8 +3350,7 @@ class Sema final {
FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
Declarator &D, Expr *BitfieldWidth,
- InClassInitStyle InitStyle,
- AccessSpecifier AS);
+ InClassInitStyle InitStyle, AccessSpecifier AS);
FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
TypeSourceInfo *TInfo,
@@ -3563,8 +3521,7 @@ class Sema final {
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;
+ bool IsRedefinitionInModule(const NamedDecl *New, const NamedDecl *Old) const;
static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
@@ -3595,9 +3552,8 @@ class Sema final {
FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID,
SourceLocation Loc);
- NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
- Scope *S, bool ForRedeclaration,
- SourceLocation Loc);
+ NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S,
+ bool ForRedeclaration, SourceLocation Loc);
/// Get the outermost AttributedType node that sets a calling convention.
/// Valid types should not have multiple attributes with different CCs.
@@ -3608,7 +3564,7 @@ class Sema final {
/// ParsingInitForAutoVars - a set of declarations with auto types for which
/// we are currently parsing the initializer.
- llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
+ llvm::SmallPtrSet<const Decl *, 4> ParsingInitForAutoVars;
/// Look for a locally scoped extern "C" declaration by the given name.
NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
@@ -3675,21 +3631,19 @@ class Sema final {
bool AllowMask) const;
/// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
- void ActOnPragmaWeakID(IdentifierInfo* WeakName,
- SourceLocation PragmaLoc,
+ void ActOnPragmaWeakID(IdentifierInfo *WeakName, SourceLocation PragmaLoc,
SourceLocation WeakNameLoc);
/// ActOnPragmaRedefineExtname - Called on well formed
/// \#pragma redefine_extname oldname newname.
- void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName,
- IdentifierInfo* AliasName,
+ void ActOnPragmaRedefineExtname(IdentifierInfo *WeakName,
+ IdentifierInfo *AliasName,
SourceLocation PragmaLoc,
SourceLocation WeakNameLoc,
SourceLocation AliasNameLoc);
/// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident.
- void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
- IdentifierInfo* AliasName,
+ void ActOnPragmaWeakAlias(IdentifierInfo *WeakName, IdentifierInfo *AliasName,
SourceLocation PragmaLoc,
SourceLocation WeakNameLoc,
SourceLocation AliasNameLoc);
@@ -3771,14 +3725,14 @@ class Sema final {
/// 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<Decl*,2> WeakTopLevelDecl;
+ SmallVector<Decl *, 2> WeakTopLevelDecl;
/// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadExtVectorDecls, 2, 2>
- ExtVectorDeclsType;
+ ExtVectorDeclsType;
/// 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.
@@ -3859,9 +3813,9 @@ class Sema final {
void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
StringRef Annot, MutableArrayRef<Expr *> Args);
- bool checkMSInheritanceAttrOnDefinition(
- CXXRecordDecl *RD, SourceRange Range, bool BestCase,
- MSInheritanceModel SemanticSpelling);
+ bool checkMSInheritanceAttrOnDefinition(CXXRecordDecl *RD, SourceRange Range,
+ bool BestCase,
+ MSInheritanceModel SemanticSpelling);
void CheckAlignasUnderalignment(Decl *D);
@@ -3910,7 +3864,7 @@ class Sema final {
void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
- enum class RetainOwnershipKind {NS, CF, OS};
+ enum class RetainOwnershipKind { NS, CF, OS };
void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
RetainOwnershipKind K, bool IsTemplateInstantiation);
@@ -3939,10 +3893,10 @@ class Sema final {
mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL,
HLSLParamModifierAttr::Spelling Spelling);
- WebAssemblyImportNameAttr *mergeImportNameAttr(
- Decl *D, const WebAssemblyImportNameAttr &AL);
- WebAssemblyImportModuleAttr *mergeImportModuleAttr(
- Decl *D, const WebAssemblyImportModuleAttr &AL);
+ WebAssemblyImportNameAttr *
+ mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL);
+ WebAssemblyImportModuleAttr *
+ mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL);
/// Create an AMDGPUWavesPerEUAttr attribute.
AMDGPUFlatWorkGroupSizeAttr *
@@ -4113,12 +4067,9 @@ class Sema final {
void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
- Decl *ActOnNamespaceAliasDef(Scope *CurScope,
- SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
- IdentifierInfo *Alias,
- CXXScopeSpec &SS,
- SourceLocation IdentLoc,
+ Decl *ActOnNamespaceAliasDef(Scope *CurScope, SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc, IdentifierInfo *Alias,
+ CXXScopeSpec &SS, SourceLocation IdentLoc,
IdentifierInfo *Ident);
void FilterUsingLookup(Scope *S, LookupResult &lookup);
@@ -4142,12 +4093,14 @@ class Sema final {
const LookupResult *R = nullptr,
const UsingDecl *UD = nullptr);
- 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 *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,
@@ -4239,7 +4192,7 @@ class Sema final {
public:
explicit ImplicitExceptionSpecification(Sema &Self)
- : Self(&Self), ComputedEST(EST_BasicNoexcept) {
+ : Self(&Self), ComputedEST(EST_BasicNoexcept) {
if (!Self.getLangOpts().CPlusPlus11)
ComputedEST = EST_DynamicNone;
}
@@ -4278,8 +4231,8 @@ class Sema final {
/// 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();
+ ESI.NoexceptExpr =
+ Self->ActOnCXXBoolLiteral(SourceLocation(), tok::kw_false).get();
}
return ESI;
}
@@ -4302,12 +4255,10 @@ class Sema final {
/// 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<ParsedType> DynamicExceptions,
- ArrayRef<SourceRange> DynamicExceptionRanges,
- Expr *NoexceptExpr);
+ void actOnDelayedExceptionSpecification(
+ Decl *Method, ExceptionSpecificationType EST,
+ SourceRange SpecificationRange, ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr);
/// Kinds of C++ special members.
enum CXXSpecialMember {
@@ -4337,8 +4288,8 @@ class Sema final {
/// default constructor will be added.
///
/// \returns The implicitly-declared default constructor.
- CXXConstructorDecl *DeclareImplicitDefaultConstructor(
- CXXRecordDecl *ClassDecl);
+ CXXConstructorDecl *
+ DeclareImplicitDefaultConstructor(CXXRecordDecl *ClassDecl);
/// DefineImplicitDefaultConstructor - Checks for feasibility of
/// defining this constructor as the default constructor.
@@ -4473,8 +4424,9 @@ class Sema final {
/// 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
+ DefineImplicitLambdaToFunctionPointerConversion(SourceLocation CurrentLoc,
+ CXXConversionDecl *Conv);
/// Define the "body" of the conversion from a lambda object to a
/// block pointer.
@@ -4486,12 +4438,9 @@ class Sema final {
void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc,
CXXConversionDecl *Conv);
- Decl *ActOnStartLinkageSpecification(Scope *S,
- SourceLocation ExternLoc,
- Expr *LangStr,
- SourceLocation LBraceLoc);
- Decl *ActOnFinishLinkageSpecification(Scope *S,
- Decl *LinkageSpec,
+ Decl *ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
+ Expr *LangStr, SourceLocation LBraceLoc);
+ Decl *ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec,
SourceLocation RBraceLoc);
//===--------------------------------------------------------------------===//
@@ -4506,61 +4455,47 @@ class Sema final {
SourceLocation ColonLoc,
const ParsedAttributesView &Attrs);
- NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
- Declarator &D,
- MultiTemplateParamsArg TemplateParameterLists,
- Expr *BitfieldWidth, const VirtSpecifiers &VS,
- InClassInitStyle InitStyle);
+ NamedDecl *
+ ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Expr *BitfieldWidth, const VirtSpecifiers &VS,
+ InClassInitStyle InitStyle);
void ActOnStartCXXInClassMemberInitializer();
void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
SourceLocation EqualLoc,
Expr *Init);
- MemInitResult ActOnMemInitializer(Decl *ConstructorD,
- Scope *S,
- CXXScopeSpec &SS,
- IdentifierInfo *MemberOrBase,
- ParsedType TemplateTypeTy,
- const DeclSpec &DS,
- SourceLocation IdLoc,
- SourceLocation LParenLoc,
- ArrayRef<Expr *> Args,
- SourceLocation RParenLoc,
- SourceLocation EllipsisLoc);
+ MemInitResult
+ ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy,
+ const DeclSpec &DS, SourceLocation IdLoc,
+ SourceLocation LParenLoc, ArrayRef<Expr *> Args,
+ SourceLocation RParenLoc, SourceLocation EllipsisLoc);
- MemInitResult ActOnMemInitializer(Decl *ConstructorD,
- Scope *S,
+ MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
- const DeclSpec &DS,
- SourceLocation IdLoc,
- Expr *InitList,
- SourceLocation EllipsisLoc);
+ const DeclSpec &DS, SourceLocation IdLoc,
+ Expr *InitList, SourceLocation EllipsisLoc);
- MemInitResult BuildMemInitializer(Decl *ConstructorD,
- Scope *S,
+ MemInitResult BuildMemInitializer(Decl *ConstructorD, Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
- const DeclSpec &DS,
- SourceLocation IdLoc,
- Expr *Init,
- SourceLocation EllipsisLoc);
+ const DeclSpec &DS, SourceLocation IdLoc,
+ Expr *Init, SourceLocation EllipsisLoc);
- MemInitResult BuildMemberInitializer(ValueDecl *Member,
- Expr *Init,
+ MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr *Init,
SourceLocation IdLoc);
MemInitResult BuildBaseInitializer(QualType BaseType,
- TypeSourceInfo *BaseTInfo,
- Expr *Init,
+ TypeSourceInfo *BaseTInfo, Expr *Init,
CXXRecordDecl *ClassDecl,
SourceLocation EllipsisLoc);
- MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
- Expr *Init,
+ MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
CXXRecordDecl *ClassDecl);
bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
@@ -4572,7 +4507,6 @@ class Sema final {
void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
-
/// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
/// mark all the non-trivial destructors of its members and bases as
/// referenced.
@@ -4598,7 +4532,7 @@ class Sema final {
/// 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<CXXRecordDecl*, SourceLocation> VTableUse;
+ typedef std::pair<CXXRecordDecl *, SourceLocation> VTableUse;
/// The list of vtables that are required but have not yet been
/// materialized.
@@ -4637,9 +4571,8 @@ class Sema final {
void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
- void ActOnMemInitializers(Decl *ConstructorDecl,
- SourceLocation ColonLoc,
- ArrayRef<CXXCtorInitializer*> MemInits,
+ void ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc,
+ ArrayRef<CXXCtorInitializer *> MemInits,
bool AnyErrors);
/// Check class-level dllimport/dllexport attribute. The caller must
@@ -4682,8 +4615,7 @@ class Sema final {
ASTContext &Ctx,
bool ErrorOnInvalidMessage);
Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
- Expr *AssertExpr,
- Expr *AssertMessageExpr,
+ Expr *AssertExpr, Expr *AssertMessageExpr,
SourceLocation RParenLoc);
Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *AssertExpr, Expr *AssertMessageExpr,
@@ -4696,13 +4628,12 @@ class Sema final {
MultiTemplateParamsArg TemplateParams);
QualType CheckConstructorDeclarator(Declarator &D, QualType R,
- StorageClass& SC);
+ StorageClass &SC);
void CheckConstructor(CXXConstructorDecl *Constructor);
QualType CheckDestructorDeclarator(Declarator &D, QualType R,
- StorageClass& SC);
+ StorageClass &SC);
bool CheckDestructor(CXXDestructorDecl *Destructor);
- void CheckConversionDeclarator(Declarator &D, QualType &R,
- StorageClass& SC);
+ void CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass &SC);
Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
bool CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
StorageClass &SC);
@@ -4752,8 +4683,8 @@ class Sema final {
/// ActOnBaseSpecifier - Parsed a base specifier
CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
- SourceRange SpecifierRange,
- bool Virtual, AccessSpecifier Access,
+ SourceRange SpecifierRange, bool Virtual,
+ AccessSpecifier Access,
TypeSourceInfo *TInfo,
SourceLocation EllipsisLoc);
@@ -4783,8 +4714,7 @@ class Sema final {
unsigned InaccessibleBaseID,
unsigned AmbiguousBaseConvID,
SourceLocation Loc, SourceRange Range,
- DeclarationName Name,
- CXXCastPath *BasePath,
+ DeclarationName Name, CXXCastPath *BasePath,
bool IgnoreAccess = false);
std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
@@ -4861,8 +4791,8 @@ class Sema final {
// Emitting members of dllexported classes is delayed until the class
// (including field initializers) is fully parsed.
- SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
- SmallVector<CXXMethodDecl*, 4> DelayedDllExportMemberFunctions;
+ SmallVector<CXXRecordDecl *, 4> DelayedDllExportClasses;
+ SmallVector<CXXMethodDecl *, 4> DelayedDllExportMemberFunctions;
void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
@@ -4877,8 +4807,7 @@ class Sema final {
VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
SourceLocation StartLoc,
- SourceLocation IdLoc,
- IdentifierInfo *Id);
+ SourceLocation IdLoc, IdentifierInfo *Id);
Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
@@ -4919,24 +4848,30 @@ class Sema final {
public:
DefaultedFunctionKind()
- : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {
- }
+ : SpecialMember(CXXInvalid),
+ Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {}
DefaultedFunctionKind(CXXSpecialMember CSM)
- : SpecialMember(CSM), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {}
+ : 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<DefaultedComparisonKind>(Comparison) != DefaultedComparisonKind::None;
+ return static_cast<DefaultedComparisonKind>(Comparison) !=
+ DefaultedComparisonKind::None;
}
explicit operator bool() const {
return isSpecialMember() || isComparison();
}
- CXXSpecialMember asSpecialMember() const { return static_cast<CXXSpecialMember>(SpecialMember); }
- DefaultedComparisonKind asComparison() const { return static_cast<DefaultedComparisonKind>(Comparison); }
+ CXXSpecialMember asSpecialMember() const {
+ return static_cast<CXXSpecialMember>(SpecialMember);
+ }
+ DefaultedComparisonKind asComparison() const {
+ return static_cast<DefaultedComparisonKind>(Comparison);
+ }
/// Get the index of this function kind for use in diagnostics.
unsigned getDiagnosticIndex() const {
@@ -4966,17 +4901,18 @@ class Sema final {
CheckConstexprKind Kind);
void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
- void FindHiddenVirtualMethods(CXXMethodDecl *MD,
- SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
- void NoteHiddenVirtualMethods(CXXMethodDecl *MD,
- SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods);
- void ActOnParamDefaultArgument(Decl *param,
- SourceLocation EqualLoc,
+ void
+ FindHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl *> &OverloadedMethods);
+ void
+ NoteHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<CXXMethodDecl *> &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);
+ Expr *DefaultArg);
ExprResult ConvertParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
SourceLocation EqualLoc);
void SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
@@ -5015,7 +4951,7 @@ class Sema final {
/// Set containing all declared private fields that are not used.
NamedDeclSetType UnusedPrivateFields;
- typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy;
+ typedef llvm::SmallPtrSet<const CXXRecordDecl *, 8> RecordDeclSetTy;
/// PureVirtualClassDiagSet - a set of class declarations which we have
/// emitted a list of pure virtual functions. Used to prevent emitting the
@@ -5136,13 +5072,16 @@ class Sema final {
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 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,
@@ -5279,7 +5218,7 @@ class Sema final {
/// 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<Expr*, 2> VolatileAssignmentLHSs;
+ SmallVector<Expr *, 2> VolatileAssignmentLHSs;
/// Set of candidates for starting an immediate invocation.
llvm::SmallVector<ImmediateInvocationCandidate, 4>
@@ -5298,7 +5237,9 @@ class Sema final {
/// \brief Describes whether we are in an expression constext which we have
/// to handle differently.
enum ExpressionKind {
- EK_Decltype, EK_TemplateArgument, EK_Other
+ EK_Decltype,
+ EK_TemplateArgument,
+ EK_Other
} ExprContext;
// A context can be nested in both a discarded statement context and
@@ -5509,7 +5450,9 @@ class Sema final {
void CleanupVarDeclMarking();
enum TryCaptureKind {
- TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
+ TryCapture_Implicit,
+ TryCapture_ExplicitByVal,
+ TryCapture_ExplicitByRef
};
/// Try to capture the given variable.
@@ -5596,17 +5539,18 @@ class Sema final {
const PartialDiagnostic &PD);
/// Similar, but diagnostic is only produced if all the specified statements
/// are reachable.
- bool DiagRuntimeBehavior(SourceLocation Loc, ArrayRef<const Stmt*> Stmts,
+ bool DiagRuntimeBehavior(SourceLocation Loc, ArrayRef<const Stmt *> Stmts,
const PartialDiagnostic &PD);
// Primary Expressions.
SourceRange getExprRange(Expr *E) const;
- ExprResult ActOnIdExpression(
- Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
- CorrectionCandidateCallback *CCC = nullptr,
- bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
+ ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc, UnqualifiedId &Id,
+ bool HasTrailingLParen, bool IsAddressOfOperand,
+ CorrectionCandidateCallback *CCC = nullptr,
+ bool IsInlineAsmIdentifier = false,
+ Token *KeywordReplacement = nullptr);
void DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer,
@@ -5629,7 +5573,7 @@ class Sema final {
ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
IdentifierInfo *II,
- bool AllowBuiltinCreation=false);
+ bool AllowBuiltinCreation = false);
/// If \p D cannot be odr-used in the current expression evaluation context,
/// return a reason explaining why. Otherwise, return NOUR_None.
@@ -5648,13 +5592,11 @@ class Sema final {
DeclRefExpr *
BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
- NestedNameSpecifierLoc NNS,
- NamedDecl *FoundD = nullptr,
+ NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr,
SourceLocation TemplateKWLoc = SourceLocation(),
const TemplateArgumentListInfo *TemplateArgs = nullptr);
- bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
- const LookupResult &R,
+ bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R,
bool HasTrailingLParen);
ExprResult
@@ -5663,8 +5605,7 @@ class Sema final {
bool IsAddressOfOperand, const Scope *S,
TypeSourceInfo **RecoveryTSI = nullptr);
- ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
- LookupResult &R,
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R,
bool NeedsADL,
bool AcceptInvalidDecl = false);
ExprResult BuildDeclarationNameExpr(
@@ -5697,8 +5638,7 @@ class Sema final {
ExprResult ActOnCharacterConstant(const Token &Tok,
Scope *UDLScope = nullptr);
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E);
- ExprResult ActOnParenListExpr(SourceLocation L,
- SourceLocation R,
+ ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R,
MultiExprArg Val);
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
@@ -5758,11 +5698,10 @@ class Sema final {
SourceRange R);
ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind);
- ExprResult
- ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
- UnaryExprOrTypeTrait ExprKind,
- bool IsType, void *TyOrEx,
- SourceRange ArgRange);
+ ExprResult ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
+ UnaryExprOrTypeTrait ExprKind,
+ bool IsType, void *TyOrEx,
+ SourceRange ArgRange);
ExprResult CheckPlaceholderExpr(Expr *E);
bool CheckVecStepExpr(Expr *E);
@@ -5812,14 +5751,11 @@ class Sema final {
SourceLocation LLoc, SourceLocation RLoc,
ArrayRef<OMPIteratorData> Data);
- bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
- FunctionDecl *FDecl,
+ bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl,
const FunctionProtoType *Proto,
- ArrayRef<Expr *> Args,
- SourceLocation RParenLoc,
+ ArrayRef<Expr *> Args, SourceLocation RParenLoc,
bool ExecConfig = false);
- void CheckStaticArrayArgument(SourceLocation CallLoc,
- ParmVarDecl *Param,
+ void CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param,
const Expr *ArgExpr);
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
@@ -5844,9 +5780,9 @@ class Sema final {
Expr *Config = nullptr, bool IsExecConfig = false,
ADLCallKind UsesADL = ADLCallKind::NotADL);
- ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
- Declarator &D, ParsedType &Ty,
- SourceLocation RParenLoc, Expr *CastExpr);
+ ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, Declarator &D,
+ ParsedType &Ty, SourceLocation RParenLoc,
+ Expr *CastExpr);
CastKind PrepareScalarCast(ExprResult &src, QualType destType);
@@ -5857,28 +5793,24 @@ class Sema final {
ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
- ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
- ParsedType Ty,
- SourceLocation RParenLoc,
- Expr *InitExpr);
+ ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+ SourceLocation RParenLoc, Expr *InitExpr);
ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
TypeSourceInfo *TInfo,
SourceLocation RParenLoc,
Expr *LiteralExpr);
- ExprResult ActOnInitList(SourceLocation LBraceLoc,
- MultiExprArg InitArgList,
+ ExprResult ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
SourceLocation RBraceLoc);
- ExprResult BuildInitList(SourceLocation LBraceLoc,
- MultiExprArg InitArgList,
+ ExprResult BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
SourceLocation RBraceLoc);
- 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 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,
@@ -5889,8 +5821,8 @@ class Sema final {
/// 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);
+ SourceLocation ColonLoc, Expr *CondExpr,
+ Expr *LHSExpr, Expr *RHSExpr);
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
@@ -5920,17 +5852,16 @@ class Sema final {
TypeSourceInfo *TInfo,
ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc);
- ExprResult ActOnBuiltinOffsetOf(Scope *S,
- SourceLocation BuiltinLoc,
+ ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
ParsedType ParsedArgTy,
ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc);
// __builtin_choose_expr(constExpr, expr1, expr2)
- ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
- Expr *CondExpr, Expr *LHSExpr,
- Expr *RHSExpr, SourceLocation RPLoc);
+ ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, Expr *CondExpr,
+ Expr *LHSExpr, Expr *RHSExpr,
+ SourceLocation RPLoc);
// __builtin_va_arg(expr, type)
ExprResult ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty,
@@ -6025,7 +5956,6 @@ class Sema final {
ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
-
/// Instantiate or parse a C++ default argument expression as necessary.
/// Return true on error.
bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
@@ -6059,7 +5989,7 @@ class Sema final {
public:
bool Suppress;
- VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { }
+ VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) {}
virtual SemaDiagnosticBuilder
diagnoseNotICEType(Sema &S, SourceLocation Loc, QualType T);
@@ -6101,18 +6031,14 @@ class Sema final {
class FullExprArg {
public:
- FullExprArg() : E(nullptr) { }
- FullExprArg(Sema &actions) : E(nullptr) { }
+ FullExprArg() : E(nullptr) {}
+ FullExprArg(Sema &actions) : E(nullptr) {}
- ExprResult release() {
- return E;
- }
+ ExprResult release() { return E; }
Expr *get() const { return E; }
- Expr *operator->() {
- return E;
- }
+ Expr *operator->() { return E; }
private:
// FIXME: No need to make the entire Sema class a friend when it's just
@@ -6191,8 +6117,8 @@ class Sema final {
ConditionKind CK, bool MissingOK = false);
QualType CheckConditionalOperands( // C99 6.5.15
- ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
- ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc);
+ ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK,
+ ExprObjectKind &OK, SourceLocation QuestionLoc);
QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc);
@@ -6264,8 +6190,8 @@ class Sema final {
/// Type-check an expression that's being passed to an
/// __unknown_anytype parameter.
- ExprResult checkUnknownAnyArg(SourceLocation callLoc,
- Expr *result, QualType ¶mType);
+ ExprResult checkUnknownAnyArg(SourceLocation callLoc, Expr *result,
+ QualType ¶mType);
// CheckMatrixCast - Check type constraints for matrix casts.
// We allow casting between matrixes of the same dimensions i.e. when they
@@ -6461,8 +6387,7 @@ class Sema final {
/// 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,
+ bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc,
QualType DstType, QualType SrcType,
Expr *SrcExpr, AssignmentAction Action,
bool *Complained = nullptr);
@@ -6478,8 +6403,7 @@ class Sema final {
/// the RHS to the LHS type. The conversion is prepared for if ConvertRHS
/// is true.
AssignConvertType CheckAssignmentConstraints(QualType LHSType,
- ExprResult &RHS,
- CastKind &Kind,
+ ExprResult &RHS, CastKind &Kind,
bool ConvertRHS = true);
/// Check assignment constraints for an assignment of RHS to LHSType.
@@ -6515,20 +6439,20 @@ class Sema final {
ExprResult &RHS);
QualType CheckMultiplyDivideOperands( // C99 6.5.5
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign,
- bool IsDivide);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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,
@@ -6537,8 +6461,8 @@ class Sema final {
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc);
QualType CheckLogicalOperands( // C99 6.5.[13,14]
- ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
- BinaryOperatorKind Opc);
+ 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.
@@ -6664,14 +6588,14 @@ class Sema final {
template <typename... Ts>
bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID,
- const Ts &... Args) {
+ const Ts &...Args) {
SizelessTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser);
}
template <typename... Ts>
bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
- const Ts &... Args) {
+ const Ts &...Args) {
SizelessTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
}
@@ -6717,7 +6641,7 @@ class Sema final {
template <typename... Ts>
class SizelessTypeDiagnoser : public BoundTypeDiagnoser<Ts...> {
public:
- SizelessTypeDiagnoser(unsigned DiagID, const Ts &... Args)
+ SizelessTypeDiagnoser(unsigned DiagID, const Ts &...Args)
: BoundTypeDiagnoser<Ts...>(DiagID, Args...) {}
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
@@ -6814,34 +6738,24 @@ class Sema final {
ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
ParsedType ObjectType);
- ExprResult BuildCXXTypeId(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- TypeSourceInfo *Operand,
- SourceLocation RParenLoc);
- ExprResult BuildCXXTypeId(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- Expr *Operand,
- SourceLocation RParenLoc);
+ ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand, SourceLocation RParenLoc);
+ ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc,
+ Expr *Operand, SourceLocation RParenLoc);
/// ActOnCXXTypeid - Parse typeid( something ).
- ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
- SourceLocation LParenLoc, bool isType,
- void *TyOrExpr,
+ ExprResult ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
+ bool isType, void *TyOrExpr,
SourceLocation RParenLoc);
- ExprResult BuildCXXUuidof(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- TypeSourceInfo *Operand,
- SourceLocation RParenLoc);
- ExprResult BuildCXXUuidof(QualType TypeInfoType,
- SourceLocation TypeidLoc,
- Expr *Operand,
- SourceLocation RParenLoc);
+ ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc,
+ TypeSourceInfo *Operand, SourceLocation RParenLoc);
+ ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc,
+ Expr *Operand, SourceLocation RParenLoc);
/// ActOnCXXUuidof - Parse __uuidof( something ).
- ExprResult ActOnCXXUuidof(SourceLocation OpLoc,
- SourceLocation LParenLoc, bool isType,
- void *TyOrExpr,
+ ExprResult ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
+ bool isType, void *TyOrExpr,
SourceLocation RParenLoc);
//// ActOnCXXThis - Parse 'this' pointer.
@@ -6894,8 +6808,8 @@ class Sema final {
/// 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,
+ bool CheckCXXThisCapture(
+ SourceLocation Loc, bool Explicit = false, bool BuildAndDiagnose = true,
const unsigned *const FunctionScopeIndexToStopAt = nullptr,
bool ByCopy = false);
@@ -6907,7 +6821,6 @@ class Sema final {
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
-
/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
@@ -7004,9 +6917,8 @@ class Sema final {
CXXRecordDecl *RD);
/// ActOnCXXDelete - Parsed a C++ 'delete' expression
- ExprResult ActOnCXXDelete(SourceLocation StartLoc,
- bool UseGlobal, bool ArrayForm,
- Expr *Operand);
+ ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+ bool ArrayForm, Expr *Operand);
void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
bool IsDelete, bool CallCanBeVirtual,
bool WarnOnNonAbstractTypes,
@@ -7017,38 +6929,27 @@ class Sema final {
ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen);
-
-
- ExprResult ActOnStartCXXMemberReference(Scope *S,
- Expr *Base,
+ ExprResult ActOnStartCXXMemberReference(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
ParsedType &ObjectType,
bool &MayBePseudoDestructor);
- ExprResult BuildPseudoDestructorExpr(Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- TypeSourceInfo *ScopeType,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- PseudoDestructorTypeStorage DestroyedType);
+ ExprResult BuildPseudoDestructorExpr(
+ Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind,
+ const CXXScopeSpec &SS, TypeSourceInfo *ScopeType, SourceLocation CCLoc,
+ SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType);
- ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName);
+ ExprResult ActOnPseudoDestructorExpr(
+ Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind,
+ CXXScopeSpec &SS, UnqualifiedId &FirstTypeName, SourceLocation CCLoc,
+ SourceLocation TildeLoc, UnqualifiedId &SecondTypeName);
ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation TildeLoc,
- const DeclSpec& DS);
+ const DeclSpec &DS);
/// MaybeCreateExprWithCleanups - If the current full-expression
/// requires any cleanups, surround it with a ExprWithCleanups node.
@@ -7078,22 +6979,20 @@ class Sema final {
ConditionKind CK);
ExprResult CheckConditionVariable(VarDecl *ConditionVar,
- SourceLocation StmtLoc,
- ConditionKind CK);
+ SourceLocation StmtLoc, ConditionKind CK);
/// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false);
bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
-
- ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
- const ImplicitConversionSequence& ICS,
- AssignmentAction Action,
- CheckedConversionKind CCK
- = CCK_ImplicitConversion);
+ ExprResult
+ PerformImplicitConversion(Expr *From, QualType ToType,
+ const ImplicitConversionSequence &ICS,
+ AssignmentAction Action,
+ CheckedConversionKind CCK = CCK_ImplicitConversion);
ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
- const StandardConversionSequence& SCS,
+ const StandardConversionSequence &SCS,
AssignmentAction Action,
CheckedConversionKind CCK);
@@ -7109,33 +7008,25 @@ class Sema final {
/// ActOnArrayTypeTrait - Parsed one of the binary type trait support
/// pseudo-functions.
- ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
- SourceLocation KWLoc,
- ParsedType LhsTy,
- Expr *DimExpr,
+ ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
+ ParsedType LhsTy, Expr *DimExpr,
SourceLocation RParen);
- ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT,
- SourceLocation KWLoc,
- TypeSourceInfo *TSInfo,
- Expr *DimExpr,
+ ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
+ TypeSourceInfo *TSInfo, Expr *DimExpr,
SourceLocation RParen);
/// ActOnExpressionTrait - Parsed one of the unary type trait support
/// pseudo-functions.
- ExprResult ActOnExpressionTrait(ExpressionTrait OET,
- SourceLocation KWLoc,
- Expr *Queried,
- SourceLocation RParen);
+ ExprResult ActOnExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc,
+ Expr *Queried, SourceLocation RParen);
- ExprResult BuildExpressionTrait(ExpressionTrait OET,
- SourceLocation KWLoc,
- Expr *Queried,
- SourceLocation RParen);
+ ExprResult BuildExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc,
+ Expr *Queried, SourceLocation RParen);
QualType CheckPointerToMemberOperands( // C++ 5.5
- ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK,
- SourceLocation OpLoc, bool isIndirect);
+ ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, SourceLocation OpLoc,
+ bool isIndirect);
QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
ExprResult &RHS,
SourceLocation QuestionLoc);
@@ -7145,14 +7036,13 @@ class Sema final {
SourceLocation QuestionLoc);
QualType CXXCheckConditionalOperands( // C++ 5.16
- ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
- ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
+ ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK,
+ ExprObjectKind &OK, SourceLocation questionLoc);
QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
bool ConvertArgs = true);
- QualType FindCompositePointerType(SourceLocation Loc,
- ExprResult &E1, ExprResult &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);
@@ -7227,39 +7117,37 @@ class Sema final {
CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
const DeclarationNameInfo &TargetNameInfo);
- IfExistsResult
- CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
- bool IsIfExists, CXXScopeSpec &SS,
- UnqualifiedId &Name);
-
+ IfExistsResult CheckMicrosoftIfExistsSymbol(Scope *S,
+ SourceLocation KeywordLoc,
+ bool IsIfExists, CXXScopeSpec &SS,
+ UnqualifiedId &Name);
+
RequiresExprBodyDecl *
ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
ArrayRef<ParmVarDecl *> 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 *ActOnTypeRequirement(SourceLocation TypenameKWLoc,
+ CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ IdentifierInfo *TypeName,
+ TemplateIdAnnotation *TemplateId);
concepts::Requirement *ActOnCompoundRequirement(Expr *E,
SourceLocation NoexceptLoc);
- concepts::Requirement *
- ActOnCompoundRequirement(
+ concepts::Requirement *ActOnCompoundRequirement(
Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
TemplateIdAnnotation *TypeConstraint, unsigned Depth);
concepts::Requirement *ActOnNestedRequirement(Expr *Constraint);
- concepts::ExprRequirement *
- BuildExprRequirement(
+ concepts::ExprRequirement *BuildExprRequirement(
Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
- concepts::ExprRequirement *
- BuildExprRequirement(
+ concepts::ExprRequirement *BuildExprRequirement(
concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag,
bool IsSatisfied, SourceLocation NoexceptLoc,
concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type);
- concepts::TypeRequirement *
- BuildTypeRequirement(
+ concepts::TypeRequirement *BuildTypeRequirement(
concepts::Requirement::SubstitutionDiagnostic *SubstDiag);
concepts::NestedRequirement *BuildNestedRequirement(Expr *E);
concepts::NestedRequirement *
@@ -7298,37 +7186,29 @@ class Sema final {
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);
+ 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);
- ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- CXXScopeSpec &SS,
+ 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);
+ 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,
@@ -7357,8 +7237,7 @@ class Sema final {
Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs,
- const Scope *S,
+ const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
ExprResult
@@ -7367,8 +7246,7 @@ class Sema final {
SourceLocation TemplateKWLoc,
NamedDecl *FirstQualifierInScope, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
- const Scope *S,
- bool SuppressQualifierCheck = false,
+ const Scope *S, bool SuppressQualifierCheck = false,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
@@ -7379,14 +7257,11 @@ class Sema final {
ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
- ExprResult
- BuildAnonymousStructUnionMemberReference(
- const CXXScopeSpec &SS,
- SourceLocation nameLoc,
+ ExprResult BuildAnonymousStructUnionMemberReference(
+ const CXXScopeSpec &SS, SourceLocation nameLoc,
IndirectFieldDecl *indirectField,
DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
- Expr *baseObjectExpr = nullptr,
- SourceLocation opLoc = SourceLocation());
+ Expr *baseObjectExpr = nullptr, SourceLocation opLoc = SourceLocation());
private:
void CheckMemberAccessOfNoDeref(const MemberExpr *E);
@@ -7418,8 +7293,7 @@ class Sema final {
ExprResult ActOnDesignatedInitializer(Designation &Desig,
SourceLocation EqualOrColonLoc,
- bool GNUSyntax,
- ExprResult Init);
+ bool GNUSyntax, ExprResult Init);
/// Check that the lifetime of the initializer (and its subobjects) is
/// sufficient for initializing the entity, and perform lifetime extension
@@ -7442,8 +7316,7 @@ class Sema final {
bool CanPerformCopyInitialization(const InitializedEntity &Entity,
ExprResult Init);
ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
- SourceLocation EqualLoc,
- ExprResult Init,
+ SourceLocation EqualLoc, ExprResult Init,
bool TopLevelOfInitList = false,
bool AllowExplicit = false);
@@ -7600,8 +7473,7 @@ class Sema final {
ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
SourceLocation ConvLocation,
- CXXConversionDecl *Conv,
- Expr *Src);
+ CXXConversionDecl *Conv, Expr *Src);
class LambdaScopeForCallOperatorInstantiationRAII
: private FunctionScopeRAII {
@@ -7680,11 +7552,7 @@ class Sema final {
/// integer are used to determine whether overload resolution succeeded.
class SpecialMemberOverloadResult {
public:
- enum Kind {
- NoMemberOrDeleted,
- Ambiguous,
- Success
- };
+ enum Kind { NoMemberOrDeleted, Ambiguous, Success };
private:
llvm::PointerIntPair<CXXMethodDecl *, 2> Pair;
@@ -7701,13 +7569,11 @@ class Sema final {
void setKind(Kind K) { Pair.setInt(K); }
};
- class SpecialMemberOverloadResultEntry
- : public llvm::FastFoldingSetNode,
- public SpecialMemberOverloadResult {
+ class SpecialMemberOverloadResultEntry : public llvm::FastFoldingSetNode,
+ public SpecialMemberOverloadResult {
public:
SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
- : FastFoldingSetNode(ID)
- {}
+ : FastFoldingSetNode(ID) {}
};
/// A cache of special member function overload resolution results
@@ -7724,7 +7590,7 @@ class Sema final {
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
// TODO: make this is a typesafe union.
- typedef llvm::SmallSetVector<DeclContext *, 16> AssociatedNamespaceSet;
+ typedef llvm::SmallSetVector<DeclContext *, 16> AssociatedNamespaceSet;
typedef llvm::SmallSetVector<CXXRecordDecl *, 16> AssociatedClassSet;
/// Describes the kind of name lookup to perform.
@@ -7802,13 +7668,10 @@ class Sema final {
LOLR_StringTemplatePack,
};
- SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D,
- CXXSpecialMember SM,
- bool ConstArg,
- bool VolatileArg,
- bool RValueThis,
- bool ConstThis,
- bool VolatileThis);
+ SpecialMemberOverloadResult
+ LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg,
+ bool VolatileArg, bool RValueThis, bool ConstThis,
+ bool VolatileThis);
typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator;
typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)>
@@ -7846,10 +7709,8 @@ class Sema final {
/// 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);
+ 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,
@@ -7861,9 +7722,9 @@ class Sema final {
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
bool AllowBuiltinCreation = false,
bool EnteringContext = false);
- ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
- RedeclarationKind Redecl
- = NotForRedeclaration);
+ ObjCProtocolDecl *
+ LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
+ RedeclarationKind Redecl = NotForRedeclaration);
bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class);
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
@@ -7895,7 +7756,7 @@ class Sema final {
/// 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<Module*> &getLookupModules();
+ llvm::DenseSet<Module *> &getLookupModules();
bool hasVisibleMergedDefinition(const NamedDecl *Def);
bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def);
@@ -7979,10 +7840,10 @@ class Sema final {
const PartialDiagnostic &PrevNote,
bool ErrorRecovery = true);
- void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
- ArrayRef<Expr *> Args,
- AssociatedNamespaceSet &AssociatedNamespaces,
- AssociatedClassSet &AssociatedClasses);
+ void FindAssociatedClassesAndNamespaces(
+ SourceLocation InstantiationLoc, ArrayRef<Expr *> Args,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses);
void DiagnoseAmbiguousLookup(LookupResult &Result);
@@ -8011,24 +7872,20 @@ class Sema final {
};
TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
- Sema::LookupNameKind LookupKind,
- Scope *S, CXXScopeSpec *SS,
- CorrectionCandidateCallback &CCC,
+ Sema::LookupNameKind LookupKind, Scope *S,
+ CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
CorrectTypoKind Mode,
DeclContext *MemberContext = nullptr,
bool EnteringContext = false,
const ObjCObjectPointerType *OPT = nullptr,
bool RecordFailure = true);
- 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);
+ 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);
/// Kinds of missing import. Note, the values of these enumerators correspond
/// to %select values in diagnostics.
@@ -8073,7 +7930,7 @@ class Sema final {
//
// The boolean value will be true to indicate that the namespace was loaded
// from an AST/PCH file, or false otherwise.
- llvm::MapVector<NamespaceDecl*, bool> KnownNamespaces;
+ llvm::MapVector<NamespaceDecl *, bool> KnownNamespaces;
/// Whether we have already loaded known namespaces from an extenal
/// source.
@@ -8086,14 +7943,11 @@ class Sema final {
/// 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<TypoCorrectionConsumer>
- makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo,
- Sema::LookupNameKind LookupKind, Scope *S,
- CXXScopeSpec *SS,
- CorrectionCandidateCallback &CCC,
- DeclContext *MemberContext, bool EnteringContext,
- const ObjCObjectPointerType *OPT,
- bool ErrorRecovery);
+ std::unique_ptr<TypoCorrectionConsumer> makeTypoCorrectionConsumer(
+ const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext, bool EnteringContext,
+ const ObjCObjectPointerType *OPT, bool ErrorRecovery);
/// The set of unhandled TypoExprs and their associated state.
llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
@@ -8256,7 +8110,7 @@ class Sema final {
clang::Module *TheImplicitGlobalModuleFragment = nullptr;
/// Namespace definitions that we will export when they finish.
- llvm::SmallPtrSet<const NamespaceDecl*, 8> DeferredExportedNamespaces;
+ llvm::SmallPtrSet<const NamespaceDecl *, 8> 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
@@ -8327,10 +8181,8 @@ class Sema final {
/// non-function.
Ovl_NonFunction
};
- OverloadKind CheckOverload(Scope *S,
- FunctionDecl *New,
- const LookupResult &OldDecls,
- NamedDecl *&OldDecl,
+ OverloadKind CheckOverload(Scope *S, FunctionDecl *New,
+ const LookupResult &OldDecls, NamedDecl *&OldDecl,
bool UseMemberUsingDeclRules);
bool IsOverload(FunctionDecl *New, FunctionDecl *Old,
bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true);
@@ -8349,13 +8201,10 @@ class Sema final {
All
};
- ImplicitConversionSequence
- TryImplicitConversion(Expr *From, QualType ToType,
- bool SuppressUserConversions,
- AllowedExplicit AllowExplicit,
- bool InOverloadResolution,
- bool CStyle,
- bool AllowObjCWritebackConversion);
+ ImplicitConversionSequence TryImplicitConversion(
+ Expr *From, QualType ToType, bool SuppressUserConversions,
+ AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle,
+ bool AllowObjCWritebackConversion);
ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
AssignmentAction Action,
@@ -8365,14 +8214,14 @@ class Sema final {
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 InOverloadResolution, QualType &ConvertedType,
+ bool &IncompatibleObjC);
bool isObjCPointerConversion(QualType FromType, QualType ToType,
- QualType& ConvertedType, bool &IncompatibleObjC);
+ QualType &ConvertedType, bool &IncompatibleObjC);
bool isObjCWritebackConversion(QualType FromType, QualType ToType,
QualType &ConvertedType);
bool IsBlockPointerConversion(QualType FromType, QualType ToType,
- QualType& ConvertedType);
+ QualType &ConvertedType);
bool FunctionParamTypesAreEqual(ArrayRef<QualType> Old,
ArrayRef<QualType> New,
@@ -8389,19 +8238,16 @@ class Sema final {
unsigned *ArgPos = nullptr,
bool Reversed = false);
- void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
- QualType FromType, QualType ToType);
+ void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, QualType FromType,
+ QualType ToType);
- bool CheckPointerConversion(Expr *From, QualType ToType,
- CastKind &Kind,
- CXXCastPath& BasePath,
- bool IgnoreBaseAccess,
+ 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,
+ bool CheckMemberPointerConversion(Expr *From, QualType ToType, CastKind &Kind,
CXXCastPath &BasePath,
bool IgnoreBaseAccess);
bool IsQualificationConversion(QualType FromType, QualType ToType,
@@ -8465,8 +8311,8 @@ class Sema final {
/// Emits a diagnostic complaining that the expression does not have
/// integral or enumeration type.
- virtual SemaDiagnosticBuilder
- diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
+ virtual SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
+ QualType T) = 0;
/// Emits a diagnostic when the expression has incomplete class type.
virtual SemaDiagnosticBuilder
@@ -8474,8 +8320,10 @@ class Sema final {
/// Emits a diagnostic when the only matching conversion function
/// is explicit.
- virtual SemaDiagnosticBuilder diagnoseExplicitConv(
- Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S,
+ SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) = 0;
/// Emits a note for the explicit conversion function.
virtual SemaDiagnosticBuilder
@@ -8483,8 +8331,8 @@ class Sema final {
/// Emits a diagnostic when there are multiple possible conversion
/// functions.
- virtual SemaDiagnosticBuilder
- diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
+ virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+ QualType T) = 0;
/// Emits a note for one of the candidate conversions.
virtual SemaDiagnosticBuilder
@@ -8492,8 +8340,10 @@ class Sema final {
/// 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;
+ virtual SemaDiagnosticBuilder diagnoseConversion(Sema &S,
+ SourceLocation Loc,
+ QualType T,
+ QualType ConvTy) = 0;
virtual ~ContextualImplicitConverter() {}
};
@@ -8502,28 +8352,29 @@ class Sema final {
bool AllowScopedEnumerations;
public:
- ICEConvertDiagnoser(bool AllowScopedEnumerations,
- bool Suppress, bool SuppressConversion)
+ ICEConvertDiagnoser(bool AllowScopedEnumerations, bool Suppress,
+ bool SuppressConversion)
: ContextualImplicitConverter(Suppress, SuppressConversion),
AllowScopedEnumerations(AllowScopedEnumerations) {}
/// Match an integral or (possibly scoped) enumeration type.
bool match(QualType T) override;
- SemaDiagnosticBuilder
- diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override {
+ SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
+ QualType T) override {
return diagnoseNotInt(S, Loc, T);
}
/// Emits a diagnostic complaining that the expression does not have
/// integral or enumeration type.
- virtual SemaDiagnosticBuilder
- diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
+ virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+ QualType T) = 0;
};
/// Perform a contextual implicit conversion.
- ExprResult PerformContextualImplicitConversion(
- SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
+ ExprResult
+ PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE,
+ ContextualImplicitConverter &Converter);
/// ReferenceCompareResult - Expresses the result of comparing two
/// types (cv1 T1 and cv2 T2) to determine their compatibility for the
@@ -8571,18 +8422,16 @@ class Sema final {
ConversionSequenceList EarlyConversions = std::nullopt,
OverloadCandidateParamOrder PO = {},
bool AggregateCandidateDeduction = false);
- void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
- ArrayRef<Expr *> Args,
- OverloadCandidateSet &CandidateSet,
- TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
- bool SuppressUserConversions = false,
- bool PartialOverloading = false,
- bool FirstArgumentIsBase = false);
- void AddMethodCandidate(DeclAccessPair FoundDecl,
- QualType ObjectType,
+ void AddFunctionCandidates(
+ const UnresolvedSetImpl &Functions, ArrayRef<Expr *> 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<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
bool SuppressUserConversion = false,
OverloadCandidateParamOrder PO = {});
void
@@ -8594,17 +8443,13 @@ class Sema final {
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<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
- bool SuppressUserConversions = false,
- bool PartialOverloading = false,
- OverloadCandidateParamOrder PO = {});
+ void AddMethodTemplateCandidate(
+ FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType,
+ Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+ bool PartialOverloading = false, OverloadCandidateParamOrder PO = {});
void AddTemplateOverloadCandidate(
FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
@@ -8633,9 +8478,9 @@ class Sema final {
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
- const FunctionProtoType *Proto,
- Expr *Object, ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet);
+ const FunctionProtoType *Proto, Expr *Object,
+ ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet);
void AddNonMemberOperatorCandidates(
const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
@@ -8645,18 +8490,16 @@ class Sema final {
OverloadCandidateSet &CandidateSet,
OverloadCandidateParamOrder PO = {});
void AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
bool IsAssignmentOperator = false,
unsigned NumContextualBoolArguments = 0);
void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
SourceLocation OpLoc, ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet);
- void AddArgumentDependentLookupCandidates(DeclarationName Name,
- SourceLocation Loc,
- ArrayRef<Expr *> Args,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- OverloadCandidateSet& CandidateSet,
- bool PartialOverloading = false);
+ OverloadCandidateSet &CandidateSet);
+ void AddArgumentDependentLookupCandidates(
+ DeclarationName Name, SourceLocation Loc, ArrayRef<Expr *> Args,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ OverloadCandidateSet &CandidateSet, bool PartialOverloading = false);
/// Check the enable_if expressions on the given function. Returns the first
/// failing attribute, or NULL if they were all successful.
@@ -8723,10 +8566,8 @@ class Sema final {
QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType);
FunctionDecl *
- ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
- QualType TargetType,
- bool Complain,
- DeclAccessPair &Found,
+ ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
+ bool Complain, DeclAccessPair &Found,
bool *pHadMultipleCandidates = nullptr);
FunctionDecl *
@@ -8745,8 +8586,6 @@ class Sema final {
QualType DestTypeForComplaining = QualType(),
unsigned DiagIDForComplaining = 0);
-
-
void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
ArrayRef<Expr *> Args,
OverloadCandidateSet &CandidateSet,
@@ -8770,14 +8609,10 @@ class Sema final {
OverloadCandidateSet *CandidateSet,
Expr *Range, ExprResult *CallExpr);
- ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
- UnresolvedLookupExpr *ULE,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation RParenLoc,
- Expr *ExecConfig,
- bool AllowTypoCorrection=true,
- bool CalleesAddressIsTaken=false);
+ ExprResult BuildOverloadedCallExpr(
+ Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc,
+ MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig,
+ bool AllowTypoCorrection = true, bool CalleesAddressIsTaken = false);
bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
MultiExprArg Args, SourceLocation RParenLoc,
@@ -8792,18 +8627,16 @@ class Sema final {
ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
UnaryOperatorKind Opc,
- const UnresolvedSetImpl &Fns,
- Expr *input, bool RequiresADL = true);
+ const UnresolvedSetImpl &Fns, Expr *input,
+ bool RequiresADL = true);
void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
OverloadedOperatorKind Op,
const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args, bool RequiresADL = true);
- ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
- BinaryOperatorKind Opc,
- const UnresolvedSetImpl &Fns,
- Expr *LHS, Expr *RHS,
- 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,
@@ -8815,17 +8648,14 @@ class Sema final {
SourceLocation RLoc, Expr *Base,
MultiExprArg Args);
- 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);
+ 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);
ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
@@ -8835,11 +8665,10 @@ class Sema final {
CXXConversionDecl *Method,
bool HadMultipleCandidates);
- ExprResult BuildLiteralOperatorCall(LookupResult &R,
- DeclarationNameInfo &SuffixInfo,
- ArrayRef<Expr *> Args,
- SourceLocation LitEndLoc,
- TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+ ExprResult BuildLiteralOperatorCall(
+ LookupResult &R, DeclarationNameInfo &SuffixInfo, ArrayRef<Expr *> Args,
+ SourceLocation LitEndLoc,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
FunctionDecl *Fn);
@@ -8852,7 +8681,7 @@ class Sema final {
/// nullptr if none could be found
ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args,
bool IsInstance,
- SmallVectorImpl<ObjCMethodDecl*>& Methods);
+ SmallVectorImpl<ObjCMethodDecl *> &Methods);
/// @}
@@ -8870,18 +8699,14 @@ class Sema final {
void maybeExtendBlockObject(ExprResult &E);
CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
- enum ObjCSubscriptKind {
- OS_Array,
- OS_Dictionary,
- OS_Error
- };
+ enum ObjCSubscriptKind { OS_Array, OS_Dictionary, OS_Error };
ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc,
UnaryOperatorKind Opcode, Expr *Op);
ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc,
- BinaryOperatorKind Opcode,
- Expr *LHS, Expr *RHS);
+ BinaryOperatorKind Opcode, Expr *LHS,
+ Expr *RHS);
ExprResult checkPseudoObjectRValue(Expr *E);
Expr *recreateSyntacticForm(PseudoObjectExpr *E);
@@ -8899,7 +8724,7 @@ class Sema final {
public:
/// Stack of active SEH __finally scopes. Can be empty.
- SmallVector<Scope*, 2> CurrentSEHFinally;
+ SmallVector<Scope *, 2> CurrentSEHFinally;
StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
StmtResult ActOnExprStmtError();
@@ -8907,9 +8732,8 @@ class Sema final {
StmtResult ActOnNullStmt(SourceLocation SemiLoc,
bool HasLeadingEmptyMacro = false);
- StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
- SourceLocation StartLoc,
- SourceLocation EndLoc);
+ StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc,
+ SourceLocation EndLoc);
void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
/// DiagnoseUnusedExprResult - If the statement passed in is an expression
@@ -8931,8 +8755,8 @@ class Sema final {
void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
- SourceLocation ColonLoc,
- Stmt *SubStmt, Scope *CurScope);
+ SourceLocation ColonLoc, Stmt *SubStmt,
+ Scope *CurScope);
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt);
@@ -8962,8 +8786,8 @@ class Sema final {
SourceLocation LParenLoc, Stmt *InitStmt,
ConditionResult Cond,
SourceLocation RParenLoc);
- StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
- Stmt *Switch, Stmt *Body);
+ StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
+ Stmt *Body);
/// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant
/// integer not in the range of enum values.
@@ -8977,20 +8801,17 @@ class Sema final {
SourceLocation WhileLoc, SourceLocation CondLParen,
Expr *Cond, SourceLocation CondRParen);
- StmtResult ActOnForStmt(SourceLocation ForLoc,
- SourceLocation LParenLoc,
- Stmt *First,
- ConditionResult Second,
- FullExprArg Third,
- SourceLocation RParenLoc,
+ StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+ Stmt *First, ConditionResult Second,
+ FullExprArg Third, SourceLocation RParenLoc,
Stmt *Body);
StmtResult ActOnForEachLValueExpr(Expr *E);
ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
Expr *collection);
- StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
- Stmt *First, Expr *collection,
+ StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, Stmt *First,
+ Expr *collection,
SourceLocation RParenLoc);
StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
@@ -9018,12 +8839,10 @@ class Sema final {
ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps = {});
StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
- StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
- SourceLocation LabelLoc,
+ StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
LabelDecl *TheDecl);
StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
- SourceLocation StarLoc,
- Expr *DestExp);
+ SourceLocation StarLoc, Expr *DestExp);
StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope);
@@ -9075,22 +8894,20 @@ class Sema final {
Scope *CurScope);
ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc,
Expr *operand);
- StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
- Expr *SynchExpr,
+ StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SynchExpr,
Stmt *SynchBody);
StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
- StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
- Decl *ExDecl, Stmt *HandlerBlock);
+ StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
+ Stmt *HandlerBlock);
StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
ArrayRef<Stmt *> Handlers);
StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
SourceLocation TryLoc, Stmt *TryBlock,
Stmt *Handler);
- StmtResult ActOnSEHExceptBlock(SourceLocation Loc,
- Expr *FilterExpr,
+ StmtResult ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr,
Stmt *Block);
void ActOnStartSEHFinallyBlock();
void ActOnAbortSEHFinallyBlock();
@@ -9103,9 +8920,8 @@ class Sema final {
DeclarationNameInfo NameInfo,
Stmt *Nested);
StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
- bool IsIfExists,
- CXXScopeSpec &SS, UnqualifiedId &Name,
- Stmt *Nested);
+ bool IsIfExists, CXXScopeSpec &SS,
+ UnqualifiedId &Name, Stmt *Nested);
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
CapturedRegionKind Kind, unsigned NumParams);
@@ -9147,8 +8963,7 @@ class Sema final {
unsigned NumInputs, IdentifierInfo **Names,
MultiExprArg Constraints, MultiExprArg Exprs,
Expr *AsmString, MultiExprArg Clobbers,
- unsigned NumLabels,
- SourceLocation RParenLoc);
+ unsigned NumLabels, SourceLocation RParenLoc);
void FillInlineAsmIdentifierInfo(Expr *Res,
llvm::InlineAsmIdentifierInfo &Info);
@@ -9156,21 +8971,18 @@ class Sema final {
SourceLocation TemplateKWLoc,
UnqualifiedId &Id,
bool IsUnevaluatedContext);
- bool LookupInlineAsmField(StringRef Base, StringRef Member,
- unsigned &Offset, SourceLocation AsmLoc);
+ 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<Token> AsmToks,
- StringRef AsmString,
+ ArrayRef<Token> AsmToks, StringRef AsmString,
unsigned NumOutputs, unsigned NumInputs,
ArrayRef<StringRef> Constraints,
ArrayRef<StringRef> Clobbers,
- ArrayRef<Expr*> Exprs,
- SourceLocation EndLoc);
+ ArrayRef<Expr *> Exprs, SourceLocation EndLoc);
LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
- SourceLocation Location,
- bool AlwaysCreate);
+ SourceLocation Location, bool AlwaysCreate);
/// @}
@@ -9239,7 +9051,7 @@ class Sema final {
/// The number of SFINAE diagnostics that have been trapped.
unsigned NumSFINAEErrors;
- ArrayRef<sema::FunctionScopeInfo*> getFunctionScopes() const {
+ ArrayRef<sema::FunctionScopeInfo *> getFunctionScopes() const {
return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
FunctionScopes.end());
}
@@ -9287,7 +9099,9 @@ class Sema final {
SourceLocation getTemplateKeywordLoc() const {
return TemplateKW.value_or(SourceLocation());
}
- bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
+ bool hasTemplateKeyword() const {
+ return getTemplateKeywordLoc().isValid();
+ }
bool isRequired() const { return TemplateKW != SourceLocation(); }
explicit operator bool() const { return isRequired(); }
@@ -9310,12 +9124,10 @@ class Sema final {
RequiredTemplateKind RequiredTemplate = SourceLocation(),
AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
- TemplateNameKind isTemplateName(Scope *S,
- CXXScopeSpec &SS,
+ TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
bool hasTemplateKeyword,
const UnqualifiedId &Name,
- ParsedType ObjectType,
- bool EnteringContext,
+ ParsedType ObjectType, bool EnteringContext,
TemplateTy &Template,
bool &MemberOfUnknownSpecialization,
bool Disambiguation = false);
@@ -9341,8 +9153,7 @@ class Sema final {
ParsedTemplateTy *Template = nullptr);
bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
- SourceLocation IILoc,
- Scope *S,
+ SourceLocation IILoc, Scope *S,
const CXXScopeSpec *SS,
TemplateTy &SuggestedTemplate,
TemplateNameKind &SuggestedKind);
@@ -9362,9 +9173,8 @@ class Sema final {
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc,
- unsigned Depth, unsigned Position,
- SourceLocation EqualLoc,
+ SourceLocation ParamNameLoc, unsigned Depth,
+ unsigned Position, SourceLocation EqualLoc,
ParsedType DefaultArg, bool HasTypeConstraint);
bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
@@ -9398,29 +9208,19 @@ class Sema final {
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
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<NamedDecl *> Params,
- SourceLocation RAngleLoc,
- Expr *RequiresClause);
+ 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<NamedDecl *> Params,
+ SourceLocation RAngleLoc, Expr *RequiresClause);
/// The context in which we are checking a template parameter list.
enum TemplateParamListContext {
@@ -9441,8 +9241,8 @@ class Sema final {
TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
SourceLocation DeclStartLoc, SourceLocation DeclLoc,
const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
- ArrayRef<TemplateParameterList *> ParamLists,
- bool IsFriend, bool &IsMemberSpecialization, bool &Invalid,
+ ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
+ bool &IsMemberSpecialization, bool &Invalid,
bool SuppressDiagnostic = false);
DeclResult CheckClassTemplate(
@@ -9463,7 +9263,7 @@ class Sema final {
QualType CheckTemplateIdType(TemplateName Template,
SourceLocation TemplateLoc,
- TemplateArgumentListInfo &TemplateArgs);
+ TemplateArgumentListInfo &TemplateArgs);
TypeResult
ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
@@ -9476,16 +9276,11 @@ class Sema final {
/// Parsed an elaborated-type-specifier that refers to a template-id,
/// such as \c class T::template apply<U>.
- TypeResult ActOnTagTemplateIdType(TagUseKind TUK,
- TypeSpecifierType TagSpec,
- SourceLocation TagLoc,
- CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- TemplateTy TemplateD,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation RAngleLoc);
+ 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,
@@ -9510,8 +9305,7 @@ class Sema final {
const TemplateArgumentListInfo *TemplateArgs);
ExprResult
- CheckConceptTemplateId(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
+ CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const TemplateArgumentListInfo *TemplateArgs);
@@ -9519,20 +9313,21 @@ class Sema final {
void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- LookupResult &R,
+ SourceLocation TemplateKWLoc, LookupResult &R,
bool RequiresADL,
- const TemplateArgumentListInfo *TemplateArgs);
+ const TemplateArgumentListInfo *TemplateArgs);
- ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
+ ExprResult
+ BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
- TemplateNameKind ActOnTemplateName(
- Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
- TemplateTy &Template, bool AllowInjectedClassName = false);
+ TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext, TemplateTy &Template,
+ bool AllowInjectedClassName = false);
DeclResult ActOnClassTemplateSpecialization(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
@@ -9554,13 +9349,11 @@ class Sema final {
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D);
- bool
- CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
- TemplateSpecializationKind ActOnExplicitInstantiationNewTSK,
- NamedDecl *PrevDecl,
- TemplateSpecializationKind PrevTSK,
- SourceLocation PrevPtOfInstantiation,
- bool &SuppressNew);
+ bool CheckSpecializationInstantiationRedecl(
+ SourceLocation NewLoc,
+ TemplateSpecializationKind ActOnExplicitInstantiationNewTSK,
+ NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPtOfInstantiation, bool &SuppressNew);
bool CheckDependentFunctionTemplateSpecialization(
FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
@@ -9586,8 +9379,7 @@ class Sema final {
SourceLocation NameLoc,
const ParsedAttributesView &Attr);
- DeclResult ActOnExplicitInstantiation(Scope *S,
- SourceLocation ExternLoc,
+ DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
SourceLocation TemplateLoc,
Declarator &D);
@@ -9679,10 +9471,8 @@ class Sema final {
std::optional<SourceRange> ParamRange = {});
void NoteTemplateParameterLocation(const NamedDecl &Decl);
- ExprResult
- BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
- QualType ParamType,
- SourceLocation Loc);
+ ExprResult BuildExpressionFromDeclTemplateArgument(
+ const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc);
ExprResult
BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc);
@@ -9817,39 +9607,31 @@ class Sema final {
/// \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);
+ const CXXScopeSpec &SS, SourceLocation TemplateLoc,
+ TemplateTy TemplateName, IdentifierInfo *TemplateII,
+ SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc);
QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
SourceLocation KeywordLoc,
NestedNameSpecifierLoc QualifierLoc,
- const IdentifierInfo &II,
- SourceLocation IILoc,
- TypeSourceInfo **TSI,
- bool DeducedTSTContext);
+ const IdentifierInfo &II, SourceLocation IILoc,
+ TypeSourceInfo **TSI, bool DeducedTSTContext);
QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
SourceLocation KeywordLoc,
NestedNameSpecifierLoc QualifierLoc,
- const IdentifierInfo &II,
- SourceLocation IILoc,
+ const IdentifierInfo &II, SourceLocation IILoc,
bool DeducedTSTContext = true);
-
TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
SourceLocation Loc,
DeclarationName Name);
bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
ExprResult RebuildExprInCurrentInstantiation(Expr *E);
- bool RebuildTemplateParamsInCurrentInstantiation(
- TemplateParameterList *Params);
+ bool
+ RebuildTemplateParamsInCurrentInstantiation(TemplateParameterList *Params);
std::string
getTemplateArgumentBindingsText(const TemplateParameterList *Params,
@@ -9864,16 +9646,16 @@ class Sema final {
SourceLocation Less,
SourceLocation Greater);
- ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- bool isAddressOfOperand,
- const TemplateArgumentListInfo *TemplateArgs);
+ ExprResult ActOnDependentIdExpression(
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo, bool isAddressOfOperand,
+ const TemplateArgumentListInfo *TemplateArgs);
- ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
+ ExprResult
+ BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
// Calculates whether the expression Constraint depends on an enclosing
// template, for the purposes of [temp.friend] p9.
@@ -9901,20 +9683,17 @@ class Sema final {
void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
- Decl *ActOnConceptDefinition(
- Scope *S, MultiTemplateParamsArg TemplateParameterLists,
- IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr);
+ Decl *ActOnConceptDefinition(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ Expr *ConstraintExpr);
void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
bool &AddToScope);
- TypeResult ActOnDependentTag(Scope *S,
- unsigned TagSpec,
- TagUseKind TUK,
- const CXXScopeSpec &SS,
- IdentifierInfo *Name,
- SourceLocation TagLoc,
- SourceLocation NameLoc);
+ TypeResult ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ const CXXScopeSpec &SS, IdentifierInfo *Name,
+ SourceLocation TagLoc, SourceLocation NameLoc);
void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
CachedTokens &Toks);
@@ -9956,13 +9735,12 @@ class Sema final {
public:
explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false)
- : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors),
- PrevInNonInstantiationSFINAEContext(
- SemaRef.InNonInstantiationSFINAEContext),
- PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE),
- PrevLastDiagnosticIgnored(
- SemaRef.getDiagnostics().isLastDiagnosticIgnored())
- {
+ : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors),
+ PrevInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext),
+ PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE),
+ PrevLastDiagnosticIgnored(
+ SemaRef.getDiagnostics().isLastDiagnosticIgnored()) {
if (!SemaRef.isSFINAEContext())
SemaRef.InNonInstantiationSFINAEContext = true;
SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE;
@@ -9970,8 +9748,8 @@ class Sema final {
~SFINAETrap() {
SemaRef.NumSFINAEErrors = PrevSFINAEErrors;
- SemaRef.InNonInstantiationSFINAEContext
- = PrevInNonInstantiationSFINAEContext;
+ SemaRef.InNonInstantiationSFINAEContext =
+ PrevInNonInstantiationSFINAEContext;
SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
SemaRef.getDiagnostics().setLastDiagnosticIgnored(
PrevLastDiagnosticIgnored);
@@ -10071,7 +9849,7 @@ class Sema final {
sema::TemplateDeductionInfo &Info,
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
bool PartialOverloading = false,
- llvm::function_ref<bool()> CheckNonDependent = []{ return false; });
+ llvm::function_ref<bool()> CheckNonDependent = [] { return false; });
TemplateDeductionResult DeduceTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
@@ -10081,13 +9859,11 @@ class Sema final {
QualType ObjectType, Expr::Classification ObjectClassification,
llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent);
- TemplateDeductionResult
- DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
- TemplateArgumentListInfo *ExplicitTemplateArgs,
- QualType ArgFunctionType,
- FunctionDecl *&Specialization,
- sema::TemplateDeductionInfo &Info,
- bool IsAddressOfFunction = false);
+ TemplateDeductionResult DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType,
+ FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction = false);
TemplateDeductionResult DeduceTemplateArguments(
FunctionTemplateDecl *FunctionTemplate, QualType ObjectType,
@@ -10104,7 +9880,7 @@ class Sema final {
/// Substitute Replacement for \p auto in \p TypeWithAuto
QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
/// Substitute Replacement for auto in TypeWithAuto
- TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ TypeSourceInfo *SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
QualType Replacement);
// Substitute auto in TypeWithAuto for a Dependent auto type
@@ -10135,9 +9911,8 @@ class Sema final {
ClassTemplatePartialSpecializationDecl *
getMoreSpecializedPartialSpecialization(
- ClassTemplatePartialSpecializationDecl *PS1,
- ClassTemplatePartialSpecializationDecl *PS2,
- SourceLocation Loc);
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
sema::TemplateDeductionInfo &Info);
@@ -10156,17 +9931,17 @@ class Sema final {
unsigned Depth, llvm::SmallBitVector &Used);
void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
- bool OnlyDeduced,
- unsigned Depth,
+ bool OnlyDeduced, unsigned Depth,
llvm::SmallBitVector &Used);
- void MarkDeducedTemplateParameters(
- const FunctionTemplateDecl *FunctionTemplate,
- llvm::SmallBitVector &Deduced) {
+ void
+ MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallBitVector &Deduced) {
return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced);
}
- static void MarkDeducedTemplateParameters(ASTContext &Ctx,
- const FunctionTemplateDecl *FunctionTemplate,
- llvm::SmallBitVector &Deduced);
+ static void
+ MarkDeducedTemplateParameters(ASTContext &Ctx,
+ const FunctionTemplateDecl *FunctionTemplate,
+ llvm::SmallBitVector &Deduced);
FunctionTemplateDecl *getMoreSpecializedTemplate(
FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
@@ -10175,8 +9950,7 @@ class Sema final {
UnresolvedSetIterator
getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
TemplateSpecCandidateSet &FailedCandidates,
- SourceLocation Loc,
- const PartialDiagnostic &NoneDiag,
+ SourceLocation Loc, const PartialDiagnostic &NoneDiag,
const PartialDiagnostic &AmbigDiag,
const PartialDiagnostic &CandidateDiag,
bool Complain = true, QualType TargetType = QualType());
@@ -10490,24 +10264,21 @@ class Sema final {
/// Note that we are substituting prior template arguments into a
/// non-type parameter.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- NamedDecl *Template,
- NonTypeTemplateParmDecl *Param,
+ NamedDecl *Template, NonTypeTemplateParmDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
/// Note that we are substituting prior template arguments into a
/// template template parameter.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- NamedDecl *Template,
- TemplateTemplateParmDecl *Param,
+ NamedDecl *Template, TemplateTemplateParmDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
/// 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,
+ TemplateDecl *Template, NamedDecl *Param,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange InstantiationRange);
@@ -10594,10 +10365,9 @@ class Sema final {
ArrayRef<TemplateArgument> TemplateArgs = std::nullopt,
sema::TemplateDeductionInfo *DeductionInfo = nullptr);
- InstantiatingTemplate(const InstantiatingTemplate&) = delete;
+ InstantiatingTemplate(const InstantiatingTemplate &) = delete;
- InstantiatingTemplate&
- operator=(const InstantiatingTemplate&) = delete;
+ InstantiatingTemplate &operator=(const InstantiatingTemplate &) = delete;
};
bool
@@ -10677,16 +10447,16 @@ class Sema final {
/// Extra modules inspected when performing a lookup during a template
/// instantiation. Computed lazily.
- SmallVector<Module*, 16> CodeSynthesisContextLookupModules;
+ SmallVector<Module *, 16> CodeSynthesisContextLookupModules;
/// 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<Module*> LookupModulesCache;
+ llvm::DenseSet<Module *> LookupModulesCache;
/// Map from the most recent declaration of a namespace to the most
/// recent visible declaration of that namespace.
- llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache;
+ llvm::DenseMap<NamedDecl *, NamedDecl *> VisibleNamespaceCache;
/// Whether we are in a SFINAE context that is not associated with
/// template instantiation.
@@ -10738,7 +10508,7 @@ class Sema final {
public:
ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
- : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+ : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
}
@@ -10854,21 +10624,17 @@ class Sema final {
StmtResult SubstStmt(Stmt *S,
const MultiLevelTemplateArgumentList &TemplateArgs);
- ExprResult SubstInitializer(Expr *E,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- bool CXXDirectInit);
+ ExprResult
+ SubstInitializer(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool CXXDirectInit);
- bool
- SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
- CXXRecordDecl *Pattern,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ 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 InstantiateClass(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK, bool Complain = true);
bool InstantiateEnum(SourceLocation PointOfInstantiation,
EnumDecl *Instantiation, EnumDecl *Pattern,
@@ -10882,25 +10648,25 @@ class Sema final {
bool usesPartialOrExplicitSpecialization(
SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec);
- bool
- InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *ClassTemplateSpec,
- TemplateSpecializationKind TSK,
- bool Complain = true);
+ bool InstantiateClassTemplateSpecialization(
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK, bool Complain = true);
- void InstantiateClassMembers(SourceLocation PointOfInstantiation,
- CXXRecordDecl *Instantiation,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- TemplateSpecializationKind TSK);
+ void
+ InstantiateClassMembers(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK);
void InstantiateClassTemplateSpecializationMembers(
- SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *ClassTemplateSpec,
- TemplateSpecializationKind TSK);
+ SourceLocation PointOfInstantiation,
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK);
- NestedNameSpecifierLoc
- SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ NestedNameSpecifierLoc SubstNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
DeclarationNameInfo
SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
@@ -10994,7 +10760,7 @@ class Sema final {
FPOptionsOverride getOverrides() { return OldOverrides; }
private:
- Sema& S;
+ Sema &S;
FPOptions OldFPFeaturesState;
FPOptionsOverride OldOverrides;
LangOptions::FPEvalMethodKind OldEvalMethod;
@@ -11064,8 +10830,7 @@ class Sema final {
LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
Decl *D)
- : TmplAttr(A), Scope(S), NewDecl(D)
- { }
+ : TmplAttr(A), Scope(S), NewDecl(D) {}
};
typedef SmallVector<LateInstantiatedAttribute, 16> LateInstantiatedAttrVec;
@@ -11123,14 +10888,16 @@ class Sema final {
bool DefinitionRequired = false,
bool AtEndOfTU = false);
- void InstantiateMemInitializers(CXXConstructorDecl *New,
- const CXXConstructorDecl *Tmpl,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ 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,
+ 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,
@@ -11148,8 +10915,9 @@ class Sema final {
const MultiLevelTemplateArgumentList &TemplateArgs,
bool EvaluateConstraints = true);
- void PerformDependentDiagnostics(const DeclContext *Pattern,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ void PerformDependentDiagnostics(
+ const DeclContext *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
private:
/// Introduce the instantiated local variables into the local
@@ -11300,9 +11068,9 @@ class Sema final {
/// \param Unexpanded the set of unexpanded parameter packs.
///
/// \returns true if an error occurred, false otherwise.
- bool DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
- UnexpandedParameterPackContext UPPC,
- ArrayRef<UnexpandedParameterPack> Unexpanded);
+ bool DiagnoseUnexpandedParameterPacks(
+ SourceLocation Loc, UnexpandedParameterPackContext UPPC,
+ ArrayRef<UnexpandedParameterPack> Unexpanded);
/// If the given type contains an unexpanded parameter pack,
/// diagnose the error.
@@ -11323,8 +11091,8 @@ class Sema final {
/// parameter packs.
///
/// \returns true if an error occurred, false otherwise.
- bool DiagnoseUnexpandedParameterPack(Expr *E,
- UnexpandedParameterPackContext UPPC = UPPC_Expression);
+ 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.
@@ -11383,48 +11151,52 @@ class Sema final {
///
/// \param Arg The template argument that will be traversed to find
/// unexpanded parameter packs.
- void collectUnexpandedParameterPacks(TemplateArgument Arg,
- SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+ void collectUnexpandedParameterPacks(
+ TemplateArgument Arg,
+ SmallVectorImpl<UnexpandedParameterPack> &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<UnexpandedParameterPack> &Unexpanded);
+ void collectUnexpandedParameterPacks(
+ TemplateArgumentLoc Arg,
+ SmallVectorImpl<UnexpandedParameterPack> &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<UnexpandedParameterPack> &Unexpanded);
+ void collectUnexpandedParameterPacks(
+ QualType T, SmallVectorImpl<UnexpandedParameterPack> &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<UnexpandedParameterPack> &Unexpanded);
+ void collectUnexpandedParameterPacks(
+ TypeLoc TL, SmallVectorImpl<UnexpandedParameterPack> &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<UnexpandedParameterPack> &Unexpanded);
+ void collectUnexpandedParameterPacks(
+ NestedNameSpecifierLoc NNS,
+ SmallVectorImpl<UnexpandedParameterPack> &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<UnexpandedParameterPack> &Unexpanded);
+ void collectUnexpandedParameterPacks(
+ const DeclarationNameInfo &NameInfo,
+ SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
/// Invoked when parsing a template argument followed by an
/// ellipsis, which creates a pack expansion.
@@ -11563,8 +11335,7 @@ class Sema final {
/// avoid actually expanding the pack where possible.
std::optional<unsigned> getFullyPackExpandedSize(TemplateArgument Arg);
- ExprResult ActOnSizeofParameterPackExpr(Scope *S,
- SourceLocation OpLoc,
+ ExprResult ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc,
IdentifierInfo &Name,
SourceLocation NameLoc,
SourceLocation RParenLoc);
@@ -11618,8 +11389,7 @@ class Sema final {
bool SatisfactionStackContains(const NamedDecl *D,
const llvm::FoldingSetNodeID &ID) const {
const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
- return llvm::find(SatisfactionStack,
- SatisfactionStackEntryTy{Can, ID}) !=
+ return llvm::find(SatisfactionStack, SatisfactionStackEntryTy{Can, ID}) !=
SatisfactionStack.end();
}
@@ -11630,8 +11400,7 @@ class Sema final {
// constraints as a 'side effect' of normal instantiation in a way that is not
// indicative of recursive definition.
class SatisfactionStackResetRAII {
- llvm::SmallVector<SatisfactionStackEntryTy, 10>
- BackupSatisfactionStack;
+ llvm::SmallVector<SatisfactionStackEntryTy, 10> BackupSatisfactionStack;
Sema &SemaRef;
public:
@@ -11772,9 +11541,8 @@ class Sema final {
/// 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);
+ void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
+ bool First = true);
/// \brief Emit diagnostics explaining why a constraint expression was deemed
/// unsatisfied.
@@ -11782,8 +11550,7 @@ class Sema final {
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
bool First = true);
- const NormalizedConstraint *
- getNormalizedAssociatedConstraints(
+ const NormalizedConstraint *getNormalizedAssociatedConstraints(
NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints);
/// \brief Check whether the given declaration's associated constraints are
@@ -11802,8 +11569,9 @@ class Sema final {
/// 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<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2);
+ bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+ NamedDecl *D1, ArrayRef<const Expr *> AC1, NamedDecl *D2,
+ ArrayRef<const Expr *> AC2);
private:
/// Caches pairs of template-like decls whose associated constraints were
@@ -11814,15 +11582,13 @@ class Sema final {
/// constrained declarations). If an error occurred while normalizing the
/// associated constraints of the template or concept, nullptr will be cached
/// here.
- llvm::DenseMap<NamedDecl *, NormalizedConstraint *>
- NormalizationCache;
+ llvm::DenseMap<NamedDecl *, NormalizedConstraint *> NormalizationCache;
llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
SatisfactionCache;
// The current stack of constraint satisfactions, so we can exit-early.
- llvm::SmallVector<SatisfactionStackEntryTy, 10>
- SatisfactionStack;
+ llvm::SmallVector<SatisfactionStackEntryTy, 10> SatisfactionStack;
/// Introduce the instantiated captures of the lambda into the local
/// instantiation scope.
@@ -11865,7 +11631,7 @@ class Sema final {
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 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) {
@@ -11876,7 +11642,7 @@ class Sema final {
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();}
+ static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange(); }
enum class CompleteTypeKind {
/// Apply the normal rules for complete types. In particular,
@@ -11895,23 +11661,16 @@ class Sema final {
/// Build a an Objective-C protocol-qualified 'id' type where no
/// base type was specified.
TypeResult actOnObjCProtocolQualifierType(
- SourceLocation lAngleLoc,
- ArrayRef<Decl *> protocols,
- ArrayRef<SourceLocation> protocolLocs,
- SourceLocation rAngleLoc);
+ SourceLocation lAngleLoc, ArrayRef<Decl *> protocols,
+ ArrayRef<SourceLocation> protocolLocs, SourceLocation rAngleLoc);
/// Build a specialized and/or protocol-qualified Objective-C type.
TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
- Scope *S,
- SourceLocation Loc,
- ParsedType BaseType,
- SourceLocation TypeArgsLAngleLoc,
- ArrayRef<ParsedType> TypeArgs,
- SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<Decl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc);
+ Scope *S, SourceLocation Loc, ParsedType BaseType,
+ SourceLocation TypeArgsLAngleLoc, ArrayRef<ParsedType> TypeArgs,
+ SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc,
+ ArrayRef<Decl *> Protocols, ArrayRef<SourceLocation> ProtocolLocs,
+ SourceLocation ProtocolRAngleLoc);
/// Build an Objective-C type parameter type.
QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
@@ -11933,10 +11692,10 @@ class Sema final {
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 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);
@@ -11984,22 +11743,18 @@ class Sema final {
/// \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<QualType> ParamTypes,
+ QualType BuildFunctionType(QualType T, MutableArrayRef<QualType> 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);
+ 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 BuildReadPipeType(QualType T, SourceLocation Loc);
+ QualType BuildWritePipeType(QualType T, SourceLocation Loc);
QualType BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D);
@@ -12195,7 +11950,7 @@ class Sema final {
bool OnlyNeedComplete = false);
bool hasVisibleDefinition(const NamedDecl *D) {
NamedDecl *Hidden;
- return hasVisibleDefinition(const_cast<NamedDecl*>(D), &Hidden);
+ return hasVisibleDefinition(const_cast<NamedDecl *>(D), &Hidden);
}
/// Determine if \p D has a reachable definition. If not, suggest a
@@ -12294,10 +12049,7 @@ class Sema final {
typedef llvm::SmallPtrSet<Selector, 8> SelectorSet;
- enum MethodMatchStrategy {
- MMS_loose,
- MMS_strict
- };
+ enum MethodMatchStrategy { MMS_loose, MMS_strict };
enum ObjCContainerKind {
OCK_None = -1,
@@ -12310,14 +12062,11 @@ class Sema final {
};
ObjCContainerKind getObjCContainerKind() const;
- DeclResult actOnObjCTypeParam(Scope *S,
- ObjCTypeParamVariance variance,
- SourceLocation varianceLoc,
- unsigned index,
+ DeclResult actOnObjCTypeParam(Scope *S, ObjCTypeParamVariance variance,
+ SourceLocation varianceLoc, unsigned index,
IdentifierInfo *paramName,
SourceLocation paramLoc,
- SourceLocation colonLoc,
- ParsedType typeBound);
+ SourceLocation colonLoc, ParsedType typeBound);
ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
ArrayRef<Decl *> typeParams,
@@ -12333,30 +12082,26 @@ class Sema final {
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<ParsedType> SuperTypeArgs,
- SourceRange SuperTypeArgsRange);
+ void ActOnSuperClassOfClassInterface(
+ Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperName, SourceLocation SuperLoc,
+ ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange);
void ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs,
SmallVectorImpl<SourceLocation> &ProtocolLocs,
IdentifierInfo *SuperName,
SourceLocation SuperLoc);
- Decl *ActOnCompatibilityAlias(
- SourceLocation AtCompatibilityAliasLoc,
- IdentifierInfo *AliasName, SourceLocation AliasLocation,
- IdentifierInfo *ClassName, SourceLocation ClassLocation);
+ Decl *ActOnCompatibilityAlias(SourceLocation AtCompatibilityAliasLoc,
+ IdentifierInfo *AliasName,
+ SourceLocation AliasLocation,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLocation);
bool CheckForwardProtocolDeclarationForCircularDependency(
- IdentifierInfo *PName,
- SourceLocation &PLoc, SourceLocation PrevLoc,
- const ObjCList<ObjCProtocolDecl> &PList);
+ IdentifierInfo *PName, SourceLocation &PLoc, SourceLocation PrevLoc,
+ const ObjCList<ObjCProtocolDecl> &PList);
ObjCProtocolDecl *ActOnStartProtocolInterface(
SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
@@ -12405,19 +12150,13 @@ class Sema final {
/// names to either Objective-C protocol qualifiers or type
/// arguments, as appropriate.
void actOnObjCTypeArgsOrProtocolQualifiers(
- Scope *S,
- ParsedType baseType,
- SourceLocation lAngleLoc,
- ArrayRef<IdentifierInfo *> identifiers,
- ArrayRef<SourceLocation> identifierLocs,
- SourceLocation rAngleLoc,
- SourceLocation &typeArgsLAngleLoc,
- SmallVectorImpl<ParsedType> &typeArgs,
- SourceLocation &typeArgsRAngleLoc,
- SourceLocation &protocolLAngleLoc,
- SmallVectorImpl<Decl *> &protocols,
- SourceLocation &protocolRAngleLoc,
- bool warnOnIncompleteProtocols);
+ Scope *S, ParsedType baseType, SourceLocation lAngleLoc,
+ ArrayRef<IdentifierInfo *> identifiers,
+ ArrayRef<SourceLocation> identifierLocs, SourceLocation rAngleLoc,
+ SourceLocation &typeArgsLAngleLoc, SmallVectorImpl<ParsedType> &typeArgs,
+ SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc,
+ SmallVectorImpl<Decl *> &protocols, SourceLocation &protocolRAngleLoc,
+ bool warnOnIncompleteProtocols);
void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
ObjCInterfaceDecl *ID);
@@ -12479,9 +12218,7 @@ class Sema final {
void AddAnyMethodToGlobalPool(Decl *D);
void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
- bool isObjCMethodDecl(Decl *D) {
- return D && isa<ObjCMethodDecl>(D);
- }
+ bool isObjCMethodDecl(Decl *D) { return D && isa<ObjCMethodDecl>(D); }
/// CheckImplementationIvars - This routine checks if the instance variables
/// listed in the implelementation match those listed in the interface.
@@ -12499,21 +12236,16 @@ class Sema final {
/// WarnExactTypedMethods - This routine issues a warning if method
/// implementation declaration matches exactly that of its declaration.
- void WarnExactTypedMethods(ObjCMethodDecl *Method,
- ObjCMethodDecl *MethodDecl,
+ void WarnExactTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl,
bool IsProtocolMethodDecl);
/// 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);
+ void MatchAllMethodDeclarations(
+ const SelectorSet &InsMap, const SelectorSet &ClsMap,
+ SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl,
+ ObjCContainerDecl *IDecl, bool &IncompleteImpl, bool ImmediateClass,
+ bool WarnCategoryMethodImpl = false);
/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
/// category matches with those implemented in its primary class and
@@ -12522,15 +12254,13 @@ class Sema final {
/// 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,
+ void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl,
+ ObjCContainerDecl *IDecl,
bool IncompleteImpl = false);
- DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
- IdentifierInfo **IdentList,
- SourceLocation *IdentLocs,
- ArrayRef<ObjCTypeParamList *> TypeParamLists,
- unsigned NumElts);
+ DeclGroupPtrTy ActOnForwardClassDeclaration(
+ SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs,
+ ArrayRef<ObjCTypeParamList *> TypeParamLists, unsigned NumElts);
/// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
/// true, or false, accordingly.
@@ -12551,22 +12281,22 @@ class Sema final {
/// returns true.
bool
CollectMultipleMethodsInGlobalPool(Selector Sel,
- SmallVectorImpl<ObjCMethodDecl*>& Methods,
+ SmallVectorImpl<ObjCMethodDecl *> &Methods,
bool InstanceFirst, bool CheckTheOther,
const ObjCObjectType *TypeBound = nullptr);
bool
AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
SourceRange R, bool receiverIdOrClass,
- SmallVectorImpl<ObjCMethodDecl*>& Methods);
+ SmallVectorImpl<ObjCMethodDecl *> &Methods);
void
- DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+ DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl *> &Methods,
Selector Sel, SourceRange R,
bool receiverIdOrClass);
- const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
- QualType ObjectType=QualType());
+ const ObjCMethodDecl *
+ SelectorsForTypoCorrection(Selector Sel, QualType ObjectType = QualType());
/// LookupImplementedMethodInGlobalPool - Returns the method which has an
/// implementation.
ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
@@ -12579,45 +12309,46 @@ class Sema final {
bool CheckObjCDeclScope(Decl *D);
void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
- IdentifierInfo *ClassName,
- SmallVectorImpl<Decl *> &Decls);
+ IdentifierInfo *ClassName, SmallVectorImpl<Decl *> &Decls);
VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
- SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- bool Invalid = false);
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, bool Invalid = false);
Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
/// initialization.
- void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
- SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+ void
+ CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+ SmallVectorImpl<ObjCIvarDecl *> &Ivars);
void DiagnoseUseOfUnimplementedSelectors();
- /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which
- /// backs the property is not used in the property's accessor.
+ /// 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);
/// 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;
+ /// 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;
/// 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);
+ void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method,
+ bool impl = false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/ true);
}
/// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
- void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
- AddMethodToGlobalPool(Method, impl, /*instance*/false);
+ void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl = false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/ false);
}
private:
@@ -12692,20 +12423,17 @@ class Sema final {
/// will hold 'respondsToSelector:'
Selector RespondsToSelectorSel;
- ExprResult
- HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
- Expr *BaseExpr,
- SourceLocation OpLoc,
- DeclarationName MemberName,
- SourceLocation MemberLoc,
- SourceLocation SuperLoc, QualType SuperType,
- bool Super);
+ ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+ Expr *BaseExpr, SourceLocation OpLoc,
+ DeclarationName MemberName,
+ SourceLocation MemberLoc,
+ SourceLocation SuperLoc,
+ QualType SuperType, bool Super);
- ExprResult
- ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
- IdentifierInfo &propertyName,
- SourceLocation receiverNameLoc,
- SourceLocation propertyNameLoc);
+ ExprResult ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+ IdentifierInfo &propertyName,
+ SourceLocation receiverNameLoc,
+ SourceLocation propertyNameLoc);
// ParseObjCStringLiteral - Parse Objective-C string literals.
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
@@ -12733,8 +12461,9 @@ class Sema final {
ObjCMethodDecl *getterMethod,
ObjCMethodDecl *setterMethod);
- ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
- MutableArrayRef<ObjCDictionaryElement> Elements);
+ ExprResult
+ BuildObjCDictionaryLiteral(SourceRange SR,
+ MutableArrayRef<ObjCDictionaryElement> Elements);
ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
TypeSourceInfo *EncodedTypeInfo,
@@ -12742,20 +12471,18 @@ class Sema final {
ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
SourceLocation EncodeLoc,
- SourceLocation LParenLoc,
- ParsedType Ty,
+ SourceLocation LParenLoc, ParsedType Ty,
SourceLocation RParenLoc);
/// ParseObjCSelectorExpression - Build selector expression for \@selector
- ExprResult ParseObjCSelectorExpression(Selector Sel,
- SourceLocation AtLoc,
+ ExprResult ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc,
SourceLocation SelLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc,
bool WarnMultipleSelectors);
/// ParseObjCProtocolExpression - Build protocol expression for \@protocol
- ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+ ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolName,
SourceLocation AtLoc,
SourceLocation ProtoLoc,
SourceLocation LParenLoc,
@@ -12776,84 +12503,61 @@ class Sema final {
ObjCClassMessage
};
- ObjCMessageKind getObjCMessageKind(Scope *S,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- bool IsSuper,
+ ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name,
+ SourceLocation NameLoc, bool IsSuper,
bool HasTrailingDot,
ParsedType &ReceiverType);
- ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
- Selector Sel,
+ ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, Selector Sel,
SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
- SourceLocation RBracLoc,
- MultiExprArg Args);
+ SourceLocation RBracLoc, MultiExprArg Args);
ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
- QualType ReceiverType,
- SourceLocation SuperLoc,
- Selector Sel,
- ObjCMethodDecl *Method,
+ QualType ReceiverType, SourceLocation SuperLoc,
+ Selector Sel, ObjCMethodDecl *Method,
SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
- SourceLocation RBracLoc,
- MultiExprArg Args,
+ SourceLocation RBracLoc, MultiExprArg Args,
bool isImplicit = false);
ExprResult BuildClassMessageImplicit(QualType ReceiverType,
- bool isSuperReceiver,
- SourceLocation Loc,
- Selector Sel,
- ObjCMethodDecl *Method,
+ bool isSuperReceiver, SourceLocation Loc,
+ Selector Sel, ObjCMethodDecl *Method,
MultiExprArg Args);
- ExprResult ActOnClassMessage(Scope *S,
- ParsedType Receiver,
- Selector Sel,
+ ExprResult ActOnClassMessage(Scope *S, ParsedType Receiver, Selector Sel,
SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
- SourceLocation RBracLoc,
- MultiExprArg Args);
+ SourceLocation RBracLoc, MultiExprArg Args);
- ExprResult BuildInstanceMessage(Expr *Receiver,
- QualType ReceiverType,
- SourceLocation SuperLoc,
- Selector Sel,
+ ExprResult BuildInstanceMessage(Expr *Receiver, QualType ReceiverType,
+ SourceLocation SuperLoc, Selector Sel,
ObjCMethodDecl *Method,
SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
- SourceLocation RBracLoc,
- MultiExprArg Args,
+ SourceLocation RBracLoc, MultiExprArg Args,
bool isImplicit = false);
- ExprResult BuildInstanceMessageImplicit(Expr *Receiver,
- QualType ReceiverType,
- SourceLocation Loc,
- Selector Sel,
+ ExprResult BuildInstanceMessageImplicit(Expr *Receiver, QualType ReceiverType,
+ SourceLocation Loc, Selector Sel,
ObjCMethodDecl *Method,
MultiExprArg Args);
- ExprResult ActOnInstanceMessage(Scope *S,
- Expr *Receiver,
- Selector Sel,
+ ExprResult ActOnInstanceMessage(Scope *S, Expr *Receiver, Selector Sel,
SourceLocation LBracLoc,
ArrayRef<SourceLocation> SelectorLocs,
- SourceLocation RBracLoc,
- MultiExprArg Args);
+ SourceLocation RBracLoc, MultiExprArg Args);
ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc,
ObjCBridgeCastKind Kind,
SourceLocation BridgeKeywordLoc,
- TypeSourceInfo *TSInfo,
- Expr *SubExpr);
+ TypeSourceInfo *TSInfo, Expr *SubExpr);
- ExprResult ActOnObjCBridgedCast(Scope *S,
- SourceLocation LParenLoc,
+ ExprResult ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc,
ObjCBridgeCastKind Kind,
SourceLocation BridgeKeywordLoc,
- ParsedType Type,
- SourceLocation RParenLoc,
+ ParsedType Type, SourceLocation RParenLoc,
Expr *SubExpr);
void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr);
@@ -12863,17 +12567,17 @@ class Sema final {
bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
CastKind &Kind);
- bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
- QualType DestType, QualType SrcType,
+ bool checkObjCBridgeRelatedComponents(SourceLocation Loc, QualType DestType,
+ QualType SrcType,
ObjCInterfaceDecl *&RelatedClass,
ObjCMethodDecl *&ClassMethod,
ObjCMethodDecl *&InstanceMethod,
- TypedefNameDecl *&TDNDecl,
- bool CfToNs, bool Diagnose = true);
+ TypedefNameDecl *&TDNDecl, bool CfToNs,
+ bool Diagnose = true);
- bool CheckObjCBridgeRelatedConversions(SourceLocation Loc,
- QualType DestType, QualType SrcType,
- Expr *&SrcExpr, bool Diagnose = true);
+ bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType,
+ QualType SrcType, Expr *&SrcExpr,
+ bool Diagnose = true);
/// Private Helper predicate to check for 'self'.
bool isSelfExpr(Expr *RExpr);
@@ -12935,18 +12639,20 @@ class Sema final {
/// LookupInstanceMethodInGlobalPool - Returns the method and warns if
/// there are multiple signatures.
- ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
- bool receiverIdOrClass=false) {
+ ObjCMethodDecl *
+ LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass = false) {
return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
- /*instance*/true);
+ /*instance*/ true);
}
/// LookupFactoryMethodInGlobalPool - Returns the method and warns if
/// there are multiple signatures.
- ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
- bool receiverIdOrClass=false) {
+ ObjCMethodDecl *
+ LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
+ bool receiverIdOrClass = false) {
return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
- /*instance*/false);
+ /*instance*/ false);
}
/// @}
@@ -12965,8 +12671,7 @@ class Sema final {
/// 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,
+ void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc,
unsigned &Attributes,
bool propertyInPrimaryClass);
@@ -12975,17 +12680,14 @@ class Sema final {
/// \param property The property declaration being processed
void ProcessPropertyDecl(ObjCPropertyDecl *property);
- Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
- SourceLocation LParenLoc,
+ 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,
+ Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc,
+ SourceLocation PropertyLoc, bool ImplKind,
IdentifierInfo *PropertyId,
IdentifierInfo *PropertyIvar,
SourceLocation PropertyIvarLoc,
@@ -12993,39 +12695,24 @@ class Sema final {
/// 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);
+ 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);
+ 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,
@@ -13038,7 +12725,7 @@ class Sema final {
/// DiagnoseUnimplementedProperties - This routine warns on those properties
/// which must be implemented by this implementation.
- void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
+ void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl,
ObjCContainerDecl *CDecl,
bool SynthesizeProperties);
@@ -13060,15 +12747,15 @@ class Sema final {
void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
- void DiagnoseMissingDesignatedInitOverrides(
- const ObjCImplementationDecl *ImplD,
- const ObjCInterfaceDecl *IFD);
+ 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);
+ void AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl,
+ ObjCInterfaceDecl *IDecl);
/// @}
@@ -13137,13 +12824,11 @@ class Sema final {
void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
void CodeCompleteOrdinaryName(Scope *S,
ParserCompletionContext CompletionContext);
- void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
- bool AllowNonIdentifiers,
+ void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers,
bool AllowNestedNameSpecifiers);
struct CodeCompleteExpressionData;
- void CodeCompleteExpression(Scope *S,
- const CodeCompleteExpressionData &Data);
+ void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data);
void CodeCompleteExpression(Scope *S, QualType PreferredType,
bool IsParenthesized = false);
void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase,
@@ -13205,8 +12890,7 @@ class Sema final {
void CodeCompleteNamespaceAliasDecl(Scope *S);
void CodeCompleteOperatorName(Scope *S);
void CodeCompleteConstructorInitializer(
- Decl *Constructor,
- ArrayRef<CXXCtorInitializer *> Initializers);
+ Decl *Constructor, ArrayRef<CXXCtorInitializer *> Initializers);
void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
bool AfterAmpersand);
@@ -13233,21 +12917,17 @@ class Sema final {
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
ObjCInterfaceDecl *Super = nullptr);
- void CodeCompleteObjCForCollection(Scope *S,
- DeclGroupPtrTy IterationVar);
- void CodeCompleteObjCSelector(Scope *S,
- ArrayRef<IdentifierInfo *> SelIdents);
- void CodeCompleteObjCProtocolReferences(
- ArrayRef<IdentifierLocPair> Protocols);
+ void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar);
+ void CodeCompleteObjCSelector(Scope *S, ArrayRef<IdentifierInfo *> SelIdents);
+ void
+ CodeCompleteObjCProtocolReferences(ArrayRef<IdentifierLocPair> Protocols);
void CodeCompleteObjCProtocolDecl(Scope *S);
void CodeCompleteObjCInterfaceDecl(Scope *S);
void CodeCompleteObjCClassForwardDecl(Scope *S);
- void CodeCompleteObjCSuperclass(Scope *S,
- IdentifierInfo *ClassName,
+ void CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
SourceLocation ClassNameLoc);
void CodeCompleteObjCImplementationDecl(Scope *S);
- void CodeCompleteObjCInterfaceCategory(Scope *S,
- IdentifierInfo *ClassName,
+ void CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName,
SourceLocation ClassNameLoc);
void CodeCompleteObjCImplementationCategory(Scope *S,
IdentifierInfo *ClassName,
@@ -13258,8 +12938,7 @@ class Sema final {
void CodeCompleteObjCMethodDecl(Scope *S,
std::optional<bool> IsInstanceMethod,
ParsedType ReturnType);
- void CodeCompleteObjCMethodDeclSelector(Scope *S,
- bool IsInstanceMethod,
+ void CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod,
bool AtParameterName,
ParsedType ReturnType,
ArrayRef<IdentifierInfo *> SelIdents);
@@ -13270,16 +12949,16 @@ class Sema final {
void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
void CodeCompletePreprocessorMacroName(bool IsDefinition);
void CodeCompletePreprocessorExpression();
- void CodeCompletePreprocessorMacroArgument(Scope *S,
- IdentifierInfo *Macro,
+ 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<CodeCompletionResult> &Results);
+ void
+ GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ SmallVectorImpl<CodeCompletionResult> &Results);
/// @}
@@ -13295,8 +12974,8 @@ class Sema final {
public:
/// Get a string to suggest for zero-initialization of a type.
- std::string
- getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const;
+ std::string getFixItZeroInitializerForType(QualType T,
+ SourceLocation Loc) const;
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
/// @}
@@ -13815,9 +13494,8 @@ class Sema final {
const DeclarationNameInfo &Id,
OpenMPDirectiveKind Kind);
/// Called on well-formed '#pragma omp threadprivate'.
- DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
- SourceLocation Loc,
- ArrayRef<Expr *> VarList);
+ DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
+ ArrayRef<Expr *> VarList);
/// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
ArrayRef<Expr *> VarList);
@@ -13998,8 +13676,7 @@ class Sema final {
/// Called on well-formed '\#pragma omp parallel' after parsing
/// of the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt,
- SourceLocation StartLoc,
+ Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
using VarsWithInheritedDSAType =
llvm::SmallDenseMap<const ValueDecl *, const Expr *, 4>;
@@ -14144,7 +13821,8 @@ class Sema final {
/// Called on well-formed '\#pragma omp target data' after parsing of
/// the associated statement.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
- Stmt *AStmt, SourceLocation StartLoc,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp target enter data' after
/// parsing of the associated statement.
@@ -14413,8 +14091,7 @@ class Sema final {
ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
SourceLocation AppendArgsLoc, SourceRange SR);
- OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
- Expr *Expr,
+ OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
@@ -14444,8 +14121,7 @@ class Sema final {
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-formed 'safelen' clause.
- OMPClause *ActOnOpenMPSafelenClause(Expr *Length,
- SourceLocation StartLoc,
+ OMPClause *ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-formed 'simdlen' clause.
@@ -14495,8 +14171,7 @@ class Sema final {
SourceLocation LParenLoc,
SourceLocation EndLoc);
- OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
- unsigned Argument,
+ OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument,
SourceLocation ArgumentLoc,
SourceLocation StartLoc,
SourceLocation LParenLoc,
@@ -14572,9 +14247,11 @@ class Sema final {
/// Called on well-formed 'fail' clause.
OMPClause *ActOnOpenMPFailClause(SourceLocation StartLoc,
SourceLocation EndLoc);
- OMPClause *ActOnOpenMPFailClause(
- OpenMPClauseKind Kind, SourceLocation KindLoc,
- SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+ OMPClause *ActOnOpenMPFailClause(OpenMPClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Called on well-formed 'seq_cst' clause.
OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
@@ -14767,8 +14444,7 @@ class Sema final {
SourceLocation LinLoc, SourceLocation ColonLoc,
SourceLocation StepModifierLoc, SourceLocation EndLoc);
/// Called on well-formed 'aligned' clause.
- OMPClause *ActOnOpenMPAlignedClause(ArrayRef<Expr *> VarList,
- Expr *Alignment,
+ OMPClause *ActOnOpenMPAlignedClause(ArrayRef<Expr *> VarList, Expr *Alignment,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation ColonLoc,
>From c0ee64f139f60f624c9f8829bad5a3622780d9a0 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Feb 2024 10:00:44 +0300
Subject: [PATCH 3/8] Commit clang-format suggestion
---
clang/include/clang/Sema/Sema.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e039f9719826d3..d28987db2da64b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3967,7 +3967,7 @@ class Sema final {
const ProcessDeclAttributeOptions &Options =
ProcessDeclAttributeOptions());
bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
- const ParsedAttributesView &AttrList);
+ const ParsedAttributesView &AttrList);
void checkUnusedDeclAttributes(Declarator &D);
>From d8ee5da8129cbbef91e2416da8f1f23f0fdd2526 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Feb 2024 10:03:31 +0300
Subject: [PATCH 4/8] Fix formatting in table of contents
---
clang/include/clang/Sema/Sema.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d28987db2da64b..3d1eb8c976935a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -453,7 +453,7 @@ class Sema final {
// 26. C++ Template Argument Deduction (SemaTemplateDeduction.cpp)
// 27. C++ Template Instantiation (SemaTemplateInstantiate.cpp)
// 28. C++ Template Declaration Instantiation
- // (SemaTemplateInstantiateDecl.cpp)
+ // (SemaTemplateInstantiateDecl.cpp)
// 29. C++ Variadic Templates (SemaTemplateVariadic.cpp)
// 30. Constraints and Concepts (SemaConcept.cpp)
// 31. Types (SemaType.cpp)
>From c91770724736f928a00bfaf8b2427d49ba95a1e0 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Mon, 19 Feb 2024 10:54:58 +0300
Subject: [PATCH 5/8] Fix doxygen syntax
---
clang/include/clang/Sema/Sema.h | 169 ++++++++++++++++----------------
1 file changed, 85 insertions(+), 84 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3d1eb8c976935a..5154381072b8cb 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -422,6 +422,7 @@ enum class TemplateDeductionResult {
};
/// Sema - This implements semantic analysis and AST building for C.
+/// \nosubgrouping
class Sema final {
// Table of Contents
// -----------------
@@ -471,7 +472,7 @@ class Sema final {
/// \name Semantic Analysis
/// Implementations are in Sema.cpp
- /// @{
+ ///@{
public:
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
@@ -1193,7 +1194,7 @@ class Sema final {
mutable IdentifierInfo *Ident_super;
- /// @}
+ ///@}
//
//
@@ -1203,7 +1204,7 @@ class Sema final {
/// \name C++ Access Control
/// Implementations are in SemaAccess.cpp
- /// @{
+ ///@{
public:
enum AccessResult {
@@ -1280,7 +1281,7 @@ class Sema final {
const MultiLevelTemplateArgumentList &TemplateArgs);
void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
- /// @}
+ ///@}
//
//
@@ -1290,7 +1291,7 @@ class Sema final {
/// \name Attributes
/// Implementations are in SemaAttr.cpp
- /// @{
+ ///@{
public:
/// Controls member pointer representation format under the MS ABI.
@@ -1887,7 +1888,7 @@ class Sema final {
bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
bool SkipArgCountCheck = false);
- /// @}
+ ///@}
//
//
@@ -1897,7 +1898,7 @@ class Sema final {
/// \name Availability Attribute Handling
/// Implementations are in SemaAvailability.cpp
- /// @{
+ ///@{
public:
/// Issue any -Wunguarded-availability warnings in \c FD
@@ -1915,7 +1916,7 @@ class Sema final {
bool AvoidPartialAvailabilityChecks = false,
ObjCInterfaceDecl *ClassReceiver = nullptr);
- /// @}
+ ///@}
//
//
@@ -1925,7 +1926,7 @@ class Sema final {
/// \name Casts
/// Implementations are in SemaCast.cpp
- /// @{
+ ///@{
public:
static bool isCast(CheckedConversionKind CCK) {
@@ -1977,7 +1978,7 @@ class Sema final {
Expr *CastExpr,
SourceLocation RParenLoc);
- /// @}
+ ///@}
//
//
@@ -1987,7 +1988,7 @@ class Sema final {
/// \name Extra Semantic Checking
/// Implementations are in SemaChecking.cpp
- /// @{
+ ///@{
public:
/// Used to change context to isConstantEvaluated without pushing a heavy
@@ -2397,7 +2398,7 @@ class Sema final {
/// Adds an expression to the set of gathered misaligned members.
void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
CharUnits Alignment);
- /// @}
+ ///@}
//
//
@@ -2407,7 +2408,7 @@ class Sema final {
/// \name C++ Coroutines
/// Implementations are in SemaCoroutine.cpp
- /// @{
+ ///@{
public:
/// The C++ "std::coroutine_traits" template, which is defined in
@@ -2448,7 +2449,7 @@ class Sema final {
/// potentially-throwing.
bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend);
- /// @}
+ ///@}
//
//
@@ -2458,7 +2459,7 @@ class Sema final {
/// \name C++ Scope Specifiers
/// Implementations are in SemaCXXScopeSpec.cpp
- /// @{
+ ///@{
public:
// Marks SS invalid if it represents an incomplete type.
@@ -2645,7 +2646,7 @@ class Sema final {
/// defining scope.
void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
- /// @}
+ ///@}
//
//
@@ -2655,7 +2656,7 @@ class Sema final {
/// \name Declarations
/// Implementations are in SemaDecl.cpp
- /// @{
+ ///@{
public:
IdentifierResolver IdResolver;
@@ -3673,7 +3674,7 @@ class Sema final {
/// it looks like the user is trying to modify the shadowing declaration.
llvm::DenseMap<const NamedDecl *, const NamedDecl *> ShadowingDecls;
- /// @}
+ ///@}
//
//
@@ -3683,7 +3684,7 @@ class Sema final {
/// \name Declaration Attribute Handling
/// Implementations are in SemaDeclAttr.cpp
- /// @{
+ ///@{
public:
/// Describes the kind of priority given to an availability attribute.
@@ -3983,7 +3984,7 @@ class Sema final {
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
- /// @}
+ ///@}
//
//
@@ -3993,7 +3994,7 @@ class Sema final {
/// \name C++ Declarations
/// Implementations are in SemaDeclCXX.cpp
- /// @{
+ ///@{
public:
void CheckDelegatingCtorCycles();
@@ -5024,7 +5025,7 @@ class Sema final {
const CXXRecordDecl *RD,
bool DeclIsField = true);
- /// @}
+ ///@}
//
//
@@ -5034,7 +5035,7 @@ class Sema final {
/// \name C++ Exception Specifications
/// Implementations are in SemaExceptionSpec.cpp
- /// @{
+ ///@{
public:
/// All the overriding functions seen during a class definition
@@ -5102,7 +5103,7 @@ class Sema final {
bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
const CXXMethodDecl *Old);
- /// @}
+ ///@}
//
//
@@ -5112,7 +5113,7 @@ class Sema final {
/// \name Expressions
/// Implementations are in SemaExpr.cpp
- /// @{
+ ///@{
public:
/// Describes how the expressions currently being parsed are
@@ -6683,7 +6684,7 @@ class Sema final {
void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E);
void CheckAddressOfNoDeref(const Expr *E);
- /// @}
+ ///@}
//
//
@@ -6693,7 +6694,7 @@ class Sema final {
/// \name C++ Expressions
/// Implementations are in SemaExprCXX.cpp
- /// @{
+ ///@{
public:
/// The C++ "std::bad_alloc" class, which is defined by the C++
@@ -7169,7 +7170,7 @@ class Sema final {
void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
bool DeleteWasArrayForm);
- /// @}
+ ///@}
//
//
@@ -7179,7 +7180,7 @@ class Sema final {
/// \name Member Access Expressions
/// Implementations are in SemaExprMember.cpp
- /// @{
+ ///@{
public:
ExprResult BuildPossibleImplicitMemberExpr(
@@ -7266,7 +7267,7 @@ class Sema final {
private:
void CheckMemberAccessOfNoDeref(const MemberExpr *E);
- /// @}
+ ///@}
//
//
@@ -7276,7 +7277,7 @@ class Sema final {
/// \name Initializers
/// Implementations are in SemaInit.cpp
- /// @{
+ ///@{
public:
/// Stack of types that correspond to the parameter entities that are
@@ -7324,7 +7325,7 @@ class Sema final {
TypeSourceInfo *TInfo, const InitializedEntity &Entity,
const InitializationKind &Kind, MultiExprArg Init);
- /// @}
+ ///@}
//
//
@@ -7334,7 +7335,7 @@ class Sema final {
/// \name C++ Lambda Expressions
/// Implementations are in SemaLambda.cpp
- /// @{
+ ///@{
public:
/// Create a new lambda closure type.
@@ -7492,7 +7493,7 @@ class Sema final {
std::tuple<MangleNumberingContext *, Decl *>
getCurrentMangleNumberContext(const DeclContext *DC);
- /// @}
+ ///@}
//
//
@@ -7527,7 +7528,7 @@ class Sema final {
/// the ability to distinguish among them.
///
/// Implementations are in SemaLookup.cpp
- /// @{
+ ///@{
public:
/// Tracks whether we are in a context where typo correction is
@@ -7970,7 +7971,7 @@ class Sema final {
bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
- /// @}
+ ///@}
//
//
@@ -7980,7 +7981,7 @@ class Sema final {
/// \name Modules
/// Implementations are in SemaModule.cpp
- /// @{
+ ///@{
public:
/// Get the module unit whose scope we are currently within.
@@ -8133,7 +8134,7 @@ class Sema final {
VisibleModuleSet VisibleModules;
- /// @}
+ ///@}
//
//
@@ -8143,7 +8144,7 @@ class Sema final {
/// \name C++ Overloading
/// Implementations are in SemaOverload.cpp
- /// @{
+ ///@{
public:
/// Whether deferrable diagnostics should be deferred.
@@ -8683,7 +8684,7 @@ class Sema final {
bool IsInstance,
SmallVectorImpl<ObjCMethodDecl *> &Methods);
- /// @}
+ ///@}
//
//
@@ -8693,7 +8694,7 @@ class Sema final {
/// \name Pseudo-Object
/// Implementations are in SemaPseudoObject.cpp
- /// @{
+ ///@{
public:
void maybeExtendBlockObject(ExprResult &E);
@@ -8710,7 +8711,7 @@ class Sema final {
ExprResult checkPseudoObjectRValue(Expr *E);
Expr *recreateSyntacticForm(PseudoObjectExpr *E);
- /// @}
+ ///@}
//
//
@@ -8720,7 +8721,7 @@ class Sema final {
/// \name Statements
/// Implementations are in SemaStmt.cpp
- /// @{
+ ///@{
public:
/// Stack of active SEH __finally scopes. Can be empty.
@@ -8945,7 +8946,7 @@ class Sema final {
/// statement that produces control flow different from GCC.
void CheckBreakContinueBinding(Expr *E);
- /// @}
+ ///@}
//
//
@@ -8955,7 +8956,7 @@ class Sema final {
/// \name `inline asm` Statement
/// Implementations are in SemaStmtAsm.cpp
- /// @{
+ ///@{
public:
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
@@ -8984,7 +8985,7 @@ class Sema final {
LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
SourceLocation Location, bool AlwaysCreate);
- /// @}
+ ///@}
//
//
@@ -8994,7 +8995,7 @@ class Sema final {
/// \name Statement Attribute Handling
/// Implementations are in SemaStmtAttr.cpp
- /// @{
+ ///@{
public:
bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
@@ -9010,7 +9011,7 @@ class Sema final {
void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs,
SmallVectorImpl<const Attr *> &OutAttrs);
- /// @}
+ ///@}
//
//
@@ -9020,7 +9021,7 @@ class Sema final {
/// \name C++ Templates
/// Implementations are in SemaTemplate.cpp
- /// @{
+ ///@{
public:
// Saves the current floating-point pragma stack and clear it in this Sema.
@@ -9706,7 +9707,7 @@ class Sema final {
void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec);
- /// @}
+ ///@}
//
//
@@ -9716,7 +9717,7 @@ class Sema final {
/// \name C++ Template Argument Deduction
/// Implementations are in SemaTemplateDeduction.cpp
- /// @{
+ ///@{
public:
/// When true, access checking violations are treated as SFINAE
@@ -9955,7 +9956,7 @@ class Sema final {
const PartialDiagnostic &CandidateDiag,
bool Complain = true, QualType TargetType = QualType());
- /// @}
+ ///@}
//
//
@@ -9965,7 +9966,7 @@ class Sema final {
/// \name C++ Template Instantiation
/// Implementations are in SemaTemplateInstantiate.cpp
- /// @{
+ ///@{
public:
/// A helper class for building up ExtParameterInfos.
@@ -10685,7 +10686,7 @@ class Sema final {
return CodeSynthesisContexts.size() > NonInstantiationEntries;
}
- /// @}
+ ///@}
//
//
@@ -10695,7 +10696,7 @@ class Sema final {
/// \name C++ Template Declaration Instantiation
/// Implementations are in SemaTemplateInstantiateDecl.cpp
- /// @{
+ ///@{
public:
/// An entity for which implicit template instantiation is required.
@@ -10962,7 +10963,7 @@ class Sema final {
}
};
- /// @}
+ ///@}
//
//
@@ -10972,7 +10973,7 @@ class Sema final {
/// \name C++ Variadic Templates
/// Implementations are in SemaTemplateVariadic.cpp
- /// @{
+ ///@{
public:
/// Determine whether an unexpanded parameter pack might be permitted in this
@@ -11365,7 +11366,7 @@ class Sema final {
ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
BinaryOperatorKind Operator);
- /// @}
+ ///@}
//
//
@@ -11375,7 +11376,7 @@ class Sema final {
/// \name Constraints and Concepts
/// Implementations are in SemaConcept.cpp
- /// @{
+ ///@{
public:
void PushSatisfactionStackEntry(const NamedDecl *D,
@@ -11612,7 +11613,7 @@ class Sema final {
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
LocalInstantiationScope &Scope);
- /// @}
+ ///@}
//
//
@@ -11622,7 +11623,7 @@ class Sema final {
/// \name Types
/// Implementations are in SemaType.cpp
- /// @{
+ ///@{
public:
/// A mapping that describes the nullability we've seen in each header file.
@@ -11982,7 +11983,7 @@ class Sema final {
IdentifierInfo *Ident_NSError = nullptr;
- /// @}
+ ///@}
//
//
@@ -11992,7 +11993,7 @@ class Sema final {
/// \name ObjC Declarations
/// Implementations are in SemaDeclObjC.cpp
- /// @{
+ ///@{
public:
enum ObjCSpecialMethodKind {
@@ -12362,7 +12363,7 @@ class Sema final {
bool receiverIdOrClass,
bool instance);
- /// @}
+ ///@}
//
//
@@ -12372,7 +12373,7 @@ class Sema final {
/// \name ObjC Expressions
/// Implementations are in SemaExprObjC.cpp
- /// @{
+ ///@{
public:
/// Caches identifiers/selectors for NSFoundation APIs.
@@ -12655,7 +12656,7 @@ class Sema final {
/*instance*/ false);
}
- /// @}
+ ///@}
//
//
@@ -12665,7 +12666,7 @@ class Sema final {
/// \name ObjC @property and @synthesize
/// Implementations are in SemaObjCProperty.cpp
- /// @{
+ ///@{
public:
/// Ensure attributes are consistent with type.
@@ -12757,7 +12758,7 @@ class Sema final {
void AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl,
ObjCInterfaceDecl *IDecl);
- /// @}
+ ///@}
//
//
@@ -12767,7 +12768,7 @@ class Sema final {
/// \name Code Completion
/// Implementations are in SemaCodeComplete.cpp
- /// @{
+ ///@{
public:
/// Code-completion consumer.
@@ -12960,7 +12961,7 @@ class Sema final {
CodeCompletionTUInfo &CCTUInfo,
SmallVectorImpl<CodeCompletionResult> &Results);
- /// @}
+ ///@}
//
//
@@ -12970,7 +12971,7 @@ class Sema final {
/// \name FixIt Helpers
/// Implementations are in SemaFixItUtils.cpp
- /// @{
+ ///@{
public:
/// Get a string to suggest for zero-initialization of a type.
@@ -12978,7 +12979,7 @@ class Sema final {
SourceLocation Loc) const;
std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
- /// @}
+ ///@}
//
//
@@ -12988,7 +12989,7 @@ class Sema final {
/// \name Name Lookup for RISC-V Vector Intrinsic
/// Implementations are in SemaRISCVVectorLookup.cpp
- /// @{
+ ///@{
public:
/// Indicate RISC-V vector builtin functions enabled or not.
@@ -13000,7 +13001,7 @@ class Sema final {
private:
std::unique_ptr<sema::RISCVIntrinsicManager> RVIntrinsicManager;
- /// @}
+ ///@}
//
//
@@ -13010,7 +13011,7 @@ class Sema final {
/// \name CUDA
/// Implementations are in SemaCUDA.cpp
- /// @{
+ ///@{
public:
/// Increments our count of the number of times we've seen a pragma forcing
@@ -13254,7 +13255,7 @@ class Sema final {
private:
unsigned ForceCUDAHostDeviceDepth = 0;
- /// @}
+ ///@}
//
//
@@ -13264,7 +13265,7 @@ class Sema final {
/// \name HLSL Constructs
/// Implementations are in SemaHLSL.cpp
- /// @{
+ ///@{
public:
Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
@@ -13272,7 +13273,7 @@ class Sema final {
SourceLocation IdentLoc, SourceLocation LBrace);
void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
- /// @}
+ ///@}
//
//
@@ -13282,7 +13283,7 @@ class Sema final {
/// \name OpenACC Constructs
/// Implementations are in SemaOpenACC.cpp
- /// @{
+ ///@{
public:
/// Called after parsing an OpenACC Clause so that it can be checked.
@@ -13322,7 +13323,7 @@ class Sema final {
/// declaration group or associated statement.
DeclGroupRef ActOnEndOpenACCDeclDirective();
- /// @}
+ ///@}
//
//
@@ -13332,7 +13333,7 @@ class Sema final {
/// \name OpenMP Directives and Clauses
/// Implementations are in SemaOpenMP.cpp
- /// @{
+ ///@{
public:
/// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
@@ -14689,7 +14690,7 @@ class Sema final {
const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion);
- /// @}
+ ///@}
//
//
@@ -14699,7 +14700,7 @@ class Sema final {
/// \name SYCL Constructs
/// Implementations are in SemaSYCL.cpp
- /// @{
+ ///@{
public:
/// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
@@ -14727,7 +14728,7 @@ class Sema final {
llvm::DenseSet<QualType> Visited,
ValueDecl *DeclToCheck);
- /// @}
+ ///@}
};
DeductionFailureInfo
>From 90df977a1d938df1f310af58bf3d9f787da6d6b9 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Thu, 22 Feb 2024 11:14:59 +0300
Subject: [PATCH 6/8] Fix access specifiers for some declarations
---
clang/include/clang/Sema/Sema.h | 41 +++++++++++++++++----------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5154381072b8cb..b77bb047594c26 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1165,6 +1165,7 @@ class Sema final {
/// CurContext - This is the current declaration context of parsing.
DeclContext *CurContext;
+protected:
friend class Parser;
friend class InitializationSequence;
friend class ASTReader;
@@ -3524,8 +3525,6 @@ class Sema final {
bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old);
bool IsRedefinitionInModule(const NamedDecl *New, const NamedDecl *Old) const;
- static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
-
bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
/// If it's a file scoped decl that must warn if not used, keep track
@@ -3674,6 +3673,8 @@ class Sema final {
/// it looks like the user is trying to modify the shadowing declaration.
llvm::DenseMap<const NamedDecl *, const NamedDecl *> ShadowingDecls;
+ static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
+
///@}
//
@@ -7796,24 +7797,6 @@ class Sema final {
bool isModuleVisible(const Module *M, bool ModulePrivate = false);
- /// 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);
-
/// Determine whether any declaration of an entity is visible.
bool
hasVisibleDeclaration(const NamedDecl *D,
@@ -7971,6 +7954,24 @@ class Sema final {
bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
+ /// 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);
+
///@}
//
>From 772ed0872c65342014080925602ce5116c8d7275 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Thu, 22 Feb 2024 11:20:20 +0300
Subject: [PATCH 7/8] Run clang-format on whole Sema.h
---
clang/include/clang/Sema/Sema.h | 383 +++++++++++++++-----------------
1 file changed, 184 insertions(+), 199 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b77bb047594c26..791efdee7a889d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -76,168 +76,168 @@
#include <vector>
namespace llvm {
- class APSInt;
- template <typename ValueT, typename ValueInfoT> class DenseSet;
- class SmallBitVector;
- struct InlineAsmIdentifierInfo;
-}
+class APSInt;
+template <typename ValueT, typename ValueInfoT> 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<CXXBaseSpecifier*, 4> 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<ImplicitConversionSequence> 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<std::pair<IdentifierInfo *, SourceLocation>> 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 T> 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<CXXBaseSpecifier *, 4> 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<ImplicitConversionSequence> 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<std::pair<IdentifierInfo *, SourceLocation>> 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 T> 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.
@@ -1077,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;
@@ -1122,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.
@@ -2798,10 +2795,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);
@@ -2870,9 +2865,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);
@@ -3053,8 +3046,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);
@@ -3083,10 +3076,10 @@ class Sema final {
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,
@@ -3098,7 +3091,7 @@ class Sema final {
void CheckVariableDeclarationType(VarDecl *NewVD);
void CheckCompleteVariableDeclaration(VarDecl *VD);
- NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ NamedDecl *ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
TypeSourceInfo *TInfo,
LookupResult &Previous,
MultiTemplateParamsArg TemplateParamLists,
@@ -3106,8 +3099,8 @@ class Sema final {
bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
// 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,
@@ -3126,8 +3119,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,
@@ -3265,8 +3257,7 @@ class Sema final {
DiagnoseSizeOfParametersAndReturnValue(ArrayRef<ParmVarDecl *> Parameters,
QualType ReturnTy, NamedDecl *D);
- Decl *ActOnFileScopeAsmDecl(Expr *expr,
- SourceLocation AsmLoc,
+ Decl *ActOnFileScopeAsmDecl(Expr *expr, SourceLocation AsmLoc,
SourceLocation RParenLoc);
Decl *ActOnTopLevelStmtDecl(Stmt *Statement);
@@ -3313,9 +3304,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 {
@@ -3355,13 +3345,11 @@ class Sema final {
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);
@@ -3423,8 +3411,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,
@@ -3453,13 +3440,13 @@ 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();
/// Add this decl to the scope shadowed decl chains.
@@ -12602,8 +12589,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);
@@ -13223,8 +13209,7 @@ 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).
>From 2c4ddd77c175f4a4c5278bb8f0625cacdb4383a5 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Tue, 5 Mar 2024 11:49:36 +0300
Subject: [PATCH 8/8] Manually re-apply some of the changes from `main` branch
---
clang/include/clang/Sema/Sema.h | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f9bd6c39fc9800..39d9132e038b1c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2150,11 +2150,7 @@ class Sema final {
VariadicDoesNotApply
};
- /// 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);
+ bool IsLayoutCompatible(QualType T1, QualType T2) const;
private:
void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
@@ -10410,7 +10406,9 @@ class Sema final {
if (FD) {
FD->setWillHaveBody(true);
S.ExprEvalContexts.back().InImmediateFunctionContext =
- FD->isImmediateFunction();
+ FD->isImmediateFunction() ||
+ S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
+ .isConstantEvaluated();
S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
} else
@@ -13297,6 +13295,11 @@ class Sema final {
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);
+
///@}
//
More information about the cfe-commits
mailing list