aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang16/include/clang/Sema
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2024-03-13 13:58:24 +0300
committerthegeorg <thegeorg@yandex-team.com>2024-03-13 14:11:53 +0300
commit11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch)
treefabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/include/clang/Sema
parent9685917341315774aad5733b1793b1e533a88bbb (diff)
downloadydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/include/clang/Sema')
-rw-r--r--contrib/libs/clang16/include/clang/Sema/AnalysisBasedWarnings.h117
-rw-r--r--contrib/libs/clang16/include/clang/Sema/CXXFieldCollector.h90
-rw-r--r--contrib/libs/clang16/include/clang/Sema/CleanupInfo.h57
-rw-r--r--contrib/libs/clang16/include/clang/Sema/CodeCompleteConsumer.h1299
-rw-r--r--contrib/libs/clang16/include/clang/Sema/CodeCompleteOptions.h66
-rw-r--r--contrib/libs/clang16/include/clang/Sema/DeclSpec.h2820
-rw-r--r--contrib/libs/clang16/include/clang/Sema/DelayedDiagnostic.h343
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Designator.h225
-rw-r--r--contrib/libs/clang16/include/clang/Sema/ExternalSemaSource.h255
-rw-r--r--contrib/libs/clang16/include/clang/Sema/HLSLExternalSemaSource.h66
-rw-r--r--contrib/libs/clang16/include/clang/Sema/IdentifierResolver.h216
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Initialization.h1433
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Lookup.h863
-rw-r--r--contrib/libs/clang16/include/clang/Sema/MultiplexExternalSemaSource.h385
-rw-r--r--contrib/libs/clang16/include/clang/Sema/ObjCMethodList.h78
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Overload.h1255
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Ownership.h315
-rw-r--r--contrib/libs/clang16/include/clang/Sema/ParsedAttr.h1220
-rw-r--r--contrib/libs/clang16/include/clang/Sema/ParsedTemplate.h273
-rw-r--r--contrib/libs/clang16/include/clang/Sema/RISCVIntrinsicManager.h46
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Scope.h581
-rw-r--r--contrib/libs/clang16/include/clang/Sema/ScopeInfo.h1078
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Sema.h14016
-rw-r--r--contrib/libs/clang16/include/clang/Sema/SemaConcept.h166
-rw-r--r--contrib/libs/clang16/include/clang/Sema/SemaConsumer.h58
-rw-r--r--contrib/libs/clang16/include/clang/Sema/SemaDiagnostic.h25
-rw-r--r--contrib/libs/clang16/include/clang/Sema/SemaFixItUtils.h101
-rw-r--r--contrib/libs/clang16/include/clang/Sema/SemaInternal.h348
-rw-r--r--contrib/libs/clang16/include/clang/Sema/SemaLambda.h51
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Template.h713
-rw-r--r--contrib/libs/clang16/include/clang/Sema/TemplateDeduction.h386
-rw-r--r--contrib/libs/clang16/include/clang/Sema/TemplateInstCallback.h93
-rw-r--r--contrib/libs/clang16/include/clang/Sema/TypoCorrection.h429
-rw-r--r--contrib/libs/clang16/include/clang/Sema/Weak.h67
34 files changed, 29534 insertions, 0 deletions
diff --git a/contrib/libs/clang16/include/clang/Sema/AnalysisBasedWarnings.h b/contrib/libs/clang16/include/clang/Sema/AnalysisBasedWarnings.h
new file mode 100644
index 0000000000..6e21df3702
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/AnalysisBasedWarnings.h
@@ -0,0 +1,117 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//=- AnalysisBasedWarnings.h - Sema warnings based on libAnalysis -*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines AnalysisBasedWarnings, a worker object used by Sema
+// that issues warnings based on dataflow-analysis.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H
+#define LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include <memory>
+
+namespace clang {
+
+class Decl;
+class FunctionDecl;
+class QualType;
+class Sema;
+namespace sema {
+ class FunctionScopeInfo;
+}
+
+namespace sema {
+
+class AnalysisBasedWarnings {
+public:
+ class Policy {
+ friend class AnalysisBasedWarnings;
+ // The warnings to run.
+ unsigned enableCheckFallThrough : 1;
+ unsigned enableCheckUnreachable : 1;
+ unsigned enableThreadSafetyAnalysis : 1;
+ unsigned enableConsumedAnalysis : 1;
+ public:
+ Policy();
+ void disableCheckFallThrough() { enableCheckFallThrough = 0; }
+ };
+
+private:
+ Sema &S;
+ Policy DefaultPolicy;
+
+ class InterProceduralData;
+ std::unique_ptr<InterProceduralData> IPData;
+
+ enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 };
+ llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD;
+
+ /// \name Statistics
+ /// @{
+
+ /// Number of function CFGs built and analyzed.
+ unsigned NumFunctionsAnalyzed;
+
+ /// Number of functions for which the CFG could not be successfully
+ /// built.
+ unsigned NumFunctionsWithBadCFGs;
+
+ /// Total number of blocks across all CFGs.
+ unsigned NumCFGBlocks;
+
+ /// Largest number of CFG blocks for a single function analyzed.
+ unsigned MaxCFGBlocksPerFunction;
+
+ /// Total number of CFGs with variables analyzed for uninitialized
+ /// uses.
+ unsigned NumUninitAnalysisFunctions;
+
+ /// Total number of variables analyzed for uninitialized uses.
+ unsigned NumUninitAnalysisVariables;
+
+ /// Max number of variables analyzed for uninitialized uses in a single
+ /// function.
+ unsigned MaxUninitAnalysisVariablesPerFunction;
+
+ /// Total number of block visits during uninitialized use analysis.
+ unsigned NumUninitAnalysisBlockVisits;
+
+ /// Max number of block visits during uninitialized use analysis of
+ /// a single function.
+ unsigned MaxUninitAnalysisBlockVisitsPerFunction;
+
+ /// @}
+
+public:
+ AnalysisBasedWarnings(Sema &s);
+ ~AnalysisBasedWarnings();
+
+ void IssueWarnings(Policy P, FunctionScopeInfo *fscope,
+ const Decl *D, QualType BlockType);
+
+ Policy getDefaultPolicy() { return DefaultPolicy; }
+
+ void PrintStats() const;
+};
+
+} // namespace sema
+} // namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/CXXFieldCollector.h b/contrib/libs/clang16/include/clang/Sema/CXXFieldCollector.h
new file mode 100644
index 0000000000..cba83ff996
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/CXXFieldCollector.h
@@ -0,0 +1,90 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- CXXFieldCollector.h - Utility class for C++ class semantic analysis ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides CXXFieldCollector that is used during parsing & semantic
+// analysis of C++ classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+#define LLVM_CLANG_SEMA_CXXFIELDCOLLECTOR_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+ class FieldDecl;
+
+/// CXXFieldCollector - Used to keep track of CXXFieldDecls during parsing of
+/// C++ classes.
+class CXXFieldCollector {
+ /// Fields - Contains all FieldDecls collected during parsing of a C++
+ /// class. When a nested class is entered, its fields are appended to the
+ /// fields of its parent class, when it is exited its fields are removed.
+ SmallVector<FieldDecl*, 32> Fields;
+
+ /// FieldCount - Each entry represents the number of fields collected during
+ /// the parsing of a C++ class. When a nested class is entered, a new field
+ /// count is pushed, when it is exited, the field count is popped.
+ SmallVector<size_t, 4> FieldCount;
+
+ // Example:
+ //
+ // class C {
+ // int x,y;
+ // class NC {
+ // int q;
+ // // At this point, Fields contains [x,y,q] decls and FieldCount contains
+ // // [2,1].
+ // };
+ // int z;
+ // // At this point, Fields contains [x,y,z] decls and FieldCount contains
+ // // [3].
+ // };
+
+public:
+ /// StartClass - Called by Sema::ActOnStartCXXClassDef.
+ void StartClass() { FieldCount.push_back(0); }
+
+ /// Add - Called by Sema::ActOnCXXMemberDeclarator.
+ void Add(FieldDecl *D) {
+ Fields.push_back(D);
+ ++FieldCount.back();
+ }
+
+ /// getCurNumField - The number of fields added to the currently parsed class.
+ size_t getCurNumFields() const {
+ assert(!FieldCount.empty() && "no currently-parsed class");
+ return FieldCount.back();
+ }
+
+ /// getCurFields - Pointer to array of fields added to the currently parsed
+ /// class.
+ FieldDecl **getCurFields() { return &*(Fields.end() - getCurNumFields()); }
+
+ /// FinishClass - Called by Sema::ActOnFinishCXXClassDef.
+ void FinishClass() {
+ Fields.resize(Fields.size() - getCurNumFields());
+ FieldCount.pop_back();
+ }
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/CleanupInfo.h b/contrib/libs/clang16/include/clang/Sema/CleanupInfo.h
new file mode 100644
index 0000000000..fc9ac9c517
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/CleanupInfo.h
@@ -0,0 +1,57 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- CleanupInfo.cpp - Cleanup Control in Sema ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a set of operations on whether generating an
+// ExprWithCleanups in a full expression.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CLEANUPINFO_H
+#define LLVM_CLANG_SEMA_CLEANUPINFO_H
+
+namespace clang {
+
+class CleanupInfo {
+ bool ExprNeedsCleanups = false;
+ bool CleanupsHaveSideEffects = false;
+
+public:
+ bool exprNeedsCleanups() const { return ExprNeedsCleanups; }
+
+ bool cleanupsHaveSideEffects() const { return CleanupsHaveSideEffects; }
+
+ void setExprNeedsCleanups(bool SideEffects) {
+ ExprNeedsCleanups = true;
+ CleanupsHaveSideEffects |= SideEffects;
+ }
+
+ void reset() {
+ ExprNeedsCleanups = false;
+ CleanupsHaveSideEffects = false;
+ }
+
+ void mergeFrom(CleanupInfo Rhs) {
+ ExprNeedsCleanups |= Rhs.ExprNeedsCleanups;
+ CleanupsHaveSideEffects |= Rhs.CleanupsHaveSideEffects;
+ }
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/CodeCompleteConsumer.h b/contrib/libs/clang16/include/clang/Sema/CodeCompleteConsumer.h
new file mode 100644
index 0000000000..737c7cb07f
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/CodeCompleteConsumer.h
@@ -0,0 +1,1299 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- CodeCompleteConsumer.h - Code Completion Interface -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CodeCompleteConsumer class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
+#define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
+
+#include "clang-c/Index.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Sema/CodeCompleteOptions.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class DeclContext;
+class FunctionDecl;
+class FunctionTemplateDecl;
+class IdentifierInfo;
+class LangOptions;
+class NamedDecl;
+class NestedNameSpecifier;
+class Preprocessor;
+class RawComment;
+class Sema;
+class UsingShadowDecl;
+
+/// Default priority values for code-completion results based
+/// on their kind.
+enum {
+ /// Priority for the next initialization in a constructor initializer
+ /// list.
+ CCP_NextInitializer = 7,
+
+ /// Priority for an enumeration constant inside a switch whose
+ /// condition is of the enumeration type.
+ CCP_EnumInCase = 7,
+
+ /// Priority for a send-to-super completion.
+ CCP_SuperCompletion = 20,
+
+ /// Priority for a declaration that is in the local scope.
+ CCP_LocalDeclaration = 34,
+
+ /// Priority for a member declaration found from the current
+ /// method or member function.
+ CCP_MemberDeclaration = 35,
+
+ /// Priority for a language keyword (that isn't any of the other
+ /// categories).
+ CCP_Keyword = 40,
+
+ /// Priority for a code pattern.
+ CCP_CodePattern = 40,
+
+ /// Priority for a non-type declaration.
+ CCP_Declaration = 50,
+
+ /// Priority for a type.
+ CCP_Type = CCP_Declaration,
+
+ /// Priority for a constant value (e.g., enumerator).
+ CCP_Constant = 65,
+
+ /// Priority for a preprocessor macro.
+ CCP_Macro = 70,
+
+ /// Priority for a nested-name-specifier.
+ CCP_NestedNameSpecifier = 75,
+
+ /// Priority for a result that isn't likely to be what the user wants,
+ /// but is included for completeness.
+ CCP_Unlikely = 80,
+
+ /// Priority for the Objective-C "_cmd" implicit parameter.
+ CCP_ObjC_cmd = CCP_Unlikely
+};
+
+/// Priority value deltas that are added to code-completion results
+/// based on the context of the result.
+enum {
+ /// The result is in a base class.
+ CCD_InBaseClass = 2,
+
+ /// The result is a C++ non-static member function whose qualifiers
+ /// exactly match the object type on which the member function can be called.
+ CCD_ObjectQualifierMatch = -1,
+
+ /// The selector of the given message exactly matches the selector
+ /// of the current method, which might imply that some kind of delegation
+ /// is occurring.
+ CCD_SelectorMatch = -3,
+
+ /// Adjustment to the "bool" type in Objective-C, where the typedef
+ /// "BOOL" is preferred.
+ CCD_bool_in_ObjC = 1,
+
+ /// Adjustment for KVC code pattern priorities when it doesn't look
+ /// like the
+ CCD_ProbablyNotObjCCollection = 15,
+
+ /// An Objective-C method being used as a property.
+ CCD_MethodAsProperty = 2,
+
+ /// An Objective-C block property completed as a setter with a
+ /// block placeholder.
+ CCD_BlockPropertySetter = 3
+};
+
+/// Priority value factors by which we will divide or multiply the
+/// priority of a code-completion result.
+enum {
+ /// Divide by this factor when a code-completion result's type exactly
+ /// matches the type we expect.
+ CCF_ExactTypeMatch = 4,
+
+ /// Divide by this factor when a code-completion result's type is
+ /// similar to the type we expect (e.g., both arithmetic types, both
+ /// Objective-C object pointer types).
+ CCF_SimilarTypeMatch = 2
+};
+
+/// A simplified classification of types used when determining
+/// "similar" types for code completion.
+enum SimplifiedTypeClass {
+ STC_Arithmetic,
+ STC_Array,
+ STC_Block,
+ STC_Function,
+ STC_ObjectiveC,
+ STC_Other,
+ STC_Pointer,
+ STC_Record,
+ STC_Void
+};
+
+/// Determine the simplified type class of the given canonical type.
+SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T);
+
+/// Determine the type that this declaration will have if it is used
+/// as a type or in an expression.
+QualType getDeclUsageType(ASTContext &C, const NamedDecl *ND);
+
+/// Determine the priority to be given to a macro code completion result
+/// with the given name.
+///
+/// \param MacroName The name of the macro.
+///
+/// \param LangOpts Options describing the current language dialect.
+///
+/// \param PreferredTypeIsPointer Whether the preferred type for the context
+/// of this macro is a pointer type.
+unsigned getMacroUsagePriority(StringRef MacroName,
+ const LangOptions &LangOpts,
+ bool PreferredTypeIsPointer = false);
+
+/// Determine the libclang cursor kind associated with the given
+/// declaration.
+CXCursorKind getCursorKindForDecl(const Decl *D);
+
+/// The context in which code completion occurred, so that the
+/// code-completion consumer can process the results accordingly.
+class CodeCompletionContext {
+public:
+ enum Kind {
+ /// An unspecified code-completion context.
+ CCC_Other,
+
+ /// An unspecified code-completion context where we should also add
+ /// macro completions.
+ CCC_OtherWithMacros,
+
+ /// Code completion occurred within a "top-level" completion context,
+ /// e.g., at namespace or global scope.
+ CCC_TopLevel,
+
+ /// Code completion occurred within an Objective-C interface,
+ /// protocol, or category interface.
+ CCC_ObjCInterface,
+
+ /// Code completion occurred within an Objective-C implementation
+ /// or category implementation.
+ CCC_ObjCImplementation,
+
+ /// Code completion occurred within the instance variable list of
+ /// an Objective-C interface, implementation, or category implementation.
+ CCC_ObjCIvarList,
+
+ /// Code completion occurred within a class, struct, or union.
+ CCC_ClassStructUnion,
+
+ /// Code completion occurred where a statement (or declaration) is
+ /// expected in a function, method, or block.
+ CCC_Statement,
+
+ /// Code completion occurred where an expression is expected.
+ CCC_Expression,
+
+ /// Code completion occurred where an Objective-C message receiver
+ /// is expected.
+ CCC_ObjCMessageReceiver,
+
+ /// Code completion occurred on the right-hand side of a member
+ /// access expression using the dot operator.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_DotMemberAccess,
+
+ /// Code completion occurred on the right-hand side of a member
+ /// access expression using the arrow operator.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_ArrowMemberAccess,
+
+ /// Code completion occurred on the right-hand side of an Objective-C
+ /// property access expression.
+ ///
+ /// The results of this completion are the members of the type being
+ /// accessed. The type itself is available via
+ /// \c CodeCompletionContext::getType().
+ CCC_ObjCPropertyAccess,
+
+ /// Code completion occurred after the "enum" keyword, to indicate
+ /// an enumeration name.
+ CCC_EnumTag,
+
+ /// Code completion occurred after the "union" keyword, to indicate
+ /// a union name.
+ CCC_UnionTag,
+
+ /// Code completion occurred after the "struct" or "class" keyword,
+ /// to indicate a struct or class name.
+ CCC_ClassOrStructTag,
+
+ /// Code completion occurred where a protocol name is expected.
+ CCC_ObjCProtocolName,
+
+ /// Code completion occurred where a namespace or namespace alias
+ /// is expected.
+ CCC_Namespace,
+
+ /// Code completion occurred where a type name is expected.
+ CCC_Type,
+
+ /// Code completion occurred where a new name is expected.
+ CCC_NewName,
+
+ /// Code completion occurred where both a new name and an existing symbol is
+ /// permissible.
+ CCC_SymbolOrNewName,
+
+ /// Code completion occurred where an existing name(such as type, function
+ /// or variable) is expected.
+ CCC_Symbol,
+
+ /// Code completion occurred where an macro is being defined.
+ CCC_MacroName,
+
+ /// Code completion occurred where a macro name is expected
+ /// (without any arguments, in the case of a function-like macro).
+ CCC_MacroNameUse,
+
+ /// Code completion occurred within a preprocessor expression.
+ CCC_PreprocessorExpression,
+
+ /// Code completion occurred where a preprocessor directive is
+ /// expected.
+ CCC_PreprocessorDirective,
+
+ /// Code completion occurred in a context where natural language is
+ /// expected, e.g., a comment or string literal.
+ ///
+ /// This context usually implies that no completions should be added,
+ /// unless they come from an appropriate natural-language dictionary.
+ CCC_NaturalLanguage,
+
+ /// Code completion for a selector, as in an \@selector expression.
+ CCC_SelectorName,
+
+ /// Code completion within a type-qualifier list.
+ CCC_TypeQualifiers,
+
+ /// Code completion in a parenthesized expression, which means that
+ /// we may also have types here in C and Objective-C (as well as in C++).
+ CCC_ParenthesizedExpression,
+
+ /// Code completion where an Objective-C instance message is
+ /// expected.
+ CCC_ObjCInstanceMessage,
+
+ /// Code completion where an Objective-C class message is expected.
+ CCC_ObjCClassMessage,
+
+ /// Code completion where the name of an Objective-C class is
+ /// expected.
+ CCC_ObjCInterfaceName,
+
+ /// Code completion where an Objective-C category name is expected.
+ CCC_ObjCCategoryName,
+
+ /// Code completion inside the filename part of a #include directive.
+ CCC_IncludedFile,
+
+ /// Code completion of an attribute name.
+ CCC_Attribute,
+
+ /// An unknown context, in which we are recovering from a parsing
+ /// error and don't know which completions we should give.
+ CCC_Recovery
+ };
+
+ using VisitedContextSet = llvm::SmallPtrSet<DeclContext *, 8>;
+
+private:
+ Kind CCKind;
+
+ /// Indicates whether we are completing a name of a using declaration, e.g.
+ /// using ^;
+ /// using a::^;
+ bool IsUsingDeclaration;
+
+ /// The type that would prefer to see at this point (e.g., the type
+ /// of an initializer or function parameter).
+ QualType PreferredType;
+
+ /// The type of the base object in a member access expression.
+ QualType BaseType;
+
+ /// The identifiers for Objective-C selector parts.
+ ArrayRef<IdentifierInfo *> SelIdents;
+
+ /// The scope specifier that comes before the completion token e.g.
+ /// "a::b::"
+ std::optional<CXXScopeSpec> ScopeSpecifier;
+
+ /// A set of declaration contexts visited by Sema when doing lookup for
+ /// code completion.
+ VisitedContextSet VisitedContexts;
+
+public:
+ /// Construct a new code-completion context of the given kind.
+ CodeCompletionContext(Kind CCKind)
+ : CCKind(CCKind), IsUsingDeclaration(false), SelIdents(std::nullopt) {}
+
+ /// Construct a new code-completion context of the given kind.
+ CodeCompletionContext(Kind CCKind, QualType T,
+ ArrayRef<IdentifierInfo *> SelIdents = std::nullopt)
+ : CCKind(CCKind), IsUsingDeclaration(false), SelIdents(SelIdents) {
+ if (CCKind == CCC_DotMemberAccess || CCKind == CCC_ArrowMemberAccess ||
+ CCKind == CCC_ObjCPropertyAccess || CCKind == CCC_ObjCClassMessage ||
+ CCKind == CCC_ObjCInstanceMessage)
+ BaseType = T;
+ else
+ PreferredType = T;
+ }
+
+ bool isUsingDeclaration() const { return IsUsingDeclaration; }
+ void setIsUsingDeclaration(bool V) { IsUsingDeclaration = V; }
+
+ /// Retrieve the kind of code-completion context.
+ Kind getKind() const { return CCKind; }
+
+ /// Retrieve the type that this expression would prefer to have, e.g.,
+ /// if the expression is a variable initializer or a function argument, the
+ /// type of the corresponding variable or function parameter.
+ QualType getPreferredType() const { return PreferredType; }
+ void setPreferredType(QualType T) { PreferredType = T; }
+
+ /// Retrieve the type of the base object in a member-access
+ /// expression.
+ QualType getBaseType() const { return BaseType; }
+
+ /// Retrieve the Objective-C selector identifiers.
+ ArrayRef<IdentifierInfo *> getSelIdents() const { return SelIdents; }
+
+ /// Determines whether we want C++ constructors as results within this
+ /// context.
+ bool wantConstructorResults() const;
+
+ /// Sets the scope specifier that comes before the completion token.
+ /// This is expected to be set in code completions on qualfied specifiers
+ /// (e.g. "a::b::").
+ void setCXXScopeSpecifier(CXXScopeSpec SS) {
+ this->ScopeSpecifier = std::move(SS);
+ }
+
+ /// Adds a visited context.
+ void addVisitedContext(DeclContext *Ctx) {
+ VisitedContexts.insert(Ctx);
+ }
+
+ /// Retrieves all visited contexts.
+ const VisitedContextSet &getVisitedContexts() const {
+ return VisitedContexts;
+ }
+
+ std::optional<const CXXScopeSpec *> getCXXScopeSpecifier() {
+ if (ScopeSpecifier)
+ return &*ScopeSpecifier;
+ return std::nullopt;
+ }
+};
+
+/// Get string representation of \p Kind, useful for debugging.
+llvm::StringRef getCompletionKindString(CodeCompletionContext::Kind Kind);
+
+/// A "string" used to describe how code completion can
+/// be performed for an entity.
+///
+/// A code completion string typically shows how a particular entity can be
+/// used. For example, the code completion string for a function would show
+/// the syntax to call it, including the parentheses, placeholders for the
+/// arguments, etc.
+class CodeCompletionString {
+public:
+ /// The different kinds of "chunks" that can occur within a code
+ /// completion string.
+ enum ChunkKind {
+ /// The piece of text that the user is expected to type to
+ /// match the code-completion string, typically a keyword or the name of a
+ /// declarator or macro.
+ CK_TypedText,
+
+ /// A piece of text that should be placed in the buffer, e.g.,
+ /// parentheses or a comma in a function call.
+ CK_Text,
+
+ /// A code completion string that is entirely optional. For example,
+ /// an optional code completion string that describes the default arguments
+ /// in a function call.
+ CK_Optional,
+
+ /// A string that acts as a placeholder for, e.g., a function
+ /// call argument.
+ CK_Placeholder,
+
+ /// A piece of text that describes something about the result but
+ /// should not be inserted into the buffer.
+ CK_Informative,
+ /// A piece of text that describes the type of an entity or, for
+ /// functions and methods, the return type.
+ CK_ResultType,
+
+ /// A piece of text that describes the parameter that corresponds
+ /// to the code-completion location within a function call, message send,
+ /// macro invocation, etc.
+ CK_CurrentParameter,
+
+ /// A left parenthesis ('(').
+ CK_LeftParen,
+
+ /// A right parenthesis (')').
+ CK_RightParen,
+
+ /// A left bracket ('[').
+ CK_LeftBracket,
+
+ /// A right bracket (']').
+ CK_RightBracket,
+
+ /// A left brace ('{').
+ CK_LeftBrace,
+
+ /// A right brace ('}').
+ CK_RightBrace,
+
+ /// A left angle bracket ('<').
+ CK_LeftAngle,
+
+ /// A right angle bracket ('>').
+ CK_RightAngle,
+
+ /// A comma separator (',').
+ CK_Comma,
+
+ /// A colon (':').
+ CK_Colon,
+
+ /// A semicolon (';').
+ CK_SemiColon,
+
+ /// An '=' sign.
+ CK_Equal,
+
+ /// Horizontal whitespace (' ').
+ CK_HorizontalSpace,
+
+ /// Vertical whitespace ('\\n' or '\\r\\n', depending on the
+ /// platform).
+ CK_VerticalSpace
+ };
+
+ /// One piece of the code completion string.
+ struct Chunk {
+ /// The kind of data stored in this piece of the code completion
+ /// string.
+ ChunkKind Kind = CK_Text;
+
+ union {
+ /// The text string associated with a CK_Text, CK_Placeholder,
+ /// CK_Informative, or CK_Comma chunk.
+ /// The string is owned by the chunk and will be deallocated
+ /// (with delete[]) when the chunk is destroyed.
+ const char *Text;
+
+ /// The code completion string associated with a CK_Optional chunk.
+ /// The optional code completion string is owned by the chunk, and will
+ /// be deallocated (with delete) when the chunk is destroyed.
+ CodeCompletionString *Optional;
+ };
+
+ Chunk() : Text(nullptr) {}
+
+ explicit Chunk(ChunkKind Kind, const char *Text = "");
+
+ /// Create a new text chunk.
+ static Chunk CreateText(const char *Text);
+
+ /// Create a new optional chunk.
+ static Chunk CreateOptional(CodeCompletionString *Optional);
+
+ /// Create a new placeholder chunk.
+ static Chunk CreatePlaceholder(const char *Placeholder);
+
+ /// Create a new informative chunk.
+ static Chunk CreateInformative(const char *Informative);
+
+ /// Create a new result type chunk.
+ static Chunk CreateResultType(const char *ResultType);
+
+ /// Create a new current-parameter chunk.
+ static Chunk CreateCurrentParameter(const char *CurrentParameter);
+ };
+
+private:
+ friend class CodeCompletionBuilder;
+ friend class CodeCompletionResult;
+
+ /// The number of chunks stored in this string.
+ unsigned NumChunks : 16;
+
+ /// The number of annotations for this code-completion result.
+ unsigned NumAnnotations : 16;
+
+ /// The priority of this code-completion string.
+ unsigned Priority : 16;
+
+ /// The availability of this code-completion result.
+ unsigned Availability : 2;
+
+ /// The name of the parent context.
+ StringRef ParentName;
+
+ /// A brief documentation comment attached to the declaration of
+ /// entity being completed by this result.
+ const char *BriefComment;
+
+ CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
+ unsigned Priority, CXAvailabilityKind Availability,
+ const char **Annotations, unsigned NumAnnotations,
+ StringRef ParentName,
+ const char *BriefComment);
+ ~CodeCompletionString() = default;
+
+public:
+ CodeCompletionString(const CodeCompletionString &) = delete;
+ CodeCompletionString &operator=(const CodeCompletionString &) = delete;
+
+ using iterator = const Chunk *;
+
+ iterator begin() const { return reinterpret_cast<const Chunk *>(this + 1); }
+ iterator end() const { return begin() + NumChunks; }
+ bool empty() const { return NumChunks == 0; }
+ unsigned size() const { return NumChunks; }
+
+ const Chunk &operator[](unsigned I) const {
+ assert(I < size() && "Chunk index out-of-range");
+ return begin()[I];
+ }
+
+ /// Returns the text in the first TypedText chunk.
+ const char *getTypedText() const;
+
+ /// Returns the combined text from all TypedText chunks.
+ std::string getAllTypedText() const;
+
+ /// Retrieve the priority of this code completion result.
+ unsigned getPriority() const { return Priority; }
+
+ /// Retrieve the availability of this code completion result.
+ unsigned getAvailability() const { return Availability; }
+
+ /// Retrieve the number of annotations for this code completion result.
+ unsigned getAnnotationCount() const;
+
+ /// Retrieve the annotation string specified by \c AnnotationNr.
+ const char *getAnnotation(unsigned AnnotationNr) const;
+
+ /// Retrieve the name of the parent context.
+ StringRef getParentContextName() const {
+ return ParentName;
+ }
+
+ const char *getBriefComment() const {
+ return BriefComment;
+ }
+
+ /// Retrieve a string representation of the code completion string,
+ /// which is mainly useful for debugging.
+ std::string getAsString() const;
+};
+
+/// An allocator used specifically for the purpose of code completion.
+class CodeCompletionAllocator : public llvm::BumpPtrAllocator {
+public:
+ /// Copy the given string into this allocator.
+ const char *CopyString(const Twine &String);
+};
+
+/// Allocator for a cached set of global code completions.
+class GlobalCodeCompletionAllocator : public CodeCompletionAllocator {};
+
+class CodeCompletionTUInfo {
+ llvm::DenseMap<const DeclContext *, StringRef> ParentNames;
+ std::shared_ptr<GlobalCodeCompletionAllocator> AllocatorRef;
+
+public:
+ explicit CodeCompletionTUInfo(
+ std::shared_ptr<GlobalCodeCompletionAllocator> Allocator)
+ : AllocatorRef(std::move(Allocator)) {}
+
+ std::shared_ptr<GlobalCodeCompletionAllocator> getAllocatorRef() const {
+ return AllocatorRef;
+ }
+
+ CodeCompletionAllocator &getAllocator() const {
+ assert(AllocatorRef);
+ return *AllocatorRef;
+ }
+
+ StringRef getParentName(const DeclContext *DC);
+};
+
+} // namespace clang
+
+namespace clang {
+
+/// A builder class used to construct new code-completion strings.
+class CodeCompletionBuilder {
+public:
+ using Chunk = CodeCompletionString::Chunk;
+
+private:
+ CodeCompletionAllocator &Allocator;
+ CodeCompletionTUInfo &CCTUInfo;
+ unsigned Priority = 0;
+ CXAvailabilityKind Availability = CXAvailability_Available;
+ StringRef ParentName;
+ const char *BriefComment = nullptr;
+
+ /// The chunks stored in this string.
+ SmallVector<Chunk, 4> Chunks;
+
+ SmallVector<const char *, 2> Annotations;
+
+public:
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo)
+ : Allocator(Allocator), CCTUInfo(CCTUInfo) {}
+
+ CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ unsigned Priority, CXAvailabilityKind Availability)
+ : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(Priority),
+ Availability(Availability) {}
+
+ /// Retrieve the allocator into which the code completion
+ /// strings should be allocated.
+ CodeCompletionAllocator &getAllocator() const { return Allocator; }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
+
+ /// Take the resulting completion string.
+ ///
+ /// This operation can only be performed once.
+ CodeCompletionString *TakeString();
+
+ /// Add a new typed-text chunk.
+ void AddTypedTextChunk(const char *Text);
+
+ /// Add a new text chunk.
+ void AddTextChunk(const char *Text);
+
+ /// Add a new optional chunk.
+ void AddOptionalChunk(CodeCompletionString *Optional);
+
+ /// Add a new placeholder chunk.
+ void AddPlaceholderChunk(const char *Placeholder);
+
+ /// Add a new informative chunk.
+ void AddInformativeChunk(const char *Text);
+
+ /// Add a new result-type chunk.
+ void AddResultTypeChunk(const char *ResultType);
+
+ /// Add a new current-parameter chunk.
+ void AddCurrentParameterChunk(const char *CurrentParameter);
+
+ /// Add a new chunk.
+ void AddChunk(CodeCompletionString::ChunkKind CK, const char *Text = "");
+
+ void AddAnnotation(const char *A) { Annotations.push_back(A); }
+
+ /// Add the parent context information to this code completion.
+ void addParentContext(const DeclContext *DC);
+
+ const char *getBriefComment() const { return BriefComment; }
+ void addBriefComment(StringRef Comment);
+
+ StringRef getParentName() const { return ParentName; }
+};
+
+/// Captures a result of code completion.
+class CodeCompletionResult {
+public:
+ /// Describes the kind of result generated.
+ enum ResultKind {
+ /// Refers to a declaration.
+ RK_Declaration = 0,
+
+ /// Refers to a keyword or symbol.
+ RK_Keyword,
+
+ /// Refers to a macro.
+ RK_Macro,
+
+ /// Refers to a precomputed pattern.
+ RK_Pattern
+ };
+
+ /// When Kind == RK_Declaration or RK_Pattern, the declaration we are
+ /// referring to. In the latter case, the declaration might be NULL.
+ const NamedDecl *Declaration = nullptr;
+
+ union {
+ /// When Kind == RK_Keyword, the string representing the keyword
+ /// or symbol's spelling.
+ const char *Keyword;
+
+ /// When Kind == RK_Pattern, the code-completion string that
+ /// describes the completion text to insert.
+ CodeCompletionString *Pattern;
+
+ /// When Kind == RK_Macro, the identifier that refers to a macro.
+ const IdentifierInfo *Macro;
+ };
+
+ /// The priority of this particular code-completion result.
+ unsigned Priority;
+
+ /// Specifies which parameter (of a function, Objective-C method,
+ /// macro, etc.) we should start with when formatting the result.
+ unsigned StartParameter = 0;
+
+ /// The kind of result stored here.
+ ResultKind Kind;
+
+ /// The cursor kind that describes this result.
+ CXCursorKind CursorKind;
+
+ /// The availability of this result.
+ CXAvailabilityKind Availability = CXAvailability_Available;
+
+ /// Fix-its that *must* be applied before inserting the text for the
+ /// corresponding completion.
+ ///
+ /// By default, CodeCompletionBuilder only returns completions with empty
+ /// fix-its. Extra completions with non-empty fix-its should be explicitly
+ /// requested by setting CompletionOptions::IncludeFixIts.
+ ///
+ /// For the clients to be able to compute position of the cursor after
+ /// applying fix-its, the following conditions are guaranteed to hold for
+ /// RemoveRange of the stored fix-its:
+ /// - Ranges in the fix-its are guaranteed to never contain the completion
+ /// point (or identifier under completion point, if any) inside them, except
+ /// at the start or at the end of the range.
+ /// - If a fix-it range starts or ends with completion point (or starts or
+ /// ends after the identifier under completion point), it will contain at
+ /// least one character. It allows to unambiguously recompute completion
+ /// point after applying the fix-it.
+ ///
+ /// The intuition is that provided fix-its change code around the identifier
+ /// we complete, but are not allowed to touch the identifier itself or the
+ /// completion point. One example of completions with corrections are the ones
+ /// replacing '.' with '->' and vice versa:
+ ///
+ /// std::unique_ptr<std::vector<int>> vec_ptr;
+ /// In 'vec_ptr.^', one of the completions is 'push_back', it requires
+ /// replacing '.' with '->'.
+ /// In 'vec_ptr->^', one of the completions is 'release', it requires
+ /// replacing '->' with '.'.
+ std::vector<FixItHint> FixIts;
+
+ /// Whether this result is hidden by another name.
+ bool Hidden : 1;
+
+ /// Whether this is a class member from base class.
+ bool InBaseClass : 1;
+
+ /// Whether this result was found via lookup into a base class.
+ bool QualifierIsInformative : 1;
+
+ /// Whether this declaration is the beginning of a
+ /// nested-name-specifier and, therefore, should be followed by '::'.
+ bool StartsNestedNameSpecifier : 1;
+
+ /// Whether all parameters (of a function, Objective-C
+ /// method, etc.) should be considered "informative".
+ bool AllParametersAreInformative : 1;
+
+ /// Whether we're completing a declaration of the given entity,
+ /// rather than a use of that entity.
+ bool DeclaringEntity : 1;
+
+ /// When completing a function, whether it can be a call. This will usually be
+ /// true, but we have some heuristics, e.g. when a pointer to a non-static
+ /// member function is completed outside of that class' scope, it can never
+ /// be a call.
+ bool FunctionCanBeCall : 1;
+
+ /// If the result should have a nested-name-specifier, this is it.
+ /// When \c QualifierIsInformative, the nested-name-specifier is
+ /// informative rather than required.
+ NestedNameSpecifier *Qualifier = nullptr;
+
+ /// If this Decl was unshadowed by using declaration, this can store a
+ /// pointer to the UsingShadowDecl which was used in the unshadowing process.
+ /// This information can be used to uprank CodeCompletionResults / which have
+ /// corresponding `using decl::qualified::name;` nearby.
+ const UsingShadowDecl *ShadowDecl = nullptr;
+
+ /// If the result is RK_Macro, this can store the information about the macro
+ /// definition. This should be set in most cases but can be missing when
+ /// the macro has been undefined.
+ const MacroInfo *MacroDefInfo = nullptr;
+
+ /// Build a result that refers to a declaration.
+ CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority,
+ NestedNameSpecifier *Qualifier = nullptr,
+ bool QualifierIsInformative = false,
+ bool Accessible = true,
+ std::vector<FixItHint> FixIts = std::vector<FixItHint>())
+ : Declaration(Declaration), Priority(Priority), Kind(RK_Declaration),
+ FixIts(std::move(FixIts)), Hidden(false), InBaseClass(false),
+ QualifierIsInformative(QualifierIsInformative),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), FunctionCanBeCall(true), Qualifier(Qualifier) {
+ // FIXME: Add assert to check FixIts range requirements.
+ computeCursorKindAndAvailability(Accessible);
+ }
+
+ /// Build a result that refers to a keyword or symbol.
+ CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
+ : Keyword(Keyword), Priority(Priority), Kind(RK_Keyword),
+ CursorKind(CXCursor_NotImplemented), Hidden(false), InBaseClass(false),
+ QualifierIsInformative(false), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ FunctionCanBeCall(true) {}
+
+ /// Build a result that refers to a macro.
+ CodeCompletionResult(const IdentifierInfo *Macro,
+ const MacroInfo *MI = nullptr,
+ unsigned Priority = CCP_Macro)
+ : Macro(Macro), Priority(Priority), Kind(RK_Macro),
+ CursorKind(CXCursor_MacroDefinition), Hidden(false), InBaseClass(false),
+ QualifierIsInformative(false), StartsNestedNameSpecifier(false),
+ AllParametersAreInformative(false), DeclaringEntity(false),
+ FunctionCanBeCall(true), MacroDefInfo(MI) {}
+
+ /// Build a result that refers to a pattern.
+ CodeCompletionResult(
+ CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern,
+ CXCursorKind CursorKind = CXCursor_NotImplemented,
+ CXAvailabilityKind Availability = CXAvailability_Available,
+ const NamedDecl *D = nullptr)
+ : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
+ CursorKind(CursorKind), Availability(Availability), Hidden(false),
+ InBaseClass(false), QualifierIsInformative(false),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), FunctionCanBeCall(true) {}
+
+ /// Build a result that refers to a pattern with an associated
+ /// declaration.
+ CodeCompletionResult(CodeCompletionString *Pattern, const NamedDecl *D,
+ unsigned Priority)
+ : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
+ Hidden(false), InBaseClass(false), QualifierIsInformative(false),
+ StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
+ DeclaringEntity(false), FunctionCanBeCall(true) {
+ computeCursorKindAndAvailability();
+ }
+
+ /// Retrieve the declaration stored in this result. This might be nullptr if
+ /// Kind is RK_Pattern.
+ const NamedDecl *getDeclaration() const {
+ assert(((Kind == RK_Declaration) || (Kind == RK_Pattern)) &&
+ "Not a declaration or pattern result");
+ return Declaration;
+ }
+
+ /// Retrieve the keyword stored in this result.
+ const char *getKeyword() const {
+ assert(Kind == RK_Keyword && "Not a keyword result");
+ return Keyword;
+ }
+
+ /// Create a new code-completion string that describes how to insert
+ /// this result into a program.
+ ///
+ /// \param S The semantic analysis that created the result.
+ ///
+ /// \param Allocator The allocator that will be used to allocate the
+ /// string itself.
+ CodeCompletionString *CreateCodeCompletionString(Sema &S,
+ const CodeCompletionContext &CCContext,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments);
+ CodeCompletionString *CreateCodeCompletionString(ASTContext &Ctx,
+ Preprocessor &PP,
+ const CodeCompletionContext &CCContext,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments);
+ /// Creates a new code-completion string for the macro result. Similar to the
+ /// above overloads, except this only requires preprocessor information.
+ /// The result kind must be `RK_Macro`.
+ CodeCompletionString *
+ CreateCodeCompletionStringForMacro(Preprocessor &PP,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo);
+
+ CodeCompletionString *createCodeCompletionStringForDecl(
+ Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
+ bool IncludeBriefComments, const CodeCompletionContext &CCContext,
+ PrintingPolicy &Policy);
+
+ CodeCompletionString *createCodeCompletionStringForOverride(
+ Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
+ bool IncludeBriefComments, const CodeCompletionContext &CCContext,
+ PrintingPolicy &Policy);
+
+ /// Retrieve the name that should be used to order a result.
+ ///
+ /// If the name needs to be constructed as a string, that string will be
+ /// saved into Saved and the returned StringRef will refer to it.
+ StringRef getOrderedName(std::string &Saved) const;
+
+private:
+ void computeCursorKindAndAvailability(bool Accessible = true);
+};
+
+bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y);
+
+inline bool operator>(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return Y < X;
+}
+
+inline bool operator<=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(Y < X);
+}
+
+inline bool operator>=(const CodeCompletionResult &X,
+ const CodeCompletionResult &Y) {
+ return !(X < Y);
+}
+
+/// Abstract interface for a consumer of code-completion
+/// information.
+class CodeCompleteConsumer {
+protected:
+ const CodeCompleteOptions CodeCompleteOpts;
+
+public:
+ class OverloadCandidate {
+ public:
+ /// Describes the type of overload candidate.
+ enum CandidateKind {
+ /// The candidate is a function declaration.
+ CK_Function,
+
+ /// The candidate is a function template, arguments are being completed.
+ CK_FunctionTemplate,
+
+ /// The "candidate" is actually a variable, expression, or block
+ /// for which we only have a function prototype.
+ CK_FunctionType,
+
+ /// The candidate is a variable or expression of function type
+ /// for which we have the location of the prototype declaration.
+ CK_FunctionProtoTypeLoc,
+
+ /// The candidate is a template, template arguments are being completed.
+ CK_Template,
+
+ /// The candidate is aggregate initialization of a record type.
+ CK_Aggregate,
+ };
+
+ private:
+ /// The kind of overload candidate.
+ CandidateKind Kind;
+
+ union {
+ /// The function overload candidate, available when
+ /// Kind == CK_Function.
+ FunctionDecl *Function;
+
+ /// The function template overload candidate, available when
+ /// Kind == CK_FunctionTemplate.
+ FunctionTemplateDecl *FunctionTemplate;
+
+ /// The function type that describes the entity being called,
+ /// when Kind == CK_FunctionType.
+ const FunctionType *Type;
+
+ /// The location of the function prototype that describes the entity being
+ /// called, when Kind == CK_FunctionProtoTypeLoc.
+ FunctionProtoTypeLoc ProtoTypeLoc;
+
+ /// The template overload candidate, available when
+ /// Kind == CK_Template.
+ const TemplateDecl *Template;
+
+ /// The class being aggregate-initialized,
+ /// when Kind == CK_Aggregate
+ const RecordDecl *AggregateType;
+ };
+
+ public:
+ OverloadCandidate(FunctionDecl *Function)
+ : Kind(CK_Function), Function(Function) {
+ assert(Function != nullptr);
+ }
+
+ OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl)
+ : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) {
+ assert(FunctionTemplateDecl != nullptr);
+ }
+
+ OverloadCandidate(const FunctionType *Type)
+ : Kind(CK_FunctionType), Type(Type) {
+ assert(Type != nullptr);
+ }
+
+ OverloadCandidate(FunctionProtoTypeLoc Prototype)
+ : Kind(CK_FunctionProtoTypeLoc), ProtoTypeLoc(Prototype) {
+ assert(!Prototype.isNull());
+ }
+
+ OverloadCandidate(const RecordDecl *Aggregate)
+ : Kind(CK_Aggregate), AggregateType(Aggregate) {
+ assert(Aggregate != nullptr);
+ }
+
+ OverloadCandidate(const TemplateDecl *Template)
+ : Kind(CK_Template), Template(Template) {}
+
+ /// Determine the kind of overload candidate.
+ CandidateKind getKind() const { return Kind; }
+
+ /// Retrieve the function overload candidate or the templated
+ /// function declaration for a function template.
+ FunctionDecl *getFunction() const;
+
+ /// Retrieve the function template overload candidate.
+ FunctionTemplateDecl *getFunctionTemplate() const {
+ assert(getKind() == CK_FunctionTemplate && "Not a function template");
+ return FunctionTemplate;
+ }
+
+ /// Retrieve the function type of the entity, regardless of how the
+ /// function is stored.
+ const FunctionType *getFunctionType() const;
+
+ /// Retrieve the function ProtoTypeLoc candidate.
+ /// This can be called for any Kind, but returns null for kinds
+ /// other than CK_FunctionProtoTypeLoc.
+ const FunctionProtoTypeLoc getFunctionProtoTypeLoc() const;
+
+ const TemplateDecl *getTemplate() const {
+ assert(getKind() == CK_Template && "Not a template");
+ return Template;
+ }
+
+ /// Retrieve the aggregate type being initialized.
+ const RecordDecl *getAggregate() const {
+ assert(getKind() == CK_Aggregate);
+ return AggregateType;
+ }
+
+ /// Get the number of parameters in this signature.
+ unsigned getNumParams() const;
+
+ /// Get the type of the Nth parameter.
+ /// Returns null if the type is unknown or N is out of range.
+ QualType getParamType(unsigned N) const;
+
+ /// Get the declaration of the Nth parameter.
+ /// Returns null if the decl is unknown or N is out of range.
+ const NamedDecl *getParamDecl(unsigned N) const;
+
+ /// Create a new code-completion string that describes the function
+ /// signature of this overload candidate.
+ CodeCompletionString *
+ CreateSignatureString(unsigned CurrentArg, Sema &S,
+ CodeCompletionAllocator &Allocator,
+ CodeCompletionTUInfo &CCTUInfo,
+ bool IncludeBriefComments, bool Braced) const;
+ };
+
+ CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts)
+ : CodeCompleteOpts(CodeCompleteOpts) {}
+
+ /// Whether the code-completion consumer wants to see macros.
+ bool includeMacros() const {
+ return CodeCompleteOpts.IncludeMacros;
+ }
+
+ /// Whether the code-completion consumer wants to see code patterns.
+ bool includeCodePatterns() const {
+ return CodeCompleteOpts.IncludeCodePatterns;
+ }
+
+ /// Whether to include global (top-level) declaration results.
+ bool includeGlobals() const { return CodeCompleteOpts.IncludeGlobals; }
+
+ /// Whether to include declarations in namespace contexts (including
+ /// the global namespace). If this is false, `includeGlobals()` will be
+ /// ignored.
+ bool includeNamespaceLevelDecls() const {
+ return CodeCompleteOpts.IncludeNamespaceLevelDecls;
+ }
+
+ /// Whether to include brief documentation comments within the set of
+ /// code completions returned.
+ bool includeBriefComments() const {
+ return CodeCompleteOpts.IncludeBriefComments;
+ }
+
+ /// Whether to include completion items with small fix-its, e.g. change
+ /// '.' to '->' on member access, etc.
+ bool includeFixIts() const { return CodeCompleteOpts.IncludeFixIts; }
+
+ /// Hint whether to load data from the external AST in order to provide
+ /// full results. If false, declarations from the preamble may be omitted.
+ bool loadExternal() const {
+ return CodeCompleteOpts.LoadExternal;
+ }
+
+ /// Deregisters and destroys this code-completion consumer.
+ virtual ~CodeCompleteConsumer();
+
+ /// \name Code-completion filtering
+ /// Check if the result should be filtered out.
+ virtual bool isResultFilteredOut(StringRef Filter,
+ CodeCompletionResult Results) {
+ return false;
+ }
+
+ /// \name Code-completion callbacks
+ //@{
+ /// Process the finalized code-completion results.
+ virtual void ProcessCodeCompleteResults(Sema &S,
+ CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) {}
+
+ /// \param S the semantic-analyzer object for which code-completion is being
+ /// done.
+ ///
+ /// \param CurrentArg the index of the current argument.
+ ///
+ /// \param Candidates an array of overload candidates.
+ ///
+ /// \param NumCandidates the number of overload candidates
+ ///
+ /// \param OpenParLoc location of the opening parenthesis of the argument
+ /// list.
+ virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc,
+ bool Braced) {}
+ //@}
+
+ /// Retrieve the allocator that will be used to allocate
+ /// code completion strings.
+ virtual CodeCompletionAllocator &getAllocator() = 0;
+
+ virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() = 0;
+};
+
+/// Get the documentation comment used to produce
+/// CodeCompletionString::BriefComment for RK_Declaration.
+const RawComment *getCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *Decl);
+
+/// Get the documentation comment used to produce
+/// CodeCompletionString::BriefComment for RK_Pattern.
+const RawComment *getPatternCompletionComment(const ASTContext &Ctx,
+ const NamedDecl *Decl);
+
+/// Get the documentation comment used to produce
+/// CodeCompletionString::BriefComment for OverloadCandidate.
+const RawComment *
+getParameterComment(const ASTContext &Ctx,
+ const CodeCompleteConsumer::OverloadCandidate &Result,
+ unsigned ArgIndex);
+
+/// A simple code-completion consumer that prints the results it
+/// receives in a simple format.
+class PrintingCodeCompleteConsumer : public CodeCompleteConsumer {
+ /// The raw output stream.
+ raw_ostream &OS;
+
+ CodeCompletionTUInfo CCTUInfo;
+
+public:
+ /// Create a new printing code-completion consumer that prints its
+ /// results to the given raw output stream.
+ PrintingCodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
+ raw_ostream &OS)
+ : CodeCompleteConsumer(CodeCompleteOpts), OS(OS),
+ CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {}
+
+ /// Prints the finalized code-completion results.
+ void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) override;
+
+ void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc,
+ bool Braced) override;
+
+ bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) override;
+
+ CodeCompletionAllocator &getAllocator() override {
+ return CCTUInfo.getAllocator();
+ }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/CodeCompleteOptions.h b/contrib/libs/clang16/include/clang/Sema/CodeCompleteOptions.h
new file mode 100644
index 0000000000..121f586a81
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/CodeCompleteOptions.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===---- CodeCompleteOptions.h - Code Completion Options -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H
+#define LLVM_CLANG_SEMA_CODECOMPLETEOPTIONS_H
+
+namespace clang {
+
+/// Options controlling the behavior of code completion.
+class CodeCompleteOptions {
+public:
+ /// Show macros in code completion results.
+ unsigned IncludeMacros : 1;
+
+ /// Show code patterns in code completion results.
+ unsigned IncludeCodePatterns : 1;
+
+ /// Show top-level decls in code completion results.
+ unsigned IncludeGlobals : 1;
+
+ /// Show decls in namespace (including the global namespace) in code
+ /// completion results. If this is 0, `IncludeGlobals` will be ignored.
+ ///
+ /// Currently, this only works when completing qualified IDs (i.e.
+ /// `Sema::CodeCompleteQualifiedId`).
+ /// FIXME: consider supporting more completion cases with this option.
+ unsigned IncludeNamespaceLevelDecls : 1;
+
+ /// Show brief documentation comments in code completion results.
+ unsigned IncludeBriefComments : 1;
+
+ /// Hint whether to load data from the external AST to provide full results.
+ /// If false, namespace-level declarations and macros from the preamble may be
+ /// omitted.
+ unsigned LoadExternal : 1;
+
+ /// Include results after corrections (small fix-its), e.g. change '.' to '->'
+ /// on member access, etc.
+ unsigned IncludeFixIts : 1;
+
+ CodeCompleteOptions()
+ : IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1),
+ IncludeNamespaceLevelDecls(1), IncludeBriefComments(0),
+ LoadExternal(1), IncludeFixIts(0) {}
+};
+
+} // namespace clang
+
+#endif
+
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/DeclSpec.h b/contrib/libs/clang16/include/clang/Sema/DeclSpec.h
new file mode 100644
index 0000000000..6bc95d8a48
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/DeclSpec.h
@@ -0,0 +1,2820 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- DeclSpec.h - Parsed declaration specifiers -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the classes used to store parsed information about
+/// declaration-specifiers and declarators.
+///
+/// \verbatim
+/// static const int volatile x, *y, *(*(*z)[10])(const void *x);
+/// ------------------------- - -- ---------------------------
+/// declaration-specifiers \ | /
+/// declarators
+/// \endverbatim
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DECLSPEC_H
+#define LLVM_CLANG_SEMA_DECLSPEC_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjCCommon.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/Basic/ExceptionSpecificationType.h"
+#include "clang/Basic/Lambda.h"
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Lex/Token.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/ParsedAttr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace clang {
+ class ASTContext;
+ class CXXRecordDecl;
+ class TypeLoc;
+ class LangOptions;
+ class IdentifierInfo;
+ class NamespaceAliasDecl;
+ class NamespaceDecl;
+ class ObjCDeclSpec;
+ class Sema;
+ class Declarator;
+ struct TemplateIdAnnotation;
+
+/// Represents a C++ nested-name-specifier or a global scope specifier.
+///
+/// These can be in 3 states:
+/// 1) Not present, identified by isEmpty()
+/// 2) Present, identified by isNotEmpty()
+/// 2.a) Valid, identified by isValid()
+/// 2.b) Invalid, identified by isInvalid().
+///
+/// isSet() is deprecated because it mostly corresponded to "valid" but was
+/// often used as if it meant "present".
+///
+/// The actual scope is described by getScopeRep().
+class CXXScopeSpec {
+ SourceRange Range;
+ NestedNameSpecifierLocBuilder Builder;
+
+public:
+ SourceRange getRange() const { return Range; }
+ void setRange(SourceRange R) { Range = R; }
+ void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
+ void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
+ SourceLocation getBeginLoc() const { return Range.getBegin(); }
+ SourceLocation getEndLoc() const { return Range.getEnd(); }
+
+ /// Retrieve the representation of the nested-name-specifier.
+ NestedNameSpecifier *getScopeRep() const {
+ return Builder.getRepresentation();
+ }
+
+ /// Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'type::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param TemplateKWLoc The location of the 'template' keyword, if present.
+ ///
+ /// \param TL The TypeLoc that describes the type preceding the '::'.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
+ SourceLocation ColonColonLoc);
+
+ /// Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'identifier::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Identifier The identifier.
+ ///
+ /// \param IdentifierLoc The location of the identifier.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, IdentifierInfo *Identifier,
+ SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
+
+ /// Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Namespace The namespace.
+ ///
+ /// \param NamespaceLoc The location of the namespace name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceDecl *Namespace,
+ SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
+
+ /// Extend the current nested-name-specifier by another
+ /// nested-name-specifier component of the form 'namespace-alias::'.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param Alias The namespace alias.
+ ///
+ /// \param AliasLoc The location of the namespace alias
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
+ SourceLocation AliasLoc, SourceLocation ColonColonLoc);
+
+ /// Turn this (empty) nested-name-specifier into the global
+ /// nested-name-specifier '::'.
+ void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
+
+ /// Turns this (empty) nested-name-specifier into '__super'
+ /// nested-name-specifier.
+ ///
+ /// \param Context The AST context in which this nested-name-specifier
+ /// resides.
+ ///
+ /// \param RD The declaration of the class in which nested-name-specifier
+ /// appeared.
+ ///
+ /// \param SuperLoc The location of the '__super' keyword.
+ /// name.
+ ///
+ /// \param ColonColonLoc The location of the trailing '::'.
+ void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
+ SourceLocation SuperLoc, SourceLocation ColonColonLoc);
+
+ /// Make a new nested-name-specifier from incomplete source-location
+ /// information.
+ ///
+ /// FIXME: This routine should be used very, very rarely, in cases where we
+ /// need to synthesize a nested-name-specifier. Most code should instead use
+ /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
+ void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
+ SourceRange R);
+
+ /// Adopt an existing nested-name-specifier (with source-range
+ /// information).
+ void Adopt(NestedNameSpecifierLoc Other);
+
+ /// Retrieve a nested-name-specifier with location information, copied
+ /// into the given AST context.
+ ///
+ /// \param Context The context into which this nested-name-specifier will be
+ /// copied.
+ NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
+
+ /// Retrieve the location of the name in the last qualifier
+ /// in this nested name specifier.
+ ///
+ /// For example, the location of \c bar
+ /// in
+ /// \verbatim
+ /// \::foo::bar<0>::
+ /// ^~~
+ /// \endverbatim
+ SourceLocation getLastQualifierNameLoc() const;
+
+ /// No scope specifier.
+ bool isEmpty() const { return Range.isInvalid() && getScopeRep() == nullptr; }
+ /// A scope specifier is present, but may be valid or invalid.
+ bool isNotEmpty() const { return !isEmpty(); }
+
+ /// An error occurred during parsing of the scope specifier.
+ bool isInvalid() const { return Range.isValid() && getScopeRep() == nullptr; }
+ /// A scope specifier is present, and it refers to a real scope.
+ bool isValid() const { return getScopeRep() != nullptr; }
+
+ /// Indicate that this nested-name-specifier is invalid.
+ void SetInvalid(SourceRange R) {
+ assert(R.isValid() && "Must have a valid source range");
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(R.getBegin());
+ Range.setEnd(R.getEnd());
+ Builder.Clear();
+ }
+
+ /// Deprecated. Some call sites intend isNotEmpty() while others intend
+ /// isValid().
+ bool isSet() const { return getScopeRep() != nullptr; }
+
+ void clear() {
+ Range = SourceRange();
+ Builder.Clear();
+ }
+
+ /// Retrieve the data associated with the source-location information.
+ char *location_data() const { return Builder.getBuffer().first; }
+
+ /// Retrieve the size of the data associated with source-location
+ /// information.
+ unsigned location_size() const { return Builder.getBuffer().second; }
+};
+
+/// Captures information about "declaration specifiers".
+///
+/// "Declaration specifiers" encompasses storage-class-specifiers,
+/// type-specifiers, type-qualifiers, and function-specifiers.
+class DeclSpec {
+public:
+ /// storage-class-specifier
+ /// \note The order of these enumerators is important for diagnostics.
+ enum SCS {
+ SCS_unspecified = 0,
+ SCS_typedef,
+ SCS_extern,
+ SCS_static,
+ SCS_auto,
+ SCS_register,
+ SCS_private_extern,
+ SCS_mutable
+ };
+
+ // Import thread storage class specifier enumeration and constants.
+ // These can be combined with SCS_extern and SCS_static.
+ typedef ThreadStorageClassSpecifier TSCS;
+ static const TSCS TSCS_unspecified = clang::TSCS_unspecified;
+ static const TSCS TSCS___thread = clang::TSCS___thread;
+ static const TSCS TSCS_thread_local = clang::TSCS_thread_local;
+ static const TSCS TSCS__Thread_local = clang::TSCS__Thread_local;
+
+ enum TSC {
+ TSC_unspecified,
+ TSC_imaginary,
+ TSC_complex
+ };
+
+ // Import type specifier type enumeration and constants.
+ typedef TypeSpecifierType TST;
+ static const TST TST_unspecified = clang::TST_unspecified;
+ static const TST TST_void = clang::TST_void;
+ static const TST TST_char = clang::TST_char;
+ static const TST TST_wchar = clang::TST_wchar;
+ static const TST TST_char8 = clang::TST_char8;
+ static const TST TST_char16 = clang::TST_char16;
+ static const TST TST_char32 = clang::TST_char32;
+ static const TST TST_int = clang::TST_int;
+ static const TST TST_int128 = clang::TST_int128;
+ static const TST TST_bitint = clang::TST_bitint;
+ static const TST TST_half = clang::TST_half;
+ static const TST TST_BFloat16 = clang::TST_BFloat16;
+ static const TST TST_float = clang::TST_float;
+ static const TST TST_double = clang::TST_double;
+ static const TST TST_float16 = clang::TST_Float16;
+ static const TST TST_accum = clang::TST_Accum;
+ static const TST TST_fract = clang::TST_Fract;
+ static const TST TST_float128 = clang::TST_float128;
+ static const TST TST_ibm128 = clang::TST_ibm128;
+ static const TST TST_bool = clang::TST_bool;
+ static const TST TST_decimal32 = clang::TST_decimal32;
+ static const TST TST_decimal64 = clang::TST_decimal64;
+ static const TST TST_decimal128 = clang::TST_decimal128;
+ static const TST TST_enum = clang::TST_enum;
+ static const TST TST_union = clang::TST_union;
+ static const TST TST_struct = clang::TST_struct;
+ static const TST TST_interface = clang::TST_interface;
+ static const TST TST_class = clang::TST_class;
+ static const TST TST_typename = clang::TST_typename;
+ static const TST TST_typeofType = clang::TST_typeofType;
+ static const TST TST_typeofExpr = clang::TST_typeofExpr;
+ static const TST TST_typeof_unqualType = clang::TST_typeof_unqualType;
+ static const TST TST_typeof_unqualExpr = clang::TST_typeof_unqualExpr;
+ static const TST TST_decltype = clang::TST_decltype;
+ static const TST TST_decltype_auto = clang::TST_decltype_auto;
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
+ static const TST TST_##Trait = clang::TST_##Trait;
+#include "clang/Basic/TransformTypeTraits.def"
+ static const TST TST_auto = clang::TST_auto;
+ static const TST TST_auto_type = clang::TST_auto_type;
+ static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
+ static const TST TST_atomic = clang::TST_atomic;
+#define GENERIC_IMAGE_TYPE(ImgType, Id) \
+ static const TST TST_##ImgType##_t = clang::TST_##ImgType##_t;
+#include "clang/Basic/OpenCLImageTypes.def"
+ static const TST TST_error = clang::TST_error;
+
+ // type-qualifiers
+ enum TQ { // NOTE: These flags must be kept in sync with Qualifiers::TQ.
+ TQ_unspecified = 0,
+ TQ_const = 1,
+ TQ_restrict = 2,
+ TQ_volatile = 4,
+ TQ_unaligned = 8,
+ // This has no corresponding Qualifiers::TQ value, because it's not treated
+ // as a qualifier in our type system.
+ TQ_atomic = 16
+ };
+
+ /// ParsedSpecifiers - Flags to query which specifiers were applied. This is
+ /// returned by getParsedSpecifiers.
+ enum ParsedSpecifiers {
+ PQ_None = 0,
+ PQ_StorageClassSpecifier = 1,
+ PQ_TypeSpecifier = 2,
+ PQ_TypeQualifier = 4,
+ PQ_FunctionSpecifier = 8
+ // FIXME: Attributes should be included here.
+ };
+
+ enum FriendSpecified : bool {
+ No,
+ Yes,
+ };
+
+private:
+ // storage-class-specifier
+ /*SCS*/unsigned StorageClassSpec : 3;
+ /*TSCS*/unsigned ThreadStorageClassSpec : 2;
+ unsigned SCS_extern_in_linkage_spec : 1;
+
+ // type-specifier
+ /*TypeSpecifierWidth*/ unsigned TypeSpecWidth : 2;
+ /*TSC*/unsigned TypeSpecComplex : 2;
+ /*TSS*/unsigned TypeSpecSign : 2;
+ /*TST*/unsigned TypeSpecType : 7;
+ unsigned TypeAltiVecVector : 1;
+ unsigned TypeAltiVecPixel : 1;
+ unsigned TypeAltiVecBool : 1;
+ unsigned TypeSpecOwned : 1;
+ unsigned TypeSpecPipe : 1;
+ unsigned TypeSpecSat : 1;
+ unsigned ConstrainedAuto : 1;
+
+ // type-qualifiers
+ unsigned TypeQualifiers : 5; // Bitwise OR of TQ.
+
+ // function-specifier
+ unsigned FS_inline_specified : 1;
+ unsigned FS_forceinline_specified: 1;
+ unsigned FS_virtual_specified : 1;
+ unsigned FS_noreturn_specified : 1;
+
+ // friend-specifier
+ unsigned Friend_specified : 1;
+
+ // constexpr-specifier
+ unsigned ConstexprSpecifier : 2;
+
+ union {
+ UnionParsedType TypeRep;
+ Decl *DeclRep;
+ Expr *ExprRep;
+ TemplateIdAnnotation *TemplateIdRep;
+ };
+
+ /// ExplicitSpecifier - Store information about explicit spicifer.
+ ExplicitSpecifier FS_explicit_specifier;
+
+ // attributes.
+ ParsedAttributes Attrs;
+
+ // Scope specifier for the type spec, if applicable.
+ CXXScopeSpec TypeScope;
+
+ // SourceLocation info. These are null if the item wasn't specified or if
+ // the setting was synthesized.
+ SourceRange Range;
+
+ SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc;
+ SourceRange TSWRange;
+ SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc, TSSatLoc;
+ /// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union,
+ /// typename, then this is the location of the named type (if present);
+ /// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and
+ /// TSTNameLoc provides source range info for tag types.
+ SourceLocation TSTNameLoc;
+ SourceRange TypeofParensRange;
+ SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc,
+ TQ_unalignedLoc;
+ SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
+ SourceLocation FS_explicitCloseParenLoc;
+ SourceLocation FS_forceinlineLoc;
+ SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
+ SourceLocation TQ_pipeLoc;
+
+ WrittenBuiltinSpecs writtenBS;
+ void SaveWrittenBuiltinSpecs();
+
+ ObjCDeclSpec *ObjCQualifiers;
+
+ static bool isTypeRep(TST T) {
+ return T == TST_atomic || T == TST_typename || T == TST_typeofType ||
+ T == TST_typeof_unqualType || isTransformTypeTrait(T);
+ }
+ static bool isExprRep(TST T) {
+ return T == TST_typeofExpr || T == TST_typeof_unqualExpr ||
+ T == TST_decltype || T == TST_bitint;
+ }
+ static bool isTemplateIdRep(TST T) {
+ return (T == TST_auto || T == TST_decltype_auto);
+ }
+
+ DeclSpec(const DeclSpec &) = delete;
+ void operator=(const DeclSpec &) = delete;
+public:
+ static bool isDeclRep(TST T) {
+ return (T == TST_enum || T == TST_struct ||
+ T == TST_interface || T == TST_union ||
+ T == TST_class);
+ }
+ static bool isTransformTypeTrait(TST T) {
+ constexpr std::array<TST, 16> Traits = {
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) TST_##Trait,
+#include "clang/Basic/TransformTypeTraits.def"
+ };
+
+ return T >= Traits.front() && T <= Traits.back();
+ }
+
+ DeclSpec(AttributeFactory &attrFactory)
+ : StorageClassSpec(SCS_unspecified),
+ ThreadStorageClassSpec(TSCS_unspecified),
+ SCS_extern_in_linkage_spec(false),
+ TypeSpecWidth(static_cast<unsigned>(TypeSpecifierWidth::Unspecified)),
+ TypeSpecComplex(TSC_unspecified),
+ TypeSpecSign(static_cast<unsigned>(TypeSpecifierSign::Unspecified)),
+ TypeSpecType(TST_unspecified), TypeAltiVecVector(false),
+ TypeAltiVecPixel(false), TypeAltiVecBool(false), TypeSpecOwned(false),
+ TypeSpecPipe(false), TypeSpecSat(false), ConstrainedAuto(false),
+ TypeQualifiers(TQ_unspecified), FS_inline_specified(false),
+ FS_forceinline_specified(false), FS_virtual_specified(false),
+ FS_noreturn_specified(false), Friend_specified(false),
+ ConstexprSpecifier(
+ static_cast<unsigned>(ConstexprSpecKind::Unspecified)),
+ Attrs(attrFactory), writtenBS(), ObjCQualifiers(nullptr) {}
+
+ // storage-class-specifier
+ SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
+ TSCS getThreadStorageClassSpec() const {
+ return (TSCS)ThreadStorageClassSpec;
+ }
+ bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; }
+ void setExternInLinkageSpec(bool Value) {
+ SCS_extern_in_linkage_spec = Value;
+ }
+
+ SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
+ SourceLocation getThreadStorageClassSpecLoc() const {
+ return ThreadStorageClassSpecLoc;
+ }
+
+ void ClearStorageClassSpecs() {
+ StorageClassSpec = DeclSpec::SCS_unspecified;
+ ThreadStorageClassSpec = DeclSpec::TSCS_unspecified;
+ SCS_extern_in_linkage_spec = false;
+ StorageClassSpecLoc = SourceLocation();
+ ThreadStorageClassSpecLoc = SourceLocation();
+ }
+
+ void ClearTypeSpecType() {
+ TypeSpecType = DeclSpec::TST_unspecified;
+ TypeSpecOwned = false;
+ TSTLoc = SourceLocation();
+ }
+
+ // type-specifier
+ TypeSpecifierWidth getTypeSpecWidth() const {
+ return static_cast<TypeSpecifierWidth>(TypeSpecWidth);
+ }
+ TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; }
+ TypeSpecifierSign getTypeSpecSign() const {
+ return static_cast<TypeSpecifierSign>(TypeSpecSign);
+ }
+ TST getTypeSpecType() const { return (TST)TypeSpecType; }
+ bool isTypeAltiVecVector() const { return TypeAltiVecVector; }
+ bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; }
+ bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
+ bool isTypeSpecOwned() const { return TypeSpecOwned; }
+ bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
+ bool isTypeSpecPipe() const { return TypeSpecPipe; }
+ bool isTypeSpecSat() const { return TypeSpecSat; }
+ bool isConstrainedAuto() const { return ConstrainedAuto; }
+
+ ParsedType getRepAsType() const {
+ assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
+ return TypeRep;
+ }
+ Decl *getRepAsDecl() const {
+ assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");
+ return DeclRep;
+ }
+ Expr *getRepAsExpr() const {
+ assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");
+ return ExprRep;
+ }
+ TemplateIdAnnotation *getRepAsTemplateId() const {
+ assert(isTemplateIdRep((TST) TypeSpecType) &&
+ "DeclSpec does not store a template id");
+ return TemplateIdRep;
+ }
+ CXXScopeSpec &getTypeSpecScope() { return TypeScope; }
+ const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
+
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
+
+ SourceLocation getTypeSpecWidthLoc() const { return TSWRange.getBegin(); }
+ SourceRange getTypeSpecWidthRange() const { return TSWRange; }
+ SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; }
+ SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
+ SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
+ SourceLocation getAltiVecLoc() const { return AltiVecLoc; }
+ SourceLocation getTypeSpecSatLoc() const { return TSSatLoc; }
+
+ SourceLocation getTypeSpecTypeNameLoc() const {
+ assert(isDeclRep((TST)TypeSpecType) || isTypeRep((TST)TypeSpecType) ||
+ isExprRep((TST)TypeSpecType));
+ return TSTNameLoc;
+ }
+
+ SourceRange getTypeofParensRange() const { return TypeofParensRange; }
+ void setTypeArgumentRange(SourceRange range) { TypeofParensRange = range; }
+
+ bool hasAutoTypeSpec() const {
+ return (TypeSpecType == TST_auto || TypeSpecType == TST_auto_type ||
+ TypeSpecType == TST_decltype_auto);
+ }
+
+ bool hasTagDefinition() const;
+
+ /// Turn a type-specifier-type into a string like "_Bool" or "union".
+ static const char *getSpecifierName(DeclSpec::TST T,
+ const PrintingPolicy &Policy);
+ static const char *getSpecifierName(DeclSpec::TQ Q);
+ static const char *getSpecifierName(TypeSpecifierSign S);
+ static const char *getSpecifierName(DeclSpec::TSC C);
+ static const char *getSpecifierName(TypeSpecifierWidth W);
+ static const char *getSpecifierName(DeclSpec::SCS S);
+ static const char *getSpecifierName(DeclSpec::TSCS S);
+ static const char *getSpecifierName(ConstexprSpecKind C);
+
+ // type-qualifiers
+
+ /// getTypeQualifiers - Return a set of TQs.
+ unsigned getTypeQualifiers() const { return TypeQualifiers; }
+ SourceLocation getConstSpecLoc() const { return TQ_constLoc; }
+ SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
+ SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
+ SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
+ SourceLocation getUnalignedSpecLoc() const { return TQ_unalignedLoc; }
+ SourceLocation getPipeLoc() const { return TQ_pipeLoc; }
+
+ /// Clear out all of the type qualifiers.
+ void ClearTypeQualifiers() {
+ TypeQualifiers = 0;
+ TQ_constLoc = SourceLocation();
+ TQ_restrictLoc = SourceLocation();
+ TQ_volatileLoc = SourceLocation();
+ TQ_atomicLoc = SourceLocation();
+ TQ_unalignedLoc = SourceLocation();
+ TQ_pipeLoc = SourceLocation();
+ }
+
+ // function-specifier
+ bool isInlineSpecified() const {
+ return FS_inline_specified | FS_forceinline_specified;
+ }
+ SourceLocation getInlineSpecLoc() const {
+ return FS_inline_specified ? FS_inlineLoc : FS_forceinlineLoc;
+ }
+
+ ExplicitSpecifier getExplicitSpecifier() const {
+ return FS_explicit_specifier;
+ }
+
+ bool isVirtualSpecified() const { return FS_virtual_specified; }
+ SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
+
+ bool hasExplicitSpecifier() const {
+ return FS_explicit_specifier.isSpecified();
+ }
+ SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; }
+ SourceRange getExplicitSpecRange() const {
+ return FS_explicit_specifier.getExpr()
+ ? SourceRange(FS_explicitLoc, FS_explicitCloseParenLoc)
+ : SourceRange(FS_explicitLoc);
+ }
+
+ bool isNoreturnSpecified() const { return FS_noreturn_specified; }
+ SourceLocation getNoreturnSpecLoc() const { return FS_noreturnLoc; }
+
+ void ClearFunctionSpecs() {
+ FS_inline_specified = false;
+ FS_inlineLoc = SourceLocation();
+ FS_forceinline_specified = false;
+ FS_forceinlineLoc = SourceLocation();
+ FS_virtual_specified = false;
+ FS_virtualLoc = SourceLocation();
+ FS_explicit_specifier = ExplicitSpecifier();
+ FS_explicitLoc = SourceLocation();
+ FS_explicitCloseParenLoc = SourceLocation();
+ FS_noreturn_specified = false;
+ FS_noreturnLoc = SourceLocation();
+ }
+
+ /// This method calls the passed in handler on each CVRU qual being
+ /// set.
+ /// Handle - a handler to be invoked.
+ void forEachCVRUQualifier(
+ llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle);
+
+ /// This method calls the passed in handler on each qual being
+ /// set.
+ /// Handle - a handler to be invoked.
+ void forEachQualifier(
+ llvm::function_ref<void(TQ, StringRef, SourceLocation)> Handle);
+
+ /// Return true if any type-specifier has been found.
+ bool hasTypeSpecifier() const {
+ return getTypeSpecType() != DeclSpec::TST_unspecified ||
+ getTypeSpecWidth() != TypeSpecifierWidth::Unspecified ||
+ getTypeSpecComplex() != DeclSpec::TSC_unspecified ||
+ getTypeSpecSign() != TypeSpecifierSign::Unspecified;
+ }
+
+ /// Return a bitmask of which flavors of specifiers this
+ /// DeclSpec includes.
+ unsigned getParsedSpecifiers() const;
+
+ /// isEmpty - Return true if this declaration specifier is completely empty:
+ /// no tokens were parsed in the production of it.
+ bool isEmpty() const {
+ return getParsedSpecifiers() == DeclSpec::PQ_None;
+ }
+
+ void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); }
+ void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); }
+
+ /// These methods set the specified attribute of the DeclSpec and
+ /// return false if there was no error. If an error occurs (for
+ /// example, if we tried to set "auto" on a spec with "extern"
+ /// already set), they return true and set PrevSpec and DiagID
+ /// such that
+ /// Diag(Loc, DiagID) << PrevSpec;
+ /// will yield a useful result.
+ ///
+ /// TODO: use a more general approach that still allows these
+ /// diagnostics to be ignored when desired.
+ bool SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID);
+ bool SetTypeSpecWidth(TypeSpecifierWidth W, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecSign(TypeSpecifierSign S, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, ParsedType Rep,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, TypeResult Rep,
+ const PrintingPolicy &Policy) {
+ if (Rep.isInvalid())
+ return SetTypeSpecError();
+ return SetTypeSpecType(T, Loc, PrevSpec, DiagID, Rep.get(), Policy);
+ }
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+ SourceLocation TagNameLoc, const char *&PrevSpec,
+ unsigned &DiagID, ParsedType Rep,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation TagKwLoc,
+ SourceLocation TagNameLoc, const char *&PrevSpec,
+ unsigned &DiagID, Decl *Rep, bool Owned,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, TemplateIdAnnotation *Rep,
+ const PrintingPolicy &Policy);
+
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, Expr *Rep,
+ const PrintingPolicy &policy);
+ bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetTypePipe(bool isPipe, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetBitIntType(SourceLocation KWLoc, Expr *BitWidth,
+ const char *&PrevSpec, unsigned &DiagID,
+ const PrintingPolicy &Policy);
+ bool SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecError();
+ void UpdateDeclRep(Decl *Rep) {
+ assert(isDeclRep((TST) TypeSpecType));
+ DeclRep = Rep;
+ }
+ void UpdateTypeRep(ParsedType Rep) {
+ assert(isTypeRep((TST) TypeSpecType));
+ TypeRep = Rep;
+ }
+ void UpdateExprRep(Expr *Rep) {
+ assert(isExprRep((TST) TypeSpecType));
+ ExprRep = Rep;
+ }
+
+ bool SetTypeQual(TQ T, SourceLocation Loc);
+
+ bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, const LangOptions &Lang);
+
+ bool setFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecForceInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, ExplicitSpecifier ExplicitSpec,
+ SourceLocation CloseParenLoc);
+ bool setFunctionSpecNoreturn(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
+ bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetConstexprSpec(ConstexprSpecKind ConstexprKind, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID);
+
+ FriendSpecified isFriendSpecified() const {
+ return static_cast<FriendSpecified>(Friend_specified);
+ }
+
+ SourceLocation getFriendSpecLoc() const { return FriendLoc; }
+
+ bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); }
+ SourceLocation getModulePrivateSpecLoc() const { return ModulePrivateLoc; }
+
+ ConstexprSpecKind getConstexprSpecifier() const {
+ return ConstexprSpecKind(ConstexprSpecifier);
+ }
+
+ SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
+ bool hasConstexprSpecifier() const {
+ return getConstexprSpecifier() != ConstexprSpecKind::Unspecified;
+ }
+
+ void ClearConstexprSpec() {
+ ConstexprSpecifier = static_cast<unsigned>(ConstexprSpecKind::Unspecified);
+ ConstexprLoc = SourceLocation();
+ }
+
+ AttributePool &getAttributePool() const {
+ return Attrs.getPool();
+ }
+
+ /// Concatenates two attribute lists.
+ ///
+ /// The GCC attribute syntax allows for the following:
+ ///
+ /// \code
+ /// short __attribute__(( unused, deprecated ))
+ /// int __attribute__(( may_alias, aligned(16) )) var;
+ /// \endcode
+ ///
+ /// This declares 4 attributes using 2 lists. The following syntax is
+ /// also allowed and equivalent to the previous declaration.
+ ///
+ /// \code
+ /// short __attribute__((unused)) __attribute__((deprecated))
+ /// int __attribute__((may_alias)) __attribute__((aligned(16))) var;
+ /// \endcode
+ ///
+ void addAttributes(const ParsedAttributesView &AL) {
+ Attrs.addAll(AL.begin(), AL.end());
+ }
+
+ bool hasAttributes() const { return !Attrs.empty(); }
+
+ ParsedAttributes &getAttributes() { return Attrs; }
+ const ParsedAttributes &getAttributes() const { return Attrs; }
+
+ void takeAttributesFrom(ParsedAttributes &attrs) {
+ Attrs.takeAllFrom(attrs);
+ }
+
+ /// Finish - This does final analysis of the declspec, issuing diagnostics for
+ /// things like "_Imaginary" (lacking an FP type). After calling this method,
+ /// DeclSpec is guaranteed self-consistent, even if an error occurred.
+ void Finish(Sema &S, const PrintingPolicy &Policy);
+
+ const WrittenBuiltinSpecs& getWrittenBuiltinSpecs() const {
+ return writtenBS;
+ }
+
+ ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; }
+ void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; }
+
+ /// Checks if this DeclSpec can stand alone, without a Declarator.
+ ///
+ /// Only tag declspecs can stand alone.
+ bool isMissingDeclaratorOk();
+};
+
+/// Captures information about "declaration specifiers" specific to
+/// Objective-C.
+class ObjCDeclSpec {
+public:
+ /// ObjCDeclQualifier - Qualifier used on types in method
+ /// declarations. Not all combinations are sensible. Parameters
+ /// can be one of { in, out, inout } with one of { bycopy, byref }.
+ /// Returns can either be { oneway } or not.
+ ///
+ /// This should be kept in sync with Decl::ObjCDeclQualifier.
+ enum ObjCDeclQualifier {
+ DQ_None = 0x0,
+ DQ_In = 0x1,
+ DQ_Inout = 0x2,
+ DQ_Out = 0x4,
+ DQ_Bycopy = 0x8,
+ DQ_Byref = 0x10,
+ DQ_Oneway = 0x20,
+ DQ_CSNullability = 0x40
+ };
+
+ ObjCDeclSpec()
+ : objcDeclQualifier(DQ_None),
+ PropertyAttributes(ObjCPropertyAttribute::kind_noattr), Nullability(0),
+ GetterName(nullptr), SetterName(nullptr) {}
+
+ ObjCDeclQualifier getObjCDeclQualifier() const {
+ return (ObjCDeclQualifier)objcDeclQualifier;
+ }
+ void setObjCDeclQualifier(ObjCDeclQualifier DQVal) {
+ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal);
+ }
+ void clearObjCDeclQualifier(ObjCDeclQualifier DQVal) {
+ objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier & ~DQVal);
+ }
+
+ ObjCPropertyAttribute::Kind getPropertyAttributes() const {
+ return ObjCPropertyAttribute::Kind(PropertyAttributes);
+ }
+ void setPropertyAttributes(ObjCPropertyAttribute::Kind PRVal) {
+ PropertyAttributes =
+ (ObjCPropertyAttribute::Kind)(PropertyAttributes | PRVal);
+ }
+
+ NullabilityKind getNullability() const {
+ assert(
+ ((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)) &&
+ "Objective-C declspec doesn't have nullability");
+ return static_cast<NullabilityKind>(Nullability);
+ }
+
+ SourceLocation getNullabilityLoc() const {
+ assert(
+ ((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)) &&
+ "Objective-C declspec doesn't have nullability");
+ return NullabilityLoc;
+ }
+
+ void setNullability(SourceLocation loc, NullabilityKind kind) {
+ assert(
+ ((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & ObjCPropertyAttribute::kind_nullability)) &&
+ "Set the nullability declspec or property attribute first");
+ Nullability = static_cast<unsigned>(kind);
+ NullabilityLoc = loc;
+ }
+
+ const IdentifierInfo *getGetterName() const { return GetterName; }
+ IdentifierInfo *getGetterName() { return GetterName; }
+ SourceLocation getGetterNameLoc() const { return GetterNameLoc; }
+ void setGetterName(IdentifierInfo *name, SourceLocation loc) {
+ GetterName = name;
+ GetterNameLoc = loc;
+ }
+
+ const IdentifierInfo *getSetterName() const { return SetterName; }
+ IdentifierInfo *getSetterName() { return SetterName; }
+ SourceLocation getSetterNameLoc() const { return SetterNameLoc; }
+ void setSetterName(IdentifierInfo *name, SourceLocation loc) {
+ SetterName = name;
+ SetterNameLoc = loc;
+ }
+
+private:
+ // FIXME: These two are unrelated and mutually exclusive. So perhaps
+ // we can put them in a union to reflect their mutual exclusivity
+ // (space saving is negligible).
+ unsigned objcDeclQualifier : 7;
+
+ // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttribute::Kind
+ unsigned PropertyAttributes : NumObjCPropertyAttrsBits;
+
+ unsigned Nullability : 2;
+
+ SourceLocation NullabilityLoc;
+
+ IdentifierInfo *GetterName; // getter name or NULL if no getter
+ IdentifierInfo *SetterName; // setter name or NULL if no setter
+ SourceLocation GetterNameLoc; // location of the getter attribute's value
+ SourceLocation SetterNameLoc; // location of the setter attribute's value
+
+};
+
+/// Describes the kind of unqualified-id parsed.
+enum class UnqualifiedIdKind {
+ /// An identifier.
+ IK_Identifier,
+ /// An overloaded operator name, e.g., operator+.
+ IK_OperatorFunctionId,
+ /// A conversion function name, e.g., operator int.
+ IK_ConversionFunctionId,
+ /// A user-defined literal name, e.g., operator "" _i.
+ IK_LiteralOperatorId,
+ /// A constructor name.
+ IK_ConstructorName,
+ /// A constructor named via a template-id.
+ IK_ConstructorTemplateId,
+ /// A destructor name.
+ IK_DestructorName,
+ /// A template-id, e.g., f<int>.
+ IK_TemplateId,
+ /// An implicit 'self' parameter
+ IK_ImplicitSelfParam,
+ /// A deduction-guide name (a template-name)
+ IK_DeductionGuideName
+};
+
+/// Represents a C++ unqualified-id that has been parsed.
+class UnqualifiedId {
+private:
+ UnqualifiedId(const UnqualifiedId &Other) = delete;
+ const UnqualifiedId &operator=(const UnqualifiedId &) = delete;
+
+ /// Describes the kind of unqualified-id parsed.
+ UnqualifiedIdKind Kind;
+
+public:
+ struct OFI {
+ /// The kind of overloaded operator.
+ OverloadedOperatorKind Operator;
+
+ /// The source locations of the individual tokens that name
+ /// the operator, e.g., the "new", "[", and "]" tokens in
+ /// operator new [].
+ ///
+ /// Different operators have different numbers of tokens in their name,
+ /// up to three. Any remaining source locations in this array will be
+ /// set to an invalid value for operators with fewer than three tokens.
+ SourceLocation SymbolLocations[3];
+ };
+
+ /// Anonymous union that holds extra data associated with the
+ /// parsed unqualified-id.
+ union {
+ /// When Kind == IK_Identifier, the parsed identifier, or when
+ /// Kind == IK_UserLiteralId, the identifier suffix.
+ IdentifierInfo *Identifier;
+
+ /// When Kind == IK_OperatorFunctionId, the overloaded operator
+ /// that we parsed.
+ struct OFI OperatorFunctionId;
+
+ /// When Kind == IK_ConversionFunctionId, the type that the
+ /// conversion function names.
+ UnionParsedType ConversionFunctionId;
+
+ /// When Kind == IK_ConstructorName, the class-name of the type
+ /// whose constructor is being referenced.
+ UnionParsedType ConstructorName;
+
+ /// When Kind == IK_DestructorName, the type referred to by the
+ /// class-name.
+ UnionParsedType DestructorName;
+
+ /// When Kind == IK_DeductionGuideName, the parsed template-name.
+ UnionParsedTemplateTy TemplateName;
+
+ /// When Kind == IK_TemplateId or IK_ConstructorTemplateId,
+ /// the template-id annotation that contains the template name and
+ /// template arguments.
+ TemplateIdAnnotation *TemplateId;
+ };
+
+ /// The location of the first token that describes this unqualified-id,
+ /// which will be the location of the identifier, "operator" keyword,
+ /// tilde (for a destructor), or the template name of a template-id.
+ SourceLocation StartLocation;
+
+ /// The location of the last token that describes this unqualified-id.
+ SourceLocation EndLocation;
+
+ UnqualifiedId()
+ : Kind(UnqualifiedIdKind::IK_Identifier), Identifier(nullptr) {}
+
+ /// Clear out this unqualified-id, setting it to default (invalid)
+ /// state.
+ void clear() {
+ Kind = UnqualifiedIdKind::IK_Identifier;
+ Identifier = nullptr;
+ StartLocation = SourceLocation();
+ EndLocation = SourceLocation();
+ }
+
+ /// Determine whether this unqualified-id refers to a valid name.
+ bool isValid() const { return StartLocation.isValid(); }
+
+ /// Determine whether this unqualified-id refers to an invalid name.
+ bool isInvalid() const { return !isValid(); }
+
+ /// Determine what kind of name we have.
+ UnqualifiedIdKind getKind() const { return Kind; }
+
+ /// Specify that this unqualified-id was parsed as an identifier.
+ ///
+ /// \param Id the parsed identifier.
+ /// \param IdLoc the location of the parsed identifier.
+ void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) {
+ Kind = UnqualifiedIdKind::IK_Identifier;
+ Identifier = const_cast<IdentifierInfo *>(Id);
+ StartLocation = EndLocation = IdLoc;
+ }
+
+ /// Specify that this unqualified-id was parsed as an
+ /// operator-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Op the overloaded operator.
+ ///
+ /// \param SymbolLocations the locations of the individual operator symbols
+ /// in the operator.
+ void setOperatorFunctionId(SourceLocation OperatorLoc,
+ OverloadedOperatorKind Op,
+ SourceLocation SymbolLocations[3]);
+
+ /// Specify that this unqualified-id was parsed as a
+ /// conversion-function-id.
+ ///
+ /// \param OperatorLoc the location of the 'operator' keyword.
+ ///
+ /// \param Ty the type to which this conversion function is converting.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConversionFunctionId(SourceLocation OperatorLoc,
+ ParsedType Ty,
+ SourceLocation EndLoc) {
+ Kind = UnqualifiedIdKind::IK_ConversionFunctionId;
+ StartLocation = OperatorLoc;
+ EndLocation = EndLoc;
+ ConversionFunctionId = Ty;
+ }
+
+ /// Specific that this unqualified-id was parsed as a
+ /// literal-operator-id.
+ ///
+ /// \param Id the parsed identifier.
+ ///
+ /// \param OpLoc the location of the 'operator' keyword.
+ ///
+ /// \param IdLoc the location of the identifier.
+ void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc,
+ SourceLocation IdLoc) {
+ Kind = UnqualifiedIdKind::IK_LiteralOperatorId;
+ Identifier = const_cast<IdentifierInfo *>(Id);
+ StartLocation = OpLoc;
+ EndLocation = IdLoc;
+ }
+
+ /// Specify that this unqualified-id was parsed as a constructor name.
+ ///
+ /// \param ClassType the class type referred to by the constructor name.
+ ///
+ /// \param ClassNameLoc the location of the class name.
+ ///
+ /// \param EndLoc the location of the last token that makes up the type name.
+ void setConstructorName(ParsedType ClassType,
+ SourceLocation ClassNameLoc,
+ SourceLocation EndLoc) {
+ Kind = UnqualifiedIdKind::IK_ConstructorName;
+ StartLocation = ClassNameLoc;
+ EndLocation = EndLoc;
+ ConstructorName = ClassType;
+ }
+
+ /// Specify that this unqualified-id was parsed as a
+ /// template-id that names a constructor.
+ ///
+ /// \param TemplateId the template-id annotation that describes the parsed
+ /// template-id. This UnqualifiedId instance will take ownership of the
+ /// \p TemplateId and will free it on destruction.
+ void setConstructorTemplateId(TemplateIdAnnotation *TemplateId);
+
+ /// Specify that this unqualified-id was parsed as a destructor name.
+ ///
+ /// \param TildeLoc the location of the '~' that introduces the destructor
+ /// name.
+ ///
+ /// \param ClassType the name of the class referred to by the destructor name.
+ void setDestructorName(SourceLocation TildeLoc,
+ ParsedType ClassType,
+ SourceLocation EndLoc) {
+ Kind = UnqualifiedIdKind::IK_DestructorName;
+ StartLocation = TildeLoc;
+ EndLocation = EndLoc;
+ DestructorName = ClassType;
+ }
+
+ /// Specify that this unqualified-id was parsed as a template-id.
+ ///
+ /// \param TemplateId the template-id annotation that describes the parsed
+ /// template-id. This UnqualifiedId instance will take ownership of the
+ /// \p TemplateId and will free it on destruction.
+ void setTemplateId(TemplateIdAnnotation *TemplateId);
+
+ /// Specify that this unqualified-id was parsed as a template-name for
+ /// a deduction-guide.
+ ///
+ /// \param Template The parsed template-name.
+ /// \param TemplateLoc The location of the parsed template-name.
+ void setDeductionGuideName(ParsedTemplateTy Template,
+ SourceLocation TemplateLoc) {
+ Kind = UnqualifiedIdKind::IK_DeductionGuideName;
+ TemplateName = Template;
+ StartLocation = EndLocation = TemplateLoc;
+ }
+
+ /// Specify that this unqualified-id is an implicit 'self'
+ /// parameter.
+ ///
+ /// \param Id the identifier.
+ void setImplicitSelfParam(const IdentifierInfo *Id) {
+ Kind = UnqualifiedIdKind::IK_ImplicitSelfParam;
+ Identifier = const_cast<IdentifierInfo *>(Id);
+ StartLocation = EndLocation = SourceLocation();
+ }
+
+ /// Return the source range that covers this unqualified-id.
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(StartLocation, EndLocation);
+ }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return StartLocation; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return EndLocation; }
+};
+
+/// A set of tokens that has been cached for later parsing.
+typedef SmallVector<Token, 4> CachedTokens;
+
+/// One instance of this struct is used for each type in a
+/// declarator that is parsed.
+///
+/// This is intended to be a small value object.
+struct DeclaratorChunk {
+ DeclaratorChunk() {};
+
+ enum {
+ Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe
+ } Kind;
+
+ /// Loc - The place where this type was defined.
+ SourceLocation Loc;
+ /// EndLoc - If valid, the place where this chunck ends.
+ SourceLocation EndLoc;
+
+ SourceRange getSourceRange() const {
+ if (EndLoc.isInvalid())
+ return SourceRange(Loc, Loc);
+ return SourceRange(Loc, EndLoc);
+ }
+
+ ParsedAttributesView AttrList;
+
+ struct PointerTypeInfo {
+ /// The type qualifiers: const/volatile/restrict/unaligned/atomic.
+ unsigned TypeQuals : 5;
+
+ /// The location of the const-qualifier, if any.
+ SourceLocation ConstQualLoc;
+
+ /// The location of the volatile-qualifier, if any.
+ SourceLocation VolatileQualLoc;
+
+ /// The location of the restrict-qualifier, if any.
+ SourceLocation RestrictQualLoc;
+
+ /// The location of the _Atomic-qualifier, if any.
+ SourceLocation AtomicQualLoc;
+
+ /// The location of the __unaligned-qualifier, if any.
+ SourceLocation UnalignedQualLoc;
+
+ void destroy() {
+ }
+ };
+
+ struct ReferenceTypeInfo {
+ /// The type qualifier: restrict. [GNU] C++ extension
+ bool HasRestrict : 1;
+ /// True if this is an lvalue reference, false if it's an rvalue reference.
+ bool LValueRef : 1;
+ void destroy() {
+ }
+ };
+
+ struct ArrayTypeInfo {
+ /// The type qualifiers for the array:
+ /// const/volatile/restrict/__unaligned/_Atomic.
+ unsigned TypeQuals : 5;
+
+ /// True if this dimension included the 'static' keyword.
+ unsigned hasStatic : 1;
+
+ /// True if this dimension was [*]. In this case, NumElts is null.
+ unsigned isStar : 1;
+
+ /// This is the size of the array, or null if [] or [*] was specified.
+ /// Since the parser is multi-purpose, and we don't want to impose a root
+ /// expression class on all clients, NumElts is untyped.
+ Expr *NumElts;
+
+ void destroy() {}
+ };
+
+ /// ParamInfo - An array of paraminfo objects is allocated whenever a function
+ /// declarator is parsed. There are two interesting styles of parameters
+ /// here:
+ /// K&R-style identifier lists and parameter type lists. K&R-style identifier
+ /// lists will have information about the identifier, but no type information.
+ /// Parameter type lists will have type info (if the actions module provides
+ /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'.
+ struct ParamInfo {
+ IdentifierInfo *Ident;
+ SourceLocation IdentLoc;
+ Decl *Param;
+
+ /// DefaultArgTokens - When the parameter's default argument
+ /// cannot be parsed immediately (because it occurs within the
+ /// declaration of a member function), it will be stored here as a
+ /// sequence of tokens to be parsed once the class definition is
+ /// complete. Non-NULL indicates that there is a default argument.
+ std::unique_ptr<CachedTokens> DefaultArgTokens;
+
+ ParamInfo() = default;
+ ParamInfo(IdentifierInfo *ident, SourceLocation iloc,
+ Decl *param,
+ std::unique_ptr<CachedTokens> DefArgTokens = nullptr)
+ : Ident(ident), IdentLoc(iloc), Param(param),
+ DefaultArgTokens(std::move(DefArgTokens)) {}
+ };
+
+ struct TypeAndRange {
+ ParsedType Ty;
+ SourceRange Range;
+ };
+
+ struct FunctionTypeInfo {
+ /// hasPrototype - This is true if the function had at least one typed
+ /// parameter. If the function is () or (a,b,c), then it has no prototype,
+ /// and is treated as a K&R-style function.
+ unsigned hasPrototype : 1;
+
+ /// isVariadic - If this function has a prototype, and if that
+ /// proto ends with ',...)', this is true. When true, EllipsisLoc
+ /// contains the location of the ellipsis.
+ unsigned isVariadic : 1;
+
+ /// Can this declaration be a constructor-style initializer?
+ unsigned isAmbiguous : 1;
+
+ /// Whether the ref-qualifier (if any) is an lvalue reference.
+ /// Otherwise, it's an rvalue reference.
+ unsigned RefQualifierIsLValueRef : 1;
+
+ /// ExceptionSpecType - An ExceptionSpecificationType value.
+ unsigned ExceptionSpecType : 4;
+
+ /// DeleteParams - If this is true, we need to delete[] Params.
+ unsigned DeleteParams : 1;
+
+ /// HasTrailingReturnType - If this is true, a trailing return type was
+ /// specified.
+ unsigned HasTrailingReturnType : 1;
+
+ /// The location of the left parenthesis in the source.
+ SourceLocation LParenLoc;
+
+ /// When isVariadic is true, the location of the ellipsis in the source.
+ SourceLocation EllipsisLoc;
+
+ /// The location of the right parenthesis in the source.
+ SourceLocation RParenLoc;
+
+ /// NumParams - This is the number of formal parameters specified by the
+ /// declarator.
+ unsigned NumParams;
+
+ /// NumExceptionsOrDecls - This is the number of types in the
+ /// dynamic-exception-decl, if the function has one. In C, this is the
+ /// number of declarations in the function prototype.
+ unsigned NumExceptionsOrDecls;
+
+ /// The location of the ref-qualifier, if any.
+ ///
+ /// If this is an invalid location, there is no ref-qualifier.
+ SourceLocation RefQualifierLoc;
+
+ /// The location of the 'mutable' qualifer in a lambda-declarator, if
+ /// any.
+ SourceLocation MutableLoc;
+
+ /// The beginning location of the exception specification, if any.
+ SourceLocation ExceptionSpecLocBeg;
+
+ /// The end location of the exception specification, if any.
+ SourceLocation ExceptionSpecLocEnd;
+
+ /// Params - This is a pointer to a new[]'d array of ParamInfo objects that
+ /// describe the parameters specified by this function declarator. null if
+ /// there are no parameters specified.
+ ParamInfo *Params;
+
+ /// DeclSpec for the function with the qualifier related info.
+ DeclSpec *MethodQualifiers;
+
+ /// AttributeFactory for the MethodQualifiers.
+ AttributeFactory *QualAttrFactory;
+
+ union {
+ /// Pointer to a new[]'d array of TypeAndRange objects that
+ /// contain the types in the function's dynamic exception specification
+ /// and their locations, if there is one.
+ TypeAndRange *Exceptions;
+
+ /// Pointer to the expression in the noexcept-specifier of this
+ /// function, if it has one.
+ Expr *NoexceptExpr;
+
+ /// Pointer to the cached tokens for an exception-specification
+ /// that has not yet been parsed.
+ CachedTokens *ExceptionSpecTokens;
+
+ /// Pointer to a new[]'d array of declarations that need to be available
+ /// for lookup inside the function body, if one exists. Does not exist in
+ /// C++.
+ NamedDecl **DeclsInPrototype;
+ };
+
+ /// If HasTrailingReturnType is true, this is the trailing return
+ /// type specified.
+ UnionParsedType TrailingReturnType;
+
+ /// If HasTrailingReturnType is true, this is the location of the trailing
+ /// return type.
+ SourceLocation TrailingReturnTypeLoc;
+
+ /// Reset the parameter list to having zero parameters.
+ ///
+ /// This is used in various places for error recovery.
+ void freeParams() {
+ for (unsigned I = 0; I < NumParams; ++I)
+ Params[I].DefaultArgTokens.reset();
+ if (DeleteParams) {
+ delete[] Params;
+ DeleteParams = false;
+ }
+ NumParams = 0;
+ }
+
+ void destroy() {
+ freeParams();
+ delete QualAttrFactory;
+ delete MethodQualifiers;
+ switch (getExceptionSpecType()) {
+ default:
+ break;
+ case EST_Dynamic:
+ delete[] Exceptions;
+ break;
+ case EST_Unparsed:
+ delete ExceptionSpecTokens;
+ break;
+ case EST_None:
+ if (NumExceptionsOrDecls != 0)
+ delete[] DeclsInPrototype;
+ break;
+ }
+ }
+
+ DeclSpec &getOrCreateMethodQualifiers() {
+ if (!MethodQualifiers) {
+ QualAttrFactory = new AttributeFactory();
+ MethodQualifiers = new DeclSpec(*QualAttrFactory);
+ }
+ return *MethodQualifiers;
+ }
+
+ /// isKNRPrototype - Return true if this is a K&R style identifier list,
+ /// like "void foo(a,b,c)". In a function definition, this will be followed
+ /// by the parameter type definitions.
+ bool isKNRPrototype() const { return !hasPrototype && NumParams != 0; }
+
+ SourceLocation getLParenLoc() const { return LParenLoc; }
+
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ SourceLocation getExceptionSpecLocBeg() const {
+ return ExceptionSpecLocBeg;
+ }
+
+ SourceLocation getExceptionSpecLocEnd() const {
+ return ExceptionSpecLocEnd;
+ }
+
+ SourceRange getExceptionSpecRange() const {
+ return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd());
+ }
+
+ /// Retrieve the location of the ref-qualifier, if any.
+ SourceLocation getRefQualifierLoc() const { return RefQualifierLoc; }
+
+ /// Retrieve the location of the 'const' qualifier.
+ SourceLocation getConstQualifierLoc() const {
+ assert(MethodQualifiers);
+ return MethodQualifiers->getConstSpecLoc();
+ }
+
+ /// Retrieve the location of the 'volatile' qualifier.
+ SourceLocation getVolatileQualifierLoc() const {
+ assert(MethodQualifiers);
+ return MethodQualifiers->getVolatileSpecLoc();
+ }
+
+ /// Retrieve the location of the 'restrict' qualifier.
+ SourceLocation getRestrictQualifierLoc() const {
+ assert(MethodQualifiers);
+ return MethodQualifiers->getRestrictSpecLoc();
+ }
+
+ /// Retrieve the location of the 'mutable' qualifier, if any.
+ SourceLocation getMutableLoc() const { return MutableLoc; }
+
+ /// Determine whether this function declaration contains a
+ /// ref-qualifier.
+ bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); }
+
+ /// Determine whether this lambda-declarator contains a 'mutable'
+ /// qualifier.
+ bool hasMutableQualifier() const { return getMutableLoc().isValid(); }
+
+ /// Determine whether this method has qualifiers.
+ bool hasMethodTypeQualifiers() const {
+ return MethodQualifiers && (MethodQualifiers->getTypeQualifiers() ||
+ MethodQualifiers->getAttributes().size());
+ }
+
+ /// Get the type of exception specification this function has.
+ ExceptionSpecificationType getExceptionSpecType() const {
+ return static_cast<ExceptionSpecificationType>(ExceptionSpecType);
+ }
+
+ /// Get the number of dynamic exception specifications.
+ unsigned getNumExceptions() const {
+ assert(ExceptionSpecType != EST_None);
+ return NumExceptionsOrDecls;
+ }
+
+ /// Get the non-parameter decls defined within this function
+ /// prototype. Typically these are tag declarations.
+ ArrayRef<NamedDecl *> getDeclsInPrototype() const {
+ assert(ExceptionSpecType == EST_None);
+ return llvm::ArrayRef(DeclsInPrototype, NumExceptionsOrDecls);
+ }
+
+ /// Determine whether this function declarator had a
+ /// trailing-return-type.
+ bool hasTrailingReturnType() const { return HasTrailingReturnType; }
+
+ /// Get the trailing-return-type for this function declarator.
+ ParsedType getTrailingReturnType() const {
+ assert(HasTrailingReturnType);
+ return TrailingReturnType;
+ }
+
+ /// Get the trailing-return-type location for this function declarator.
+ SourceLocation getTrailingReturnTypeLoc() const {
+ assert(HasTrailingReturnType);
+ return TrailingReturnTypeLoc;
+ }
+ };
+
+ struct BlockPointerTypeInfo {
+ /// For now, sema will catch these as invalid.
+ /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic.
+ unsigned TypeQuals : 5;
+
+ void destroy() {
+ }
+ };
+
+ struct MemberPointerTypeInfo {
+ /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic.
+ unsigned TypeQuals : 5;
+ /// Location of the '*' token.
+ SourceLocation StarLoc;
+ // CXXScopeSpec has a constructor, so it can't be a direct member.
+ // So we need some pointer-aligned storage and a bit of trickery.
+ alignas(CXXScopeSpec) char ScopeMem[sizeof(CXXScopeSpec)];
+ CXXScopeSpec &Scope() {
+ return *reinterpret_cast<CXXScopeSpec *>(ScopeMem);
+ }
+ const CXXScopeSpec &Scope() const {
+ return *reinterpret_cast<const CXXScopeSpec *>(ScopeMem);
+ }
+ void destroy() {
+ Scope().~CXXScopeSpec();
+ }
+ };
+
+ struct PipeTypeInfo {
+ /// The access writes.
+ unsigned AccessWrites : 3;
+
+ void destroy() {}
+ };
+
+ union {
+ PointerTypeInfo Ptr;
+ ReferenceTypeInfo Ref;
+ ArrayTypeInfo Arr;
+ FunctionTypeInfo Fun;
+ BlockPointerTypeInfo Cls;
+ MemberPointerTypeInfo Mem;
+ PipeTypeInfo PipeInfo;
+ };
+
+ void destroy() {
+ switch (Kind) {
+ case DeclaratorChunk::Function: return Fun.destroy();
+ case DeclaratorChunk::Pointer: return Ptr.destroy();
+ case DeclaratorChunk::BlockPointer: return Cls.destroy();
+ case DeclaratorChunk::Reference: return Ref.destroy();
+ case DeclaratorChunk::Array: return Arr.destroy();
+ case DeclaratorChunk::MemberPointer: return Mem.destroy();
+ case DeclaratorChunk::Paren: return;
+ case DeclaratorChunk::Pipe: return PipeInfo.destroy();
+ }
+ }
+
+ /// If there are attributes applied to this declaratorchunk, return
+ /// them.
+ const ParsedAttributesView &getAttrs() const { return AttrList; }
+ ParsedAttributesView &getAttrs() { return AttrList; }
+
+ /// Return a DeclaratorChunk for a pointer.
+ static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc,
+ SourceLocation ConstQualLoc,
+ SourceLocation VolatileQualLoc,
+ SourceLocation RestrictQualLoc,
+ SourceLocation AtomicQualLoc,
+ SourceLocation UnalignedQualLoc) {
+ DeclaratorChunk I;
+ I.Kind = Pointer;
+ I.Loc = Loc;
+ new (&I.Ptr) PointerTypeInfo;
+ I.Ptr.TypeQuals = TypeQuals;
+ I.Ptr.ConstQualLoc = ConstQualLoc;
+ I.Ptr.VolatileQualLoc = VolatileQualLoc;
+ I.Ptr.RestrictQualLoc = RestrictQualLoc;
+ I.Ptr.AtomicQualLoc = AtomicQualLoc;
+ I.Ptr.UnalignedQualLoc = UnalignedQualLoc;
+ return I;
+ }
+
+ /// Return a DeclaratorChunk for a reference.
+ static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc,
+ bool lvalue) {
+ DeclaratorChunk I;
+ I.Kind = Reference;
+ I.Loc = Loc;
+ I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0;
+ I.Ref.LValueRef = lvalue;
+ return I;
+ }
+
+ /// Return a DeclaratorChunk for an array.
+ static DeclaratorChunk getArray(unsigned TypeQuals,
+ bool isStatic, bool isStar, Expr *NumElts,
+ SourceLocation LBLoc, SourceLocation RBLoc) {
+ DeclaratorChunk I;
+ I.Kind = Array;
+ I.Loc = LBLoc;
+ I.EndLoc = RBLoc;
+ I.Arr.TypeQuals = TypeQuals;
+ I.Arr.hasStatic = isStatic;
+ I.Arr.isStar = isStar;
+ I.Arr.NumElts = NumElts;
+ return I;
+ }
+
+ /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
+ /// "TheDeclarator" is the declarator that this will be added to.
+ static DeclaratorChunk getFunction(bool HasProto,
+ bool IsAmbiguous,
+ SourceLocation LParenLoc,
+ ParamInfo *Params, unsigned NumParams,
+ SourceLocation EllipsisLoc,
+ SourceLocation RParenLoc,
+ bool RefQualifierIsLvalueRef,
+ SourceLocation RefQualifierLoc,
+ SourceLocation MutableLoc,
+ ExceptionSpecificationType ESpecType,
+ SourceRange ESpecRange,
+ ParsedType *Exceptions,
+ SourceRange *ExceptionRanges,
+ unsigned NumExceptions,
+ Expr *NoexceptExpr,
+ CachedTokens *ExceptionSpecTokens,
+ ArrayRef<NamedDecl *> DeclsInPrototype,
+ SourceLocation LocalRangeBegin,
+ SourceLocation LocalRangeEnd,
+ Declarator &TheDeclarator,
+ TypeResult TrailingReturnType =
+ TypeResult(),
+ SourceLocation TrailingReturnTypeLoc =
+ SourceLocation(),
+ DeclSpec *MethodQualifiers = nullptr);
+
+ /// Return a DeclaratorChunk for a block.
+ static DeclaratorChunk getBlockPointer(unsigned TypeQuals,
+ SourceLocation Loc) {
+ DeclaratorChunk I;
+ I.Kind = BlockPointer;
+ I.Loc = Loc;
+ I.Cls.TypeQuals = TypeQuals;
+ return I;
+ }
+
+ /// Return a DeclaratorChunk for a block.
+ static DeclaratorChunk getPipe(unsigned TypeQuals,
+ SourceLocation Loc) {
+ DeclaratorChunk I;
+ I.Kind = Pipe;
+ I.Loc = Loc;
+ I.Cls.TypeQuals = TypeQuals;
+ return I;
+ }
+
+ static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
+ unsigned TypeQuals,
+ SourceLocation StarLoc,
+ SourceLocation EndLoc) {
+ DeclaratorChunk I;
+ I.Kind = MemberPointer;
+ I.Loc = SS.getBeginLoc();
+ I.EndLoc = EndLoc;
+ new (&I.Mem) MemberPointerTypeInfo;
+ I.Mem.StarLoc = StarLoc;
+ I.Mem.TypeQuals = TypeQuals;
+ new (I.Mem.ScopeMem) CXXScopeSpec(SS);
+ return I;
+ }
+
+ /// Return a DeclaratorChunk for a paren.
+ static DeclaratorChunk getParen(SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ DeclaratorChunk I;
+ I.Kind = Paren;
+ I.Loc = LParenLoc;
+ I.EndLoc = RParenLoc;
+ return I;
+ }
+
+ bool isParen() const {
+ return Kind == Paren;
+ }
+};
+
+/// A parsed C++17 decomposition declarator of the form
+/// '[' identifier-list ']'
+class DecompositionDeclarator {
+public:
+ struct Binding {
+ IdentifierInfo *Name;
+ SourceLocation NameLoc;
+ };
+
+private:
+ /// The locations of the '[' and ']' tokens.
+ SourceLocation LSquareLoc, RSquareLoc;
+
+ /// The bindings.
+ Binding *Bindings;
+ unsigned NumBindings : 31;
+ unsigned DeleteBindings : 1;
+
+ friend class Declarator;
+
+public:
+ DecompositionDeclarator()
+ : Bindings(nullptr), NumBindings(0), DeleteBindings(false) {}
+ DecompositionDeclarator(const DecompositionDeclarator &G) = delete;
+ DecompositionDeclarator &operator=(const DecompositionDeclarator &G) = delete;
+ ~DecompositionDeclarator() {
+ if (DeleteBindings)
+ delete[] Bindings;
+ }
+
+ void clear() {
+ LSquareLoc = RSquareLoc = SourceLocation();
+ if (DeleteBindings)
+ delete[] Bindings;
+ Bindings = nullptr;
+ NumBindings = 0;
+ DeleteBindings = false;
+ }
+
+ ArrayRef<Binding> bindings() const {
+ return llvm::ArrayRef(Bindings, NumBindings);
+ }
+
+ bool isSet() const { return LSquareLoc.isValid(); }
+
+ SourceLocation getLSquareLoc() const { return LSquareLoc; }
+ SourceLocation getRSquareLoc() const { return RSquareLoc; }
+ SourceRange getSourceRange() const {
+ return SourceRange(LSquareLoc, RSquareLoc);
+ }
+};
+
+/// Described the kind of function definition (if any) provided for
+/// a function.
+enum class FunctionDefinitionKind {
+ Declaration,
+ Definition,
+ Defaulted,
+ Deleted
+};
+
+enum class DeclaratorContext {
+ File, // File scope declaration.
+ Prototype, // Within a function prototype.
+ ObjCResult, // An ObjC method result type.
+ ObjCParameter, // An ObjC method parameter type.
+ KNRTypeList, // K&R type definition list for formals.
+ TypeName, // Abstract declarator for types.
+ FunctionalCast, // Type in a C++ functional cast expression.
+ Member, // Struct/Union field.
+ Block, // Declaration within a block in a function.
+ ForInit, // Declaration within first part of a for loop.
+ SelectionInit, // Declaration within optional init stmt of if/switch.
+ Condition, // Condition declaration in a C++ if/switch/while/for.
+ TemplateParam, // Within a template parameter list.
+ CXXNew, // C++ new-expression.
+ CXXCatch, // C++ catch exception-declaration
+ ObjCCatch, // Objective-C catch exception-declaration
+ BlockLiteral, // Block literal declarator.
+ LambdaExpr, // Lambda-expression declarator.
+ LambdaExprParameter, // Lambda-expression parameter declarator.
+ ConversionId, // C++ conversion-type-id.
+ TrailingReturn, // C++11 trailing-type-specifier.
+ TrailingReturnVar, // C++11 trailing-type-specifier for variable.
+ TemplateArg, // Any template argument (in template argument list).
+ TemplateTypeArg, // Template type argument (in default argument).
+ AliasDecl, // C++11 alias-declaration.
+ AliasTemplate, // C++11 alias-declaration template.
+ RequiresExpr, // C++2a requires-expression.
+ Association // C11 _Generic selection expression association.
+};
+
+// Describes whether the current context is a context where an implicit
+// typename is allowed (C++2a [temp.res]p5]).
+enum class ImplicitTypenameContext {
+ No,
+ Yes,
+};
+
+/// Information about one declarator, including the parsed type
+/// information and the identifier.
+///
+/// When the declarator is fully formed, this is turned into the appropriate
+/// Decl object.
+///
+/// Declarators come in two types: normal declarators and abstract declarators.
+/// Abstract declarators are used when parsing types, and don't have an
+/// identifier. Normal declarators do have ID's.
+///
+/// Instances of this class should be a transient object that lives on the
+/// stack, not objects that are allocated in large quantities on the heap.
+class Declarator {
+
+private:
+ const DeclSpec &DS;
+ CXXScopeSpec SS;
+ UnqualifiedId Name;
+ SourceRange Range;
+
+ /// Where we are parsing this declarator.
+ DeclaratorContext Context;
+
+ /// The C++17 structured binding, if any. This is an alternative to a Name.
+ DecompositionDeclarator BindingGroup;
+
+ /// DeclTypeInfo - This holds each type that the declarator includes as it is
+ /// parsed. This is pushed from the identifier out, which means that element
+ /// #0 will be the most closely bound to the identifier, and
+ /// DeclTypeInfo.back() will be the least closely bound.
+ SmallVector<DeclaratorChunk, 8> DeclTypeInfo;
+
+ /// InvalidType - Set by Sema::GetTypeForDeclarator().
+ unsigned InvalidType : 1;
+
+ /// GroupingParens - Set by Parser::ParseParenDeclarator().
+ unsigned GroupingParens : 1;
+
+ /// FunctionDefinition - Is this Declarator for a function or member
+ /// definition and, if so, what kind?
+ ///
+ /// Actually a FunctionDefinitionKind.
+ unsigned FunctionDefinition : 2;
+
+ /// Is this Declarator a redeclaration?
+ unsigned Redeclaration : 1;
+
+ /// true if the declaration is preceded by \c __extension__.
+ unsigned Extension : 1;
+
+ /// Indicates whether this is an Objective-C instance variable.
+ unsigned ObjCIvar : 1;
+
+ /// Indicates whether this is an Objective-C 'weak' property.
+ unsigned ObjCWeakProperty : 1;
+
+ /// Indicates whether the InlineParams / InlineBindings storage has been used.
+ unsigned InlineStorageUsed : 1;
+
+ /// Indicates whether this declarator has an initializer.
+ unsigned HasInitializer : 1;
+
+ /// Attributes attached to the declarator.
+ ParsedAttributes Attrs;
+
+ /// Attributes attached to the declaration. See also documentation for the
+ /// corresponding constructor parameter.
+ const ParsedAttributesView &DeclarationAttrs;
+
+ /// The asm label, if specified.
+ Expr *AsmLabel;
+
+ /// \brief The constraint-expression specified by the trailing
+ /// requires-clause, or null if no such clause was specified.
+ Expr *TrailingRequiresClause;
+
+ /// If this declarator declares a template, its template parameter lists.
+ ArrayRef<TemplateParameterList *> TemplateParameterLists;
+
+ /// If the declarator declares an abbreviated function template, the innermost
+ /// template parameter list containing the invented and explicit template
+ /// parameters (if any).
+ TemplateParameterList *InventedTemplateParameterList;
+
+#ifndef _MSC_VER
+ union {
+#endif
+ /// InlineParams - This is a local array used for the first function decl
+ /// chunk to avoid going to the heap for the common case when we have one
+ /// function chunk in the declarator.
+ DeclaratorChunk::ParamInfo InlineParams[16];
+ DecompositionDeclarator::Binding InlineBindings[16];
+#ifndef _MSC_VER
+ };
+#endif
+
+ /// If this is the second or subsequent declarator in this declaration,
+ /// the location of the comma before this declarator.
+ SourceLocation CommaLoc;
+
+ /// If provided, the source location of the ellipsis used to describe
+ /// this declarator as a parameter pack.
+ SourceLocation EllipsisLoc;
+
+ friend struct DeclaratorChunk;
+
+public:
+ /// `DS` and `DeclarationAttrs` must outlive the `Declarator`. In particular,
+ /// take care not to pass temporary objects for these parameters.
+ ///
+ /// `DeclarationAttrs` contains [[]] attributes from the
+ /// attribute-specifier-seq at the beginning of a declaration, which appertain
+ /// to the declared entity itself. Attributes with other syntax (e.g. GNU)
+ /// should not be placed in this attribute list; if they occur at the
+ /// beginning of a declaration, they apply to the `DeclSpec` and should be
+ /// attached to that instead.
+ ///
+ /// Here is an example of an attribute associated with a declaration:
+ ///
+ /// [[deprecated]] int x, y;
+ ///
+ /// This attribute appertains to all of the entities declared in the
+ /// declaration, i.e. `x` and `y` in this case.
+ Declarator(const DeclSpec &DS, const ParsedAttributesView &DeclarationAttrs,
+ DeclaratorContext C)
+ : DS(DS), Range(DS.getSourceRange()), Context(C),
+ InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
+ GroupingParens(false), FunctionDefinition(static_cast<unsigned>(
+ FunctionDefinitionKind::Declaration)),
+ Redeclaration(false), Extension(false), ObjCIvar(false),
+ ObjCWeakProperty(false), InlineStorageUsed(false),
+ HasInitializer(false), Attrs(DS.getAttributePool().getFactory()),
+ DeclarationAttrs(DeclarationAttrs), AsmLabel(nullptr),
+ TrailingRequiresClause(nullptr),
+ InventedTemplateParameterList(nullptr) {
+ assert(llvm::all_of(DeclarationAttrs,
+ [](const ParsedAttr &AL) {
+ return AL.isStandardAttributeSyntax();
+ }) &&
+ "DeclarationAttrs may only contain [[]] attributes");
+ }
+
+ ~Declarator() {
+ clear();
+ }
+ /// getDeclSpec - Return the declaration-specifier that this declarator was
+ /// declared with.
+ const DeclSpec &getDeclSpec() const { return DS; }
+
+ /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This
+ /// should be used with extreme care: declspecs can often be shared between
+ /// multiple declarators, so mutating the DeclSpec affects all of the
+ /// Declarators. This should only be done when the declspec is known to not
+ /// be shared or when in error recovery etc.
+ DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); }
+
+ AttributePool &getAttributePool() const {
+ return Attrs.getPool();
+ }
+
+ /// getCXXScopeSpec - Return the C++ scope specifier (global scope or
+ /// nested-name-specifier) that is part of the declarator-id.
+ const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
+ CXXScopeSpec &getCXXScopeSpec() { return SS; }
+
+ /// Retrieve the name specified by this declarator.
+ UnqualifiedId &getName() { return Name; }
+
+ const DecompositionDeclarator &getDecompositionDeclarator() const {
+ return BindingGroup;
+ }
+
+ DeclaratorContext getContext() const { return Context; }
+
+ bool isPrototypeContext() const {
+ return (Context == DeclaratorContext::Prototype ||
+ Context == DeclaratorContext::ObjCParameter ||
+ Context == DeclaratorContext::ObjCResult ||
+ Context == DeclaratorContext::LambdaExprParameter);
+ }
+
+ /// Get the source range that spans this declarator.
+ SourceRange getSourceRange() const LLVM_READONLY { return Range; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); }
+
+ void SetSourceRange(SourceRange R) { Range = R; }
+ /// SetRangeBegin - Set the start of the source range to Loc, unless it's
+ /// invalid.
+ void SetRangeBegin(SourceLocation Loc) {
+ if (!Loc.isInvalid())
+ Range.setBegin(Loc);
+ }
+ /// SetRangeEnd - Set the end of the source range to Loc, unless it's invalid.
+ void SetRangeEnd(SourceLocation Loc) {
+ if (!Loc.isInvalid())
+ Range.setEnd(Loc);
+ }
+ /// ExtendWithDeclSpec - Extend the declarator source range to include the
+ /// given declspec, unless its location is invalid. Adopts the range start if
+ /// the current range start is invalid.
+ void ExtendWithDeclSpec(const DeclSpec &DS) {
+ SourceRange SR = DS.getSourceRange();
+ if (Range.getBegin().isInvalid())
+ Range.setBegin(SR.getBegin());
+ if (!SR.getEnd().isInvalid())
+ Range.setEnd(SR.getEnd());
+ }
+
+ /// Reset the contents of this Declarator.
+ void clear() {
+ SS.clear();
+ Name.clear();
+ Range = DS.getSourceRange();
+ BindingGroup.clear();
+
+ for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
+ DeclTypeInfo[i].destroy();
+ DeclTypeInfo.clear();
+ Attrs.clear();
+ AsmLabel = nullptr;
+ InlineStorageUsed = false;
+ HasInitializer = false;
+ ObjCIvar = false;
+ ObjCWeakProperty = false;
+ CommaLoc = SourceLocation();
+ EllipsisLoc = SourceLocation();
+ }
+
+ /// mayOmitIdentifier - Return true if the identifier is either optional or
+ /// not allowed. This is true for typenames, prototypes, and template
+ /// parameter lists.
+ bool mayOmitIdentifier() const {
+ switch (Context) {
+ case DeclaratorContext::File:
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::Member:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::Condition:
+ return false;
+
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
+ case DeclaratorContext::RequiresExpr:
+ case DeclaratorContext::Association:
+ return true;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// mayHaveIdentifier - Return true if the identifier is either optional or
+ /// required. This is true for normal declarators and prototypes, but not
+ /// typenames.
+ bool mayHaveIdentifier() const {
+ switch (Context) {
+ case DeclaratorContext::File:
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::Member:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::Condition:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::RequiresExpr:
+ return true;
+
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
+ case DeclaratorContext::Association:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// Return true if the context permits a C++17 decomposition declarator.
+ bool mayHaveDecompositionDeclarator() const {
+ switch (Context) {
+ case DeclaratorContext::File:
+ // FIXME: It's not clear that the proposal meant to allow file-scope
+ // structured bindings, but it does.
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::Condition:
+ return true;
+
+ case DeclaratorContext::Member:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::RequiresExpr:
+ // Maybe one day...
+ return false;
+
+ // These contexts don't allow any kind of non-abstract declarator.
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
+ case DeclaratorContext::Association:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be
+ /// followed by a C++ direct initializer, e.g. "int x(1);".
+ bool mayBeFollowedByCXXDirectInit() const {
+ if (hasGroupingParens()) return false;
+
+ if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ return false;
+
+ if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern &&
+ Context != DeclaratorContext::File)
+ return false;
+
+ // Special names can't have direct initializers.
+ if (Name.getKind() != UnqualifiedIdKind::IK_Identifier)
+ return false;
+
+ switch (Context) {
+ case DeclaratorContext::File:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::TrailingReturnVar:
+ return true;
+
+ case DeclaratorContext::Condition:
+ // This may not be followed by a direct initializer, but it can't be a
+ // function declaration either, and we'd prefer to perform a tentative
+ // parse in order to produce the right diagnostic.
+ return true;
+
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::Member:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast: // FIXME
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::RequiresExpr:
+ case DeclaratorContext::Association:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// isPastIdentifier - Return true if we have parsed beyond the point where
+ /// the name would appear. (This may happen even if we haven't actually parsed
+ /// a name, perhaps because this context doesn't require one.)
+ bool isPastIdentifier() const { return Name.isValid(); }
+
+ /// hasName - Whether this declarator has a name, which might be an
+ /// identifier (accessible via getIdentifier()) or some kind of
+ /// special C++ name (constructor, destructor, etc.), or a structured
+ /// binding (which is not exactly a name, but occupies the same position).
+ bool hasName() const {
+ return Name.getKind() != UnqualifiedIdKind::IK_Identifier ||
+ Name.Identifier || isDecompositionDeclarator();
+ }
+
+ /// Return whether this declarator is a decomposition declarator.
+ bool isDecompositionDeclarator() const {
+ return BindingGroup.isSet();
+ }
+
+ IdentifierInfo *getIdentifier() const {
+ if (Name.getKind() == UnqualifiedIdKind::IK_Identifier)
+ return Name.Identifier;
+
+ return nullptr;
+ }
+ SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
+
+ /// Set the name of this declarator to be the given identifier.
+ void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
+ Name.setIdentifier(Id, IdLoc);
+ }
+
+ /// Set the decomposition bindings for this declarator.
+ void
+ setDecompositionBindings(SourceLocation LSquareLoc,
+ ArrayRef<DecompositionDeclarator::Binding> Bindings,
+ SourceLocation RSquareLoc);
+
+ /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
+ /// EndLoc, which should be the last token of the chunk.
+ /// This function takes attrs by R-Value reference because it takes ownership
+ /// of those attributes from the parameter.
+ void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs,
+ SourceLocation EndLoc) {
+ DeclTypeInfo.push_back(TI);
+ DeclTypeInfo.back().getAttrs().addAll(attrs.begin(), attrs.end());
+ getAttributePool().takeAllFrom(attrs.getPool());
+
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
+ /// EndLoc, which should be the last token of the chunk.
+ void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
+ DeclTypeInfo.push_back(TI);
+
+ if (!EndLoc.isInvalid())
+ SetRangeEnd(EndLoc);
+ }
+
+ /// Add a new innermost chunk to this declarator.
+ void AddInnermostTypeInfo(const DeclaratorChunk &TI) {
+ DeclTypeInfo.insert(DeclTypeInfo.begin(), TI);
+ }
+
+ /// Return the number of types applied to this declarator.
+ unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); }
+
+ /// Return the specified TypeInfo from this declarator. TypeInfo #0 is
+ /// closest to the identifier.
+ const DeclaratorChunk &getTypeObject(unsigned i) const {
+ assert(i < DeclTypeInfo.size() && "Invalid type chunk");
+ return DeclTypeInfo[i];
+ }
+ DeclaratorChunk &getTypeObject(unsigned i) {
+ assert(i < DeclTypeInfo.size() && "Invalid type chunk");
+ return DeclTypeInfo[i];
+ }
+
+ typedef SmallVectorImpl<DeclaratorChunk>::const_iterator type_object_iterator;
+ typedef llvm::iterator_range<type_object_iterator> type_object_range;
+
+ /// Returns the range of type objects, from the identifier outwards.
+ type_object_range type_objects() const {
+ return type_object_range(DeclTypeInfo.begin(), DeclTypeInfo.end());
+ }
+
+ void DropFirstTypeObject() {
+ assert(!DeclTypeInfo.empty() && "No type chunks to drop.");
+ DeclTypeInfo.front().destroy();
+ DeclTypeInfo.erase(DeclTypeInfo.begin());
+ }
+
+ /// Return the innermost (closest to the declarator) chunk of this
+ /// declarator that is not a parens chunk, or null if there are no
+ /// non-parens chunks.
+ const DeclaratorChunk *getInnermostNonParenChunk() const {
+ for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+ if (!DeclTypeInfo[i].isParen())
+ return &DeclTypeInfo[i];
+ }
+ return nullptr;
+ }
+
+ /// Return the outermost (furthest from the declarator) chunk of
+ /// this declarator that is not a parens chunk, or null if there are
+ /// no non-parens chunks.
+ const DeclaratorChunk *getOutermostNonParenChunk() const {
+ for (unsigned i = DeclTypeInfo.size(), i_end = 0; i != i_end; --i) {
+ if (!DeclTypeInfo[i-1].isParen())
+ return &DeclTypeInfo[i-1];
+ }
+ return nullptr;
+ }
+
+ /// isArrayOfUnknownBound - This method returns true if the declarator
+ /// is a declarator for an array of unknown bound (looking through
+ /// parentheses).
+ bool isArrayOfUnknownBound() const {
+ const DeclaratorChunk *chunk = getInnermostNonParenChunk();
+ return (chunk && chunk->Kind == DeclaratorChunk::Array &&
+ !chunk->Arr.NumElts);
+ }
+
+ /// isFunctionDeclarator - This method returns true if the declarator
+ /// is a function declarator (looking through parentheses).
+ /// If true is returned, then the reference type parameter idx is
+ /// assigned with the index of the declaration chunk.
+ bool isFunctionDeclarator(unsigned& idx) const {
+ for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
+ switch (DeclTypeInfo[i].Kind) {
+ case DeclaratorChunk::Function:
+ idx = i;
+ return true;
+ case DeclaratorChunk::Paren:
+ continue;
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ case DeclaratorChunk::Pipe:
+ return false;
+ }
+ llvm_unreachable("Invalid type chunk");
+ }
+ return false;
+ }
+
+ /// isFunctionDeclarator - Once this declarator is fully parsed and formed,
+ /// this method returns true if the identifier is a function declarator
+ /// (looking through parentheses).
+ bool isFunctionDeclarator() const {
+ unsigned index;
+ return isFunctionDeclarator(index);
+ }
+
+ /// getFunctionTypeInfo - Retrieves the function type info object
+ /// (looking through parentheses).
+ DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() {
+ assert(isFunctionDeclarator() && "Not a function declarator!");
+ unsigned index = 0;
+ isFunctionDeclarator(index);
+ return DeclTypeInfo[index].Fun;
+ }
+
+ /// getFunctionTypeInfo - Retrieves the function type info object
+ /// (looking through parentheses).
+ const DeclaratorChunk::FunctionTypeInfo &getFunctionTypeInfo() const {
+ return const_cast<Declarator*>(this)->getFunctionTypeInfo();
+ }
+
+ /// Determine whether the declaration that will be produced from
+ /// this declaration will be a function.
+ ///
+ /// A declaration can declare a function even if the declarator itself
+ /// isn't a function declarator, if the type specifier refers to a function
+ /// type. This routine checks for both cases.
+ bool isDeclarationOfFunction() const;
+
+ /// Return true if this declaration appears in a context where a
+ /// function declarator would be a function declaration.
+ bool isFunctionDeclarationContext() const {
+ if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ return false;
+
+ switch (Context) {
+ case DeclaratorContext::File:
+ case DeclaratorContext::Member:
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ return true;
+
+ case DeclaratorContext::Condition:
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::TypeName:
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TemplateArg:
+ case DeclaratorContext::TemplateTypeArg:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
+ case DeclaratorContext::RequiresExpr:
+ case DeclaratorContext::Association:
+ return false;
+ }
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// Determine whether this declaration appears in a context where an
+ /// expression could appear.
+ bool isExpressionContext() const {
+ switch (Context) {
+ case DeclaratorContext::File:
+ case DeclaratorContext::KNRTypeList:
+ case DeclaratorContext::Member:
+
+ // FIXME: sizeof(...) permits an expression.
+ case DeclaratorContext::TypeName:
+
+ case DeclaratorContext::FunctionalCast:
+ case DeclaratorContext::AliasDecl:
+ case DeclaratorContext::AliasTemplate:
+ case DeclaratorContext::Prototype:
+ case DeclaratorContext::LambdaExprParameter:
+ case DeclaratorContext::ObjCParameter:
+ case DeclaratorContext::ObjCResult:
+ case DeclaratorContext::TemplateParam:
+ case DeclaratorContext::CXXNew:
+ case DeclaratorContext::CXXCatch:
+ case DeclaratorContext::ObjCCatch:
+ case DeclaratorContext::BlockLiteral:
+ case DeclaratorContext::LambdaExpr:
+ case DeclaratorContext::ConversionId:
+ case DeclaratorContext::TrailingReturn:
+ case DeclaratorContext::TrailingReturnVar:
+ case DeclaratorContext::TemplateTypeArg:
+ case DeclaratorContext::RequiresExpr:
+ case DeclaratorContext::Association:
+ return false;
+
+ case DeclaratorContext::Block:
+ case DeclaratorContext::ForInit:
+ case DeclaratorContext::SelectionInit:
+ case DeclaratorContext::Condition:
+ case DeclaratorContext::TemplateArg:
+ return true;
+ }
+
+ llvm_unreachable("unknown context kind!");
+ }
+
+ /// Return true if a function declarator at this position would be a
+ /// function declaration.
+ bool isFunctionDeclaratorAFunctionDeclaration() const {
+ if (!isFunctionDeclarationContext())
+ return false;
+
+ for (unsigned I = 0, N = getNumTypeObjects(); I != N; ++I)
+ if (getTypeObject(I).Kind != DeclaratorChunk::Paren)
+ return false;
+
+ return true;
+ }
+
+ /// Determine whether a trailing return type was written (at any
+ /// level) within this declarator.
+ bool hasTrailingReturnType() const {
+ for (const auto &Chunk : type_objects())
+ if (Chunk.Kind == DeclaratorChunk::Function &&
+ Chunk.Fun.hasTrailingReturnType())
+ return true;
+ return false;
+ }
+ /// Get the trailing return type appearing (at any level) within this
+ /// declarator.
+ ParsedType getTrailingReturnType() const {
+ for (const auto &Chunk : type_objects())
+ if (Chunk.Kind == DeclaratorChunk::Function &&
+ Chunk.Fun.hasTrailingReturnType())
+ return Chunk.Fun.getTrailingReturnType();
+ return ParsedType();
+ }
+
+ /// \brief Sets a trailing requires clause for this declarator.
+ void setTrailingRequiresClause(Expr *TRC) {
+ TrailingRequiresClause = TRC;
+
+ SetRangeEnd(TRC->getEndLoc());
+ }
+
+ /// \brief Sets a trailing requires clause for this declarator.
+ Expr *getTrailingRequiresClause() {
+ return TrailingRequiresClause;
+ }
+
+ /// \brief Determine whether a trailing requires clause was written in this
+ /// declarator.
+ bool hasTrailingRequiresClause() const {
+ return TrailingRequiresClause != nullptr;
+ }
+
+ /// Sets the template parameter lists that preceded the declarator.
+ void setTemplateParameterLists(ArrayRef<TemplateParameterList *> TPLs) {
+ TemplateParameterLists = TPLs;
+ }
+
+ /// The template parameter lists that preceded the declarator.
+ ArrayRef<TemplateParameterList *> getTemplateParameterLists() const {
+ return TemplateParameterLists;
+ }
+
+ /// Sets the template parameter list generated from the explicit template
+ /// parameters along with any invented template parameters from
+ /// placeholder-typed parameters.
+ void setInventedTemplateParameterList(TemplateParameterList *Invented) {
+ InventedTemplateParameterList = Invented;
+ }
+
+ /// The template parameter list generated from the explicit template
+ /// parameters along with any invented template parameters from
+ /// placeholder-typed parameters, if there were any such parameters.
+ TemplateParameterList * getInventedTemplateParameterList() const {
+ return InventedTemplateParameterList;
+ }
+
+ /// takeAttributes - Takes attributes from the given parsed-attributes
+ /// set and add them to this declarator.
+ ///
+ /// These examples both add 3 attributes to "var":
+ /// short int var __attribute__((aligned(16),common,deprecated));
+ /// short int x, __attribute__((aligned(16)) var
+ /// __attribute__((common,deprecated));
+ ///
+ /// Also extends the range of the declarator.
+ void takeAttributes(ParsedAttributes &attrs) {
+ Attrs.takeAllFrom(attrs);
+
+ if (attrs.Range.getEnd().isValid())
+ SetRangeEnd(attrs.Range.getEnd());
+ }
+
+ const ParsedAttributes &getAttributes() const { return Attrs; }
+ ParsedAttributes &getAttributes() { return Attrs; }
+
+ const ParsedAttributesView &getDeclarationAttributes() const {
+ return DeclarationAttrs;
+ }
+
+ /// hasAttributes - do we contain any attributes?
+ bool hasAttributes() const {
+ if (!getAttributes().empty() || !getDeclarationAttributes().empty() ||
+ getDeclSpec().hasAttributes())
+ return true;
+ for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i)
+ if (!getTypeObject(i).getAttrs().empty())
+ return true;
+ return false;
+ }
+
+ /// Return a source range list of C++11 attributes associated
+ /// with the declarator.
+ void getCXX11AttributeRanges(SmallVectorImpl<SourceRange> &Ranges) {
+ for (const ParsedAttr &AL : Attrs)
+ if (AL.isCXX11Attribute())
+ Ranges.push_back(AL.getRange());
+ }
+
+ void setAsmLabel(Expr *E) { AsmLabel = E; }
+ Expr *getAsmLabel() const { return AsmLabel; }
+
+ void setExtension(bool Val = true) { Extension = Val; }
+ bool getExtension() const { return Extension; }
+
+ void setObjCIvar(bool Val = true) { ObjCIvar = Val; }
+ bool isObjCIvar() const { return ObjCIvar; }
+
+ void setObjCWeakProperty(bool Val = true) { ObjCWeakProperty = Val; }
+ bool isObjCWeakProperty() const { return ObjCWeakProperty; }
+
+ void setInvalidType(bool Val = true) { InvalidType = Val; }
+ bool isInvalidType() const {
+ return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
+ }
+
+ void setGroupingParens(bool flag) { GroupingParens = flag; }
+ bool hasGroupingParens() const { return GroupingParens; }
+
+ bool isFirstDeclarator() const { return !CommaLoc.isValid(); }
+ SourceLocation getCommaLoc() const { return CommaLoc; }
+ void setCommaLoc(SourceLocation CL) { CommaLoc = CL; }
+
+ bool hasEllipsis() const { return EllipsisLoc.isValid(); }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+ void setEllipsisLoc(SourceLocation EL) { EllipsisLoc = EL; }
+
+ void setFunctionDefinitionKind(FunctionDefinitionKind Val) {
+ FunctionDefinition = static_cast<unsigned>(Val);
+ }
+
+ bool isFunctionDefinition() const {
+ return getFunctionDefinitionKind() != FunctionDefinitionKind::Declaration;
+ }
+
+ FunctionDefinitionKind getFunctionDefinitionKind() const {
+ return (FunctionDefinitionKind)FunctionDefinition;
+ }
+
+ void setHasInitializer(bool Val = true) { HasInitializer = Val; }
+ bool hasInitializer() const { return HasInitializer; }
+
+ /// Returns true if this declares a real member and not a friend.
+ bool isFirstDeclarationOfMember() {
+ return getContext() == DeclaratorContext::Member &&
+ !getDeclSpec().isFriendSpecified();
+ }
+
+ /// Returns true if this declares a static member. This cannot be called on a
+ /// declarator outside of a MemberContext because we won't know until
+ /// redeclaration time if the decl is static.
+ bool isStaticMember();
+
+ /// Returns true if this declares a constructor or a destructor.
+ bool isCtorOrDtor();
+
+ void setRedeclaration(bool Val) { Redeclaration = Val; }
+ bool isRedeclaration() const { return Redeclaration; }
+};
+
+/// This little struct is used to capture information about
+/// structure field declarators, which is basically just a bitfield size.
+struct FieldDeclarator {
+ Declarator D;
+ Expr *BitfieldSize;
+ explicit FieldDeclarator(const DeclSpec &DS,
+ const ParsedAttributes &DeclarationAttrs)
+ : D(DS, DeclarationAttrs, DeclaratorContext::Member),
+ BitfieldSize(nullptr) {}
+};
+
+/// Represents a C++11 virt-specifier-seq.
+class VirtSpecifiers {
+public:
+ enum Specifier {
+ VS_None = 0,
+ VS_Override = 1,
+ VS_Final = 2,
+ VS_Sealed = 4,
+ // Represents the __final keyword, which is legal for gcc in pre-C++11 mode.
+ VS_GNU_Final = 8,
+ VS_Abstract = 16
+ };
+
+ VirtSpecifiers() : Specifiers(0), LastSpecifier(VS_None) { }
+
+ bool SetSpecifier(Specifier VS, SourceLocation Loc,
+ const char *&PrevSpec);
+
+ bool isUnset() const { return Specifiers == 0; }
+
+ bool isOverrideSpecified() const { return Specifiers & VS_Override; }
+ SourceLocation getOverrideLoc() const { return VS_overrideLoc; }
+
+ bool isFinalSpecified() const { return Specifiers & (VS_Final | VS_Sealed | VS_GNU_Final); }
+ bool isFinalSpelledSealed() const { return Specifiers & VS_Sealed; }
+ SourceLocation getFinalLoc() const { return VS_finalLoc; }
+ SourceLocation getAbstractLoc() const { return VS_abstractLoc; }
+
+ void clear() { Specifiers = 0; }
+
+ static const char *getSpecifierName(Specifier VS);
+
+ SourceLocation getFirstLocation() const { return FirstLocation; }
+ SourceLocation getLastLocation() const { return LastLocation; }
+ Specifier getLastSpecifier() const { return LastSpecifier; }
+
+private:
+ unsigned Specifiers;
+ Specifier LastSpecifier;
+
+ SourceLocation VS_overrideLoc, VS_finalLoc, VS_abstractLoc;
+ SourceLocation FirstLocation;
+ SourceLocation LastLocation;
+};
+
+enum class LambdaCaptureInitKind {
+ NoInit, //!< [a]
+ CopyInit, //!< [a = b], [a = {b}]
+ DirectInit, //!< [a(b)]
+ ListInit //!< [a{b}]
+};
+
+/// Represents a complete lambda introducer.
+struct LambdaIntroducer {
+ /// An individual capture in a lambda introducer.
+ struct LambdaCapture {
+ LambdaCaptureKind Kind;
+ SourceLocation Loc;
+ IdentifierInfo *Id;
+ SourceLocation EllipsisLoc;
+ LambdaCaptureInitKind InitKind;
+ ExprResult Init;
+ ParsedType InitCaptureType;
+ SourceRange ExplicitRange;
+
+ LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc,
+ IdentifierInfo *Id, SourceLocation EllipsisLoc,
+ LambdaCaptureInitKind InitKind, ExprResult Init,
+ ParsedType InitCaptureType,
+ SourceRange ExplicitRange)
+ : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc),
+ InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType),
+ ExplicitRange(ExplicitRange) {}
+ };
+
+ SourceRange Range;
+ SourceLocation DefaultLoc;
+ LambdaCaptureDefault Default;
+ SmallVector<LambdaCapture, 4> Captures;
+
+ LambdaIntroducer()
+ : Default(LCD_None) {}
+
+ bool hasLambdaCapture() const {
+ return Captures.size() > 0 || Default != LCD_None;
+ }
+
+ /// Append a capture in a lambda introducer.
+ void addCapture(LambdaCaptureKind Kind,
+ SourceLocation Loc,
+ IdentifierInfo* Id,
+ SourceLocation EllipsisLoc,
+ LambdaCaptureInitKind InitKind,
+ ExprResult Init,
+ ParsedType InitCaptureType,
+ SourceRange ExplicitRange) {
+ Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init,
+ InitCaptureType, ExplicitRange));
+ }
+};
+
+struct InventedTemplateParameterInfo {
+ /// The number of parameters in the template parameter list that were
+ /// explicitly specified by the user, as opposed to being invented by use
+ /// of an auto parameter.
+ unsigned NumExplicitTemplateParams = 0;
+
+ /// If this is a generic lambda or abbreviated function template, use this
+ /// as the depth of each 'auto' parameter, during initial AST construction.
+ unsigned AutoTemplateParameterDepth = 0;
+
+ /// Store the list of the template parameters for a generic lambda or an
+ /// abbreviated function template.
+ /// If this is a generic lambda or abbreviated function template, this holds
+ /// the explicit template parameters followed by the auto parameters
+ /// converted into TemplateTypeParmDecls.
+ /// It can be used to construct the generic lambda or abbreviated template's
+ /// template parameter list during initial AST construction.
+ SmallVector<NamedDecl*, 4> TemplateParams;
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_DECLSPEC_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/DelayedDiagnostic.h b/contrib/libs/clang16/include/clang/Sema/DelayedDiagnostic.h
new file mode 100644
index 0000000000..dd6b1ca0fd
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/DelayedDiagnostic.h
@@ -0,0 +1,343 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- DelayedDiagnostic.h - Delayed declarator diagnostics -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// Defines the classes clang::DelayedDiagnostic and
+/// clang::AccessedEntity.
+///
+/// DelayedDiangostic is used to record diagnostics that are being
+/// conditionally produced during declarator parsing. Certain kinds of
+/// diagnostics -- notably deprecation and access control -- are suppressed
+/// based on semantic properties of the parsed declaration that aren't known
+/// until it is fully parsed.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
+#define LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
+
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstddef>
+#include <utility>
+
+namespace clang {
+
+class ObjCInterfaceDecl;
+class ObjCPropertyDecl;
+
+namespace sema {
+
+/// A declaration being accessed, together with information about how
+/// it was accessed.
+class AccessedEntity {
+public:
+ /// A member declaration found through lookup. The target is the
+ /// member.
+ enum MemberNonce { Member };
+
+ /// A hierarchy (base-to-derived or derived-to-base) conversion.
+ /// The target is the base class.
+ enum BaseNonce { Base };
+
+ AccessedEntity(PartialDiagnostic::DiagStorageAllocator &Allocator,
+ MemberNonce _, CXXRecordDecl *NamingClass,
+ DeclAccessPair FoundDecl, QualType BaseObjectType)
+ : Access(FoundDecl.getAccess()), IsMember(true),
+ Target(FoundDecl.getDecl()), NamingClass(NamingClass),
+ BaseObjectType(BaseObjectType), Diag(0, Allocator) {}
+
+ AccessedEntity(PartialDiagnostic::DiagStorageAllocator &Allocator,
+ BaseNonce _, CXXRecordDecl *BaseClass,
+ CXXRecordDecl *DerivedClass, AccessSpecifier Access)
+ : Access(Access), IsMember(false), Target(BaseClass),
+ NamingClass(DerivedClass), Diag(0, Allocator) {}
+
+ bool isMemberAccess() const { return IsMember; }
+
+ bool isQuiet() const { return Diag.getDiagID() == 0; }
+
+ AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
+
+ // These apply to member decls...
+ NamedDecl *getTargetDecl() const { return Target; }
+ CXXRecordDecl *getNamingClass() const { return NamingClass; }
+
+ // ...and these apply to hierarchy conversions.
+ CXXRecordDecl *getBaseClass() const {
+ assert(!IsMember); return cast<CXXRecordDecl>(Target);
+ }
+ CXXRecordDecl *getDerivedClass() const { return NamingClass; }
+
+ /// Retrieves the base object type, important when accessing
+ /// an instance member.
+ QualType getBaseObjectType() const { return BaseObjectType; }
+
+ /// Sets a diagnostic to be performed. The diagnostic is given
+ /// four (additional) arguments:
+ /// %0 - 0 if the entity was private, 1 if protected
+ /// %1 - the DeclarationName of the entity
+ /// %2 - the TypeDecl type of the naming class
+ /// %3 - the TypeDecl type of the declaring class
+ void setDiag(const PartialDiagnostic &PDiag) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ Diag = PDiag;
+ }
+ PartialDiagnostic &setDiag(unsigned DiagID) {
+ assert(isQuiet() && "partial diagnostic already defined");
+ assert(DiagID && "creating null diagnostic");
+ Diag.Reset(DiagID);
+ return Diag;
+ }
+ const PartialDiagnostic &getDiag() const {
+ return Diag;
+ }
+
+private:
+ unsigned Access : 2;
+ unsigned IsMember : 1;
+ NamedDecl *Target;
+ CXXRecordDecl *NamingClass;
+ QualType BaseObjectType;
+ PartialDiagnostic Diag;
+};
+
+/// A diagnostic message which has been conditionally emitted pending
+/// the complete parsing of the current declaration.
+class DelayedDiagnostic {
+public:
+ enum DDKind : unsigned char { Availability, Access, ForbiddenType };
+
+ DDKind Kind;
+ bool Triggered;
+
+ SourceLocation Loc;
+
+ void Destroy();
+
+ static DelayedDiagnostic makeAvailability(AvailabilityResult AR,
+ ArrayRef<SourceLocation> Locs,
+ const NamedDecl *ReferringDecl,
+ const NamedDecl *OffendingDecl,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ const ObjCPropertyDecl *ObjCProperty,
+ StringRef Msg,
+ bool ObjCPropertyAccess);
+
+ static DelayedDiagnostic makeAccess(SourceLocation Loc,
+ const AccessedEntity &Entity) {
+ DelayedDiagnostic DD;
+ DD.Kind = Access;
+ DD.Triggered = false;
+ DD.Loc = Loc;
+ new (&DD.getAccessData()) AccessedEntity(Entity);
+ return DD;
+ }
+
+ static DelayedDiagnostic makeForbiddenType(SourceLocation loc,
+ unsigned diagnostic,
+ QualType type,
+ unsigned argument) {
+ DelayedDiagnostic DD;
+ DD.Kind = ForbiddenType;
+ DD.Triggered = false;
+ DD.Loc = loc;
+ DD.ForbiddenTypeData.Diagnostic = diagnostic;
+ DD.ForbiddenTypeData.OperandType = type.getAsOpaquePtr();
+ DD.ForbiddenTypeData.Argument = argument;
+ return DD;
+ }
+
+ AccessedEntity &getAccessData() {
+ assert(Kind == Access && "Not an access diagnostic.");
+ return *reinterpret_cast<AccessedEntity*>(AccessData);
+ }
+ const AccessedEntity &getAccessData() const {
+ assert(Kind == Access && "Not an access diagnostic.");
+ return *reinterpret_cast<const AccessedEntity*>(AccessData);
+ }
+
+ const NamedDecl *getAvailabilityReferringDecl() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return AvailabilityData.ReferringDecl;
+ }
+
+ const NamedDecl *getAvailabilityOffendingDecl() const {
+ return AvailabilityData.OffendingDecl;
+ }
+
+ StringRef getAvailabilityMessage() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return StringRef(AvailabilityData.Message, AvailabilityData.MessageLen);
+ }
+
+ ArrayRef<SourceLocation> getAvailabilitySelectorLocs() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return llvm::ArrayRef(AvailabilityData.SelectorLocs,
+ AvailabilityData.NumSelectorLocs);
+ }
+
+ AvailabilityResult getAvailabilityResult() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return AvailabilityData.AR;
+ }
+
+ /// The diagnostic ID to emit. Used like so:
+ /// Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
+ /// << diag.getForbiddenTypeOperand()
+ /// << diag.getForbiddenTypeArgument();
+ unsigned getForbiddenTypeDiagnostic() const {
+ assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+ return ForbiddenTypeData.Diagnostic;
+ }
+
+ unsigned getForbiddenTypeArgument() const {
+ assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+ return ForbiddenTypeData.Argument;
+ }
+
+ QualType getForbiddenTypeOperand() const {
+ assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+ return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType);
+ }
+
+ const ObjCInterfaceDecl *getUnknownObjCClass() const {
+ return AvailabilityData.UnknownObjCClass;
+ }
+
+ const ObjCPropertyDecl *getObjCProperty() const {
+ return AvailabilityData.ObjCProperty;
+ }
+
+ bool getObjCPropertyAccess() const {
+ return AvailabilityData.ObjCPropertyAccess;
+ }
+
+private:
+ struct AD {
+ const NamedDecl *ReferringDecl;
+ const NamedDecl *OffendingDecl;
+ const ObjCInterfaceDecl *UnknownObjCClass;
+ const ObjCPropertyDecl *ObjCProperty;
+ const char *Message;
+ size_t MessageLen;
+ SourceLocation *SelectorLocs;
+ size_t NumSelectorLocs;
+ AvailabilityResult AR;
+ bool ObjCPropertyAccess;
+ };
+
+ struct FTD {
+ unsigned Diagnostic;
+ unsigned Argument;
+ void *OperandType;
+ };
+
+ union {
+ struct AD AvailabilityData;
+ struct FTD ForbiddenTypeData;
+
+ /// Access control.
+ char AccessData[sizeof(AccessedEntity)];
+ };
+};
+
+/// A collection of diagnostics which were delayed.
+class DelayedDiagnosticPool {
+ const DelayedDiagnosticPool *Parent;
+ SmallVector<DelayedDiagnostic, 4> Diagnostics;
+
+public:
+ DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {}
+
+ DelayedDiagnosticPool(const DelayedDiagnosticPool &) = delete;
+ DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &) = delete;
+
+ DelayedDiagnosticPool(DelayedDiagnosticPool &&Other)
+ : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) {
+ Other.Diagnostics.clear();
+ }
+
+ DelayedDiagnosticPool &operator=(DelayedDiagnosticPool &&Other) {
+ Parent = Other.Parent;
+ Diagnostics = std::move(Other.Diagnostics);
+ Other.Diagnostics.clear();
+ return *this;
+ }
+
+ ~DelayedDiagnosticPool() {
+ for (SmallVectorImpl<DelayedDiagnostic>::iterator
+ i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
+ i->Destroy();
+ }
+
+ const DelayedDiagnosticPool *getParent() const { return Parent; }
+
+ /// Does this pool, or any of its ancestors, contain any diagnostics?
+ bool empty() const {
+ return (Diagnostics.empty() && (!Parent || Parent->empty()));
+ }
+
+ /// Add a diagnostic to this pool.
+ void add(const DelayedDiagnostic &diag) {
+ Diagnostics.push_back(diag);
+ }
+
+ /// Steal the diagnostics from the given pool.
+ void steal(DelayedDiagnosticPool &pool) {
+ if (pool.Diagnostics.empty()) return;
+
+ if (Diagnostics.empty()) {
+ Diagnostics = std::move(pool.Diagnostics);
+ } else {
+ Diagnostics.append(pool.pool_begin(), pool.pool_end());
+ }
+ pool.Diagnostics.clear();
+ }
+
+ using pool_iterator = SmallVectorImpl<DelayedDiagnostic>::const_iterator;
+
+ pool_iterator pool_begin() const { return Diagnostics.begin(); }
+ pool_iterator pool_end() const { return Diagnostics.end(); }
+ bool pool_empty() const { return Diagnostics.empty(); }
+};
+
+} // namespace clang
+
+/// Add a diagnostic to the current delay pool.
+inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) {
+ assert(shouldDelayDiagnostics() && "trying to delay without pool");
+ CurPool->add(diag);
+}
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Designator.h b/contrib/libs/clang16/include/clang/Sema/Designator.h
new file mode 100644
index 0000000000..b449537566
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Designator.h
@@ -0,0 +1,225 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- Designator.h - Initialization Designator ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines interfaces used to represent designators (a la
+// C99 designated initializers) during parsing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_DESIGNATOR_H
+#define LLVM_CLANG_SEMA_DESIGNATOR_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang {
+
+class Expr;
+class IdentifierInfo;
+class Sema;
+
+/// Designator - A designator in a C99 designated initializer.
+///
+/// This class is a discriminated union which holds the various
+/// different sorts of designators possible. A Designation is an array of
+/// these. An example of a designator are things like this:
+/// [8] .field [47] // C99 designation: 3 designators
+/// [8 ... 47] field: // GNU extensions: 2 designators
+/// These occur in initializers, e.g.:
+/// int a[10] = {2, 4, [8]=9, 10};
+///
+class Designator {
+public:
+ enum DesignatorKind {
+ FieldDesignator, ArrayDesignator, ArrayRangeDesignator
+ };
+private:
+ Designator() {};
+
+ DesignatorKind Kind;
+
+ struct FieldDesignatorInfo {
+ const IdentifierInfo *II;
+ SourceLocation DotLoc;
+ SourceLocation NameLoc;
+ };
+ struct ArrayDesignatorInfo {
+ Expr *Index;
+ SourceLocation LBracketLoc;
+ mutable SourceLocation RBracketLoc;
+ };
+ struct ArrayRangeDesignatorInfo {
+ Expr *Start, *End;
+ SourceLocation LBracketLoc, EllipsisLoc;
+ mutable SourceLocation RBracketLoc;
+ };
+
+ union {
+ FieldDesignatorInfo FieldInfo;
+ ArrayDesignatorInfo ArrayInfo;
+ ArrayRangeDesignatorInfo ArrayRangeInfo;
+ };
+
+public:
+
+ DesignatorKind getKind() const { return Kind; }
+ bool isFieldDesignator() const { return Kind == FieldDesignator; }
+ bool isArrayDesignator() const { return Kind == ArrayDesignator; }
+ bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
+
+ const IdentifierInfo *getField() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return FieldInfo.II;
+ }
+
+ SourceLocation getDotLoc() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return FieldInfo.DotLoc;
+ }
+
+ SourceLocation getFieldLoc() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return FieldInfo.NameLoc;
+ }
+
+ Expr *getArrayIndex() const {
+ assert(isArrayDesignator() && "Invalid accessor");
+ return ArrayInfo.Index;
+ }
+
+ Expr *getArrayRangeStart() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return ArrayRangeInfo.Start;
+ }
+ Expr *getArrayRangeEnd() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return ArrayRangeInfo.End;
+ }
+
+ SourceLocation getLBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ return ArrayInfo.LBracketLoc;
+ else
+ return ArrayRangeInfo.LBracketLoc;
+ }
+
+ SourceLocation getRBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ return ArrayInfo.RBracketLoc;
+ else
+ return ArrayRangeInfo.RBracketLoc;
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return ArrayRangeInfo.EllipsisLoc;
+ }
+
+ static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc,
+ SourceLocation NameLoc) {
+ Designator D;
+ D.Kind = FieldDesignator;
+ new (&D.FieldInfo) FieldDesignatorInfo;
+ D.FieldInfo.II = II;
+ D.FieldInfo.DotLoc = DotLoc;
+ D.FieldInfo.NameLoc = NameLoc;
+ return D;
+ }
+
+ static Designator getArray(Expr *Index,
+ SourceLocation LBracketLoc) {
+ Designator D;
+ D.Kind = ArrayDesignator;
+ new (&D.ArrayInfo) ArrayDesignatorInfo;
+ D.ArrayInfo.Index = Index;
+ D.ArrayInfo.LBracketLoc = LBracketLoc;
+ D.ArrayInfo.RBracketLoc = SourceLocation();
+ return D;
+ }
+
+ static Designator getArrayRange(Expr *Start,
+ Expr *End,
+ SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc) {
+ Designator D;
+ D.Kind = ArrayRangeDesignator;
+ new (&D.ArrayRangeInfo) ArrayRangeDesignatorInfo;
+ D.ArrayRangeInfo.Start = Start;
+ D.ArrayRangeInfo.End = End;
+ D.ArrayRangeInfo.LBracketLoc = LBracketLoc;
+ D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc;
+ D.ArrayRangeInfo.RBracketLoc = SourceLocation();
+ return D;
+ }
+
+ void setRBracketLoc(SourceLocation RBracketLoc) const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ ArrayInfo.RBracketLoc = RBracketLoc;
+ else
+ ArrayRangeInfo.RBracketLoc = RBracketLoc;
+ }
+
+ /// ClearExprs - Null out any expression references, which prevents
+ /// them from being 'delete'd later.
+ void ClearExprs(Sema &Actions) {}
+
+ /// FreeExprs - Release any unclaimed memory for the expressions in
+ /// this designator.
+ void FreeExprs(Sema &Actions) {}
+};
+
+
+/// Designation - Represent a full designation, which is a sequence of
+/// designators. This class is mostly a helper for InitListDesignations.
+class Designation {
+ /// Designators - The actual designators for this initializer.
+ SmallVector<Designator, 2> Designators;
+
+public:
+ /// AddDesignator - Add a designator to the end of this list.
+ void AddDesignator(Designator D) {
+ Designators.push_back(D);
+ }
+
+ bool empty() const { return Designators.empty(); }
+
+ unsigned getNumDesignators() const { return Designators.size(); }
+ const Designator &getDesignator(unsigned Idx) const {
+ assert(Idx < Designators.size());
+ return Designators[Idx];
+ }
+
+ /// ClearExprs - Null out any expression references, which prevents them from
+ /// being 'delete'd later.
+ void ClearExprs(Sema &Actions) {}
+
+ /// FreeExprs - Release any unclaimed memory for the expressions in this
+ /// designation.
+ void FreeExprs(Sema &Actions) {}
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/ExternalSemaSource.h b/contrib/libs/clang16/include/clang/Sema/ExternalSemaSource.h
new file mode 100644
index 0000000000..795f336a6d
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/ExternalSemaSource.h
@@ -0,0 +1,255 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- ExternalSemaSource.h - External Sema Interface ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ExternalSemaSource interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_EXTERNALSEMASOURCE_H
+#define LLVM_CLANG_SEMA_EXTERNALSEMASOURCE_H
+
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/Type.h"
+#include "clang/Sema/TypoCorrection.h"
+#include "clang/Sema/Weak.h"
+#include "llvm/ADT/MapVector.h"
+#include <utility>
+
+namespace llvm {
+template <class T, unsigned n> class SmallSetVector;
+}
+
+namespace clang {
+
+class CXXConstructorDecl;
+class CXXRecordDecl;
+class DeclaratorDecl;
+class LookupResult;
+class Scope;
+class Sema;
+class TypedefNameDecl;
+class ValueDecl;
+class VarDecl;
+struct LateParsedTemplate;
+
+/// A simple structure that captures a vtable use for the purposes of
+/// the \c ExternalSemaSource.
+struct ExternalVTableUse {
+ CXXRecordDecl *Record;
+ SourceLocation Location;
+ bool DefinitionRequired;
+};
+
+/// An abstract interface that should be implemented by
+/// external AST sources that also provide information for semantic
+/// analysis.
+class ExternalSemaSource : public ExternalASTSource {
+ /// LLVM-style RTTI.
+ static char ID;
+
+public:
+ ExternalSemaSource() = default;
+
+ ~ExternalSemaSource() override;
+
+ /// Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S) {}
+
+ /// Inform the semantic consumer that Sema is no longer available.
+ virtual void ForgetSema() {}
+
+ /// Load the contents of the global method pool for a given
+ /// selector.
+ virtual void ReadMethodPool(Selector Sel);
+
+ /// Load the contents of the global method pool for a given
+ /// selector if necessary.
+ virtual void updateOutOfDateSelector(Selector Sel);
+
+ /// Load the set of namespaces that are known to the external source,
+ /// which will be used during typo correction.
+ virtual void ReadKnownNamespaces(
+ SmallVectorImpl<NamespaceDecl *> &Namespaces);
+
+ /// Load the set of used but not defined functions or variables with
+ /// internal linkage, or used but not defined internal functions.
+ virtual void
+ ReadUndefinedButUsed(llvm::MapVector<NamedDecl *, SourceLocation> &Undefined);
+
+ virtual void ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &);
+
+ /// Do last resort, unqualified lookup on a LookupResult that
+ /// Sema cannot find.
+ ///
+ /// \param R a LookupResult that is being recovered.
+ ///
+ /// \param S the Scope of the identifier occurrence.
+ ///
+ /// \return true to tell Sema to recover using the LookupResult.
+ virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; }
+
+ /// Read the set of tentative definitions known to the external Sema
+ /// source.
+ ///
+ /// The external source should append its own tentative definitions to the
+ /// given vector of tentative definitions. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadTentativeDefinitions(
+ SmallVectorImpl<VarDecl *> &TentativeDefs) {}
+
+ /// Read the set of unused file-scope declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own unused, filed-scope to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl *> &Decls) {}
+
+ /// Read the set of delegating constructors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own delegating constructors to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl *> &Decls) {}
+
+ /// Read the set of ext_vector type declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own ext_vector type declarations to
+ /// the given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {}
+
+ /// Read the set of potentially unused typedefs known to the source.
+ ///
+ /// The external source should append its own potentially unused local
+ /// typedefs to the given vector of declarations. Note that this routine may
+ /// be invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void ReadUnusedLocalTypedefNameCandidates(
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {}
+
+ /// Read the set of referenced selectors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own referenced selectors to the
+ /// given vector of selectors. Note that this routine
+ /// may be invoked multiple times; the external source should take care not
+ /// to introduce the same selectors repeatedly.
+ virtual void ReadReferencedSelectors(
+ SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {}
+
+ /// Read the set of weak, undeclared identifiers known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own weak, undeclared identifiers to
+ /// the given vector. Note that this routine may be invoked multiple times;
+ /// the external source should take care not to introduce the same identifiers
+ /// repeatedly.
+ virtual void ReadWeakUndeclaredIdentifiers(
+ SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) {}
+
+ /// Read the set of used vtables known to the external Sema source.
+ ///
+ /// The external source should append its own used vtables to the given
+ /// vector. Note that this routine may be invoked multiple times; the external
+ /// source should take care not to introduce the same vtables repeatedly.
+ virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {}
+
+ /// Read the set of pending instantiations known to the external
+ /// Sema source.
+ ///
+ /// The external source should append its own pending instantiations to the
+ /// given vector. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same instantiations
+ /// repeatedly.
+ virtual void ReadPendingInstantiations(
+ SmallVectorImpl<std::pair<ValueDecl *,
+ SourceLocation> > &Pending) {}
+
+ /// Read the set of late parsed template functions for this source.
+ ///
+ /// The external source should insert its own late parsed template functions
+ /// into the map. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same map entries
+ /// repeatedly.
+ virtual void ReadLateParsedTemplates(
+ llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
+ &LPTMap) {}
+
+ /// Read the set of decls to be checked for deferred diags.
+ ///
+ /// The external source should append its own potentially emitted function
+ /// and variable decls which may cause deferred diags. Note that this routine
+ /// may be invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ virtual void
+ ReadDeclsToCheckForDeferredDiags(llvm::SmallSetVector<Decl *, 4> &Decls) {}
+
+ /// \copydoc Sema::CorrectTypo
+ /// \note LookupKind must correspond to a valid Sema::LookupNameKind
+ ///
+ /// ExternalSemaSource::CorrectTypo is always given the first chance to
+ /// correct a typo (really, to offer suggestions to repair a failed lookup).
+ /// It will even be called when SpellChecking is turned off or after a
+ /// fatal error has already been detected.
+ virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ int LookupKind, Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT) {
+ return TypoCorrection();
+ }
+
+ /// Produces a diagnostic note if the external source contains a
+ /// complete definition for \p T.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the \c QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
+ QualType T) {
+ return false;
+ }
+
+ /// LLVM-style RTTI.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || ExternalASTSource::isA(ClassID);
+ }
+ static bool classof(const ExternalASTSource *S) { return S->isA(&ID); }
+ /// \}
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/HLSLExternalSemaSource.h b/contrib/libs/clang16/include/clang/Sema/HLSLExternalSemaSource.h
new file mode 100644
index 0000000000..85e29b8849
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/HLSLExternalSemaSource.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- HLSLExternalSemaSource.h - HLSL Sema Source ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the HLSLExternalSemaSource interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef CLANG_SEMA_HLSLEXTERNALSEMASOURCE_H
+#define CLANG_SEMA_HLSLEXTERNALSEMASOURCE_H
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "clang/Sema/ExternalSemaSource.h"
+
+namespace clang {
+class NamespaceDecl;
+class Sema;
+
+class HLSLExternalSemaSource : public ExternalSemaSource {
+ Sema *SemaPtr = nullptr;
+ NamespaceDecl *HLSLNamespace = nullptr;
+ CXXRecordDecl *ResourceDecl;
+
+ using CompletionFunction = std::function<void(CXXRecordDecl *)>;
+ llvm::DenseMap<CXXRecordDecl *, CompletionFunction> Completions;
+
+ void defineHLSLVectorAlias();
+ void defineTrivialHLSLTypes();
+ void forwardDeclareHLSLTypes();
+
+ void completeBufferType(CXXRecordDecl *Record);
+
+public:
+ ~HLSLExternalSemaSource() override;
+
+ /// Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ void InitializeSema(Sema &S) override;
+
+ /// Inform the semantic consumer that Sema is no longer available.
+ void ForgetSema() override { SemaPtr = nullptr; }
+
+ using ExternalASTSource::CompleteType;
+ /// Complete an incomplete HLSL builtin type
+ void CompleteType(TagDecl *Tag) override;
+};
+
+} // namespace clang
+
+#endif // CLANG_SEMA_HLSLEXTERNALSEMASOURCE_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/IdentifierResolver.h b/contrib/libs/clang16/include/clang/Sema/IdentifierResolver.h
new file mode 100644
index 0000000000..d20f645f4c
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/IdentifierResolver.h
@@ -0,0 +1,216 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- IdentifierResolver.h - Lexical Scope Name lookup ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the IdentifierResolver class, which is used for lexical
+// scoped lookup, based on declaration names.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
+#define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+
+namespace clang {
+
+class Decl;
+class DeclarationName;
+class DeclContext;
+class IdentifierInfo;
+class LangOptions;
+class NamedDecl;
+class Preprocessor;
+class Scope;
+
+/// IdentifierResolver - Keeps track of shadowed decls on enclosing
+/// scopes. It manages the shadowing chains of declaration names and
+/// implements efficient decl lookup based on a declaration name.
+class IdentifierResolver {
+ /// IdDeclInfo - Keeps track of information about decls associated
+ /// to a particular declaration name. IdDeclInfos are lazily
+ /// constructed and assigned to a declaration name the first time a
+ /// decl with that declaration name is shadowed in some scope.
+ class IdDeclInfo {
+ public:
+ using DeclsTy = SmallVector<NamedDecl *, 2>;
+
+ DeclsTy::iterator decls_begin() { return Decls.begin(); }
+ DeclsTy::iterator decls_end() { return Decls.end(); }
+
+ void AddDecl(NamedDecl *D) { Decls.push_back(D); }
+
+ /// RemoveDecl - Remove the decl from the scope chain.
+ /// The decl must already be part of the decl chain.
+ void RemoveDecl(NamedDecl *D);
+
+ /// Insert the given declaration at the given position in the list.
+ void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) {
+ Decls.insert(Pos, D);
+ }
+
+ private:
+ DeclsTy Decls;
+ };
+
+public:
+ /// iterator - Iterate over the decls of a specified declaration name.
+ /// It will walk or not the parent declaration contexts depending on how
+ /// it was instantiated.
+ class iterator {
+ public:
+ friend class IdentifierResolver;
+
+ using value_type = NamedDecl *;
+ using reference = NamedDecl *;
+ using pointer = NamedDecl *;
+ using iterator_category = std::input_iterator_tag;
+ using difference_type = std::ptrdiff_t;
+
+ /// Ptr - There are 2 forms that 'Ptr' represents:
+ /// 1) A single NamedDecl. (Ptr & 0x1 == 0)
+ /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the
+ /// same declaration context. (Ptr & 0x1 == 0x1)
+ uintptr_t Ptr = 0;
+ using BaseIter = IdDeclInfo::DeclsTy::iterator;
+
+ /// A single NamedDecl. (Ptr & 0x1 == 0)
+ iterator(NamedDecl *D) {
+ Ptr = reinterpret_cast<uintptr_t>(D);
+ assert((Ptr & 0x1) == 0 && "Invalid Ptr!");
+ }
+
+ /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
+ /// contexts depending on 'LookInParentCtx'.
+ iterator(BaseIter I) {
+ Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
+ }
+
+ bool isIterator() const { return (Ptr & 0x1); }
+
+ BaseIter getIterator() const {
+ assert(isIterator() && "Ptr not an iterator!");
+ return reinterpret_cast<BaseIter>(Ptr & ~0x1);
+ }
+
+ void incrementSlowCase();
+
+ public:
+ iterator() = default;
+
+ NamedDecl *operator*() const {
+ if (isIterator())
+ return *getIterator();
+ else
+ return reinterpret_cast<NamedDecl*>(Ptr);
+ }
+
+ bool operator==(const iterator &RHS) const {
+ return Ptr == RHS.Ptr;
+ }
+ bool operator!=(const iterator &RHS) const {
+ return Ptr != RHS.Ptr;
+ }
+
+ // Preincrement.
+ iterator& operator++() {
+ if (!isIterator()) // common case.
+ Ptr = 0;
+ else
+ incrementSlowCase();
+ return *this;
+ }
+ };
+
+ explicit IdentifierResolver(Preprocessor &PP);
+ ~IdentifierResolver();
+
+ /// begin - Returns an iterator for decls with the name 'Name'.
+ iterator begin(DeclarationName Name);
+
+ /// end - Returns an iterator that has 'finished'.
+ iterator end() {
+ return iterator();
+ }
+
+ /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+ /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+ /// true if 'D' belongs to the given declaration context.
+ ///
+ /// \param AllowInlineNamespace If \c true, we are checking whether a prior
+ /// declaration is in scope in a declaration that requires a prior
+ /// declaration (because it is either explicitly qualified or is a
+ /// template instantiation or specialization). In this case, a
+ /// declaration is in scope if it's in the inline namespace set of the
+ /// context.
+ bool isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S = nullptr,
+ bool AllowInlineNamespace = false) const;
+
+ /// AddDecl - Link the decl to its shadowed decl chain.
+ void AddDecl(NamedDecl *D);
+
+ /// RemoveDecl - Unlink the decl from its shadowed decl chain.
+ /// The decl must already be part of the decl chain.
+ void RemoveDecl(NamedDecl *D);
+
+ /// Insert the given declaration after the given iterator
+ /// position.
+ void InsertDeclAfter(iterator Pos, NamedDecl *D);
+
+ /// Try to add the given declaration to the top level scope, if it
+ /// (or a redeclaration of it) hasn't already been added.
+ ///
+ /// \param D The externally-produced declaration to add.
+ ///
+ /// \param Name The name of the externally-produced declaration.
+ ///
+ /// \returns true if the declaration was added, false otherwise.
+ bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name);
+
+private:
+ const LangOptions &LangOpt;
+ Preprocessor &PP;
+
+ class IdDeclInfoMap;
+ IdDeclInfoMap *IdDeclInfos;
+
+ void updatingIdentifier(IdentifierInfo &II);
+ void readingIdentifier(IdentifierInfo &II);
+
+ /// FETokenInfo contains a Decl pointer if lower bit == 0.
+ static inline bool isDeclPtr(void *Ptr) {
+ return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
+ }
+
+ /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+ static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
+ assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
+ && "Ptr not a IdDeclInfo* !");
+ return reinterpret_cast<IdDeclInfo*>(
+ reinterpret_cast<uintptr_t>(Ptr) & ~0x1);
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Initialization.h b/contrib/libs/clang16/include/clang/Sema/Initialization.h
new file mode 100644
index 0000000000..ba0d6542b3
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Initialization.h
@@ -0,0 +1,1433 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Initialization.h - Semantic Analysis for Initializers ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides supporting data types for initialization of objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_INITIALIZATION_H
+#define LLVM_CLANG_SEMA_INITIALIZATION_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Sema/Overload.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstdint>
+#include <string>
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class CXXConstructorDecl;
+class ObjCMethodDecl;
+class Sema;
+
+/// Describes an entity that is being initialized.
+class alignas(8) InitializedEntity {
+public:
+ /// Specifies the kind of entity being initialized.
+ enum EntityKind {
+ /// The entity being initialized is a variable.
+ EK_Variable,
+
+ /// The entity being initialized is a function parameter.
+ EK_Parameter,
+
+ /// The entity being initialized is a non-type template parameter.
+ EK_TemplateParameter,
+
+ /// The entity being initialized is the result of a function call.
+ EK_Result,
+
+ /// The entity being initialized is the result of a statement expression.
+ EK_StmtExprResult,
+
+ /// The entity being initialized is an exception object that
+ /// is being thrown.
+ EK_Exception,
+
+ /// The entity being initialized is a non-static data member
+ /// subobject.
+ EK_Member,
+
+ /// The entity being initialized is an element of an array.
+ EK_ArrayElement,
+
+ /// The entity being initialized is an object (or array of
+ /// objects) allocated via new.
+ EK_New,
+
+ /// The entity being initialized is a temporary object.
+ EK_Temporary,
+
+ /// The entity being initialized is a base member subobject.
+ EK_Base,
+
+ /// The initialization is being done by a delegating constructor.
+ EK_Delegating,
+
+ /// The entity being initialized is an element of a vector.
+ /// or vector.
+ EK_VectorElement,
+
+ /// The entity being initialized is a field of block descriptor for
+ /// the copied-in c++ object.
+ EK_BlockElement,
+
+ /// The entity being initialized is a field of block descriptor for the
+ /// copied-in lambda object that's used in the lambda to block conversion.
+ EK_LambdaToBlockConversionBlockElement,
+
+ /// The entity being initialized is the real or imaginary part of a
+ /// complex number.
+ EK_ComplexElement,
+
+ /// The entity being initialized is the field that captures a
+ /// variable in a lambda.
+ EK_LambdaCapture,
+
+ /// The entity being initialized is the initializer for a compound
+ /// literal.
+ EK_CompoundLiteralInit,
+
+ /// The entity being implicitly initialized back to the formal
+ /// result type.
+ EK_RelatedResult,
+
+ /// The entity being initialized is a function parameter; function
+ /// is member of group of audited CF APIs.
+ EK_Parameter_CF_Audited,
+
+ /// The entity being initialized is a structured binding of a
+ /// decomposition declaration.
+ EK_Binding,
+
+ // Note: err_init_conversion_failed in DiagnosticSemaKinds.td uses this
+ // enum as an index for its first %select. When modifying this list,
+ // that diagnostic text needs to be updated as well.
+ };
+
+private:
+ /// The kind of entity being initialized.
+ EntityKind Kind;
+
+ /// If non-NULL, the parent entity in which this
+ /// initialization occurs.
+ const InitializedEntity *Parent = nullptr;
+
+ /// The type of the object or reference being initialized.
+ QualType Type;
+
+ /// The mangling number for the next reference temporary to be created.
+ mutable unsigned ManglingNumber = 0;
+
+ struct LN {
+ /// When Kind == EK_Result, EK_Exception, EK_New, the
+ /// location of the 'return', 'throw', or 'new' keyword,
+ /// respectively. When Kind == EK_Temporary, the location where
+ /// the temporary is being created.
+ SourceLocation Location;
+
+ /// Whether the entity being initialized may end up using the
+ /// named return value optimization (NRVO).
+ bool NRVO;
+ };
+
+ struct VD {
+ /// The VarDecl, FieldDecl, or BindingDecl being initialized.
+ ValueDecl *VariableOrMember;
+
+ /// When Kind == EK_Member, whether this is an implicit member
+ /// initialization in a copy or move constructor. These can perform array
+ /// copies.
+ bool IsImplicitFieldInit;
+
+ /// When Kind == EK_Member, whether this is the initial initialization
+ /// check for a default member initializer.
+ bool IsDefaultMemberInit;
+ };
+
+ struct C {
+ /// The name of the variable being captured by an EK_LambdaCapture.
+ IdentifierInfo *VarID;
+
+ /// The source location at which the capture occurs.
+ SourceLocation Location;
+ };
+
+ union {
+ /// When Kind == EK_Variable, EK_Member, EK_Binding, or
+ /// EK_TemplateParameter, the variable, binding, or template parameter.
+ VD Variable;
+
+ /// When Kind == EK_RelatedResult, the ObjectiveC method where
+ /// result type was implicitly changed to accommodate ARC semantics.
+ ObjCMethodDecl *MethodDecl;
+
+ /// When Kind == EK_Parameter, the ParmVarDecl, with the
+ /// integer indicating whether the parameter is "consumed".
+ llvm::PointerIntPair<ParmVarDecl *, 1> Parameter;
+
+ /// When Kind == EK_Temporary or EK_CompoundLiteralInit, the type
+ /// source information for the temporary.
+ TypeSourceInfo *TypeInfo;
+
+ struct LN LocAndNRVO;
+
+ /// When Kind == EK_Base, the base specifier that provides the
+ /// base class. The integer specifies whether the base is an inherited
+ /// virtual base.
+ llvm::PointerIntPair<const CXXBaseSpecifier *, 1> Base;
+
+ /// When Kind == EK_ArrayElement, EK_VectorElement, or
+ /// EK_ComplexElement, the index of the array or vector element being
+ /// initialized.
+ unsigned Index;
+
+ struct C Capture;
+ };
+
+ InitializedEntity() {};
+
+ /// Create the initialization entity for a variable.
+ InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
+ : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {}
+
+ /// Create the initialization entity for the result of a
+ /// function, throwing an object, performing an explicit cast, or
+ /// initializing a parameter for which there is no declaration.
+ InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
+ bool NRVO = false)
+ : Kind(Kind), Type(Type) {
+ new (&LocAndNRVO) LN;
+ LocAndNRVO.Location = Loc;
+ LocAndNRVO.NRVO = NRVO;
+ }
+
+ /// Create the initialization entity for a member subobject.
+ InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent,
+ bool Implicit, bool DefaultMemberInit)
+ : Kind(EK_Member), Parent(Parent), Type(Member->getType()),
+ Variable{Member, Implicit, DefaultMemberInit} {}
+
+ /// Create the initialization entity for an array element.
+ InitializedEntity(ASTContext &Context, unsigned Index,
+ const InitializedEntity &Parent);
+
+ /// Create the initialization entity for a lambda capture.
+ InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc)
+ : Kind(EK_LambdaCapture), Type(FieldType) {
+ new (&Capture) C;
+ Capture.VarID = VarID;
+ Capture.Location = Loc;
+ }
+
+public:
+ /// Create the initialization entity for a variable.
+ static InitializedEntity InitializeVariable(VarDecl *Var) {
+ return InitializedEntity(Var);
+ }
+
+ /// Create the initialization entity for a parameter.
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ ParmVarDecl *Parm) {
+ return InitializeParameter(Context, Parm, Parm->getType());
+ }
+
+ /// Create the initialization entity for a parameter, but use
+ /// another type.
+ static InitializedEntity
+ InitializeParameter(ASTContext &Context, ParmVarDecl *Parm, QualType Type) {
+ bool Consumed = (Context.getLangOpts().ObjCAutoRefCount &&
+ Parm->hasAttr<NSConsumedAttr>());
+
+ InitializedEntity Entity;
+ Entity.Kind = EK_Parameter;
+ Entity.Type =
+ Context.getVariableArrayDecayedType(Type.getUnqualifiedType());
+ Entity.Parent = nullptr;
+ Entity.Parameter = {Parm, Consumed};
+ return Entity;
+ }
+
+ /// Create the initialization entity for a parameter that is
+ /// only known by its type.
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ QualType Type,
+ bool Consumed) {
+ InitializedEntity Entity;
+ Entity.Kind = EK_Parameter;
+ Entity.Type = Context.getVariableArrayDecayedType(Type);
+ Entity.Parent = nullptr;
+ Entity.Parameter = {nullptr, Consumed};
+ return Entity;
+ }
+
+ /// Create the initialization entity for a template parameter.
+ static InitializedEntity
+ InitializeTemplateParameter(QualType T, NonTypeTemplateParmDecl *Param) {
+ InitializedEntity Entity;
+ Entity.Kind = EK_TemplateParameter;
+ Entity.Type = T;
+ Entity.Parent = nullptr;
+ Entity.Variable = {Param, false, false};
+ return Entity;
+ }
+
+ /// Create the initialization entity for the result of a function.
+ static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
+ QualType Type) {
+ return InitializedEntity(EK_Result, ReturnLoc, Type);
+ }
+
+ static InitializedEntity InitializeStmtExprResult(SourceLocation ReturnLoc,
+ QualType Type) {
+ return InitializedEntity(EK_StmtExprResult, ReturnLoc, Type);
+ }
+
+ static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
+ QualType Type) {
+ return InitializedEntity(EK_BlockElement, BlockVarLoc, Type);
+ }
+
+ static InitializedEntity InitializeLambdaToBlock(SourceLocation BlockVarLoc,
+ QualType Type) {
+ return InitializedEntity(EK_LambdaToBlockConversionBlockElement,
+ BlockVarLoc, Type);
+ }
+
+ /// Create the initialization entity for an exception object.
+ static InitializedEntity InitializeException(SourceLocation ThrowLoc,
+ QualType Type) {
+ return InitializedEntity(EK_Exception, ThrowLoc, Type);
+ }
+
+ /// Create the initialization entity for an object allocated via new.
+ static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) {
+ return InitializedEntity(EK_New, NewLoc, Type);
+ }
+
+ /// Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(QualType Type) {
+ return InitializeTemporary(nullptr, Type);
+ }
+
+ /// Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(ASTContext &Context,
+ TypeSourceInfo *TypeInfo) {
+ QualType Type = TypeInfo->getType();
+ if (Context.getLangOpts().OpenCLCPlusPlus) {
+ assert(!Type.hasAddressSpace() && "Temporary already has address space!");
+ Type = Context.getAddrSpaceQualType(Type, LangAS::opencl_private);
+ }
+
+ return InitializeTemporary(TypeInfo, Type);
+ }
+
+ /// Create the initialization entity for a temporary.
+ static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo,
+ QualType Type) {
+ InitializedEntity Result(EK_Temporary, SourceLocation(), Type);
+ Result.TypeInfo = TypeInfo;
+ return Result;
+ }
+
+ /// Create the initialization entity for a related result.
+ static InitializedEntity InitializeRelatedResult(ObjCMethodDecl *MD,
+ QualType Type) {
+ InitializedEntity Result(EK_RelatedResult, SourceLocation(), Type);
+ Result.MethodDecl = MD;
+ return Result;
+ }
+
+ /// Create the initialization entity for a base class subobject.
+ static InitializedEntity
+ InitializeBase(ASTContext &Context, const CXXBaseSpecifier *Base,
+ bool IsInheritedVirtualBase,
+ const InitializedEntity *Parent = nullptr);
+
+ /// Create the initialization entity for a delegated constructor.
+ static InitializedEntity InitializeDelegation(QualType Type) {
+ return InitializedEntity(EK_Delegating, SourceLocation(), Type);
+ }
+
+ /// Create the initialization entity for a member subobject.
+ static InitializedEntity
+ InitializeMember(FieldDecl *Member,
+ const InitializedEntity *Parent = nullptr,
+ bool Implicit = false) {
+ return InitializedEntity(Member, Parent, Implicit, false);
+ }
+
+ /// Create the initialization entity for a member subobject.
+ static InitializedEntity
+ InitializeMember(IndirectFieldDecl *Member,
+ const InitializedEntity *Parent = nullptr,
+ bool Implicit = false) {
+ return InitializedEntity(Member->getAnonField(), Parent, Implicit, false);
+ }
+
+ /// Create the initialization entity for a default member initializer.
+ static InitializedEntity
+ InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) {
+ return InitializedEntity(Member, nullptr, false, true);
+ }
+
+ /// Create the initialization entity for an array element.
+ static InitializedEntity InitializeElement(ASTContext &Context,
+ unsigned Index,
+ const InitializedEntity &Parent) {
+ return InitializedEntity(Context, Index, Parent);
+ }
+
+ /// Create the initialization entity for a structured binding.
+ static InitializedEntity InitializeBinding(VarDecl *Binding) {
+ return InitializedEntity(Binding, EK_Binding);
+ }
+
+ /// Create the initialization entity for a lambda capture.
+ ///
+ /// \p VarID The name of the entity being captured, or nullptr for 'this'.
+ static InitializedEntity InitializeLambdaCapture(IdentifierInfo *VarID,
+ QualType FieldType,
+ SourceLocation Loc) {
+ return InitializedEntity(VarID, FieldType, Loc);
+ }
+
+ /// Create the entity for a compound literal initializer.
+ static InitializedEntity InitializeCompoundLiteralInit(TypeSourceInfo *TSI) {
+ InitializedEntity Result(EK_CompoundLiteralInit, SourceLocation(),
+ TSI->getType());
+ Result.TypeInfo = TSI;
+ return Result;
+ }
+
+ /// Determine the kind of initialization.
+ EntityKind getKind() const { return Kind; }
+
+ /// Retrieve the parent of the entity being initialized, when
+ /// the initialization itself is occurring within the context of a
+ /// larger initialization.
+ const InitializedEntity *getParent() const { return Parent; }
+
+ /// Retrieve type being initialized.
+ QualType getType() const { return Type; }
+
+ /// Retrieve complete type-source information for the object being
+ /// constructed, if known.
+ TypeSourceInfo *getTypeSourceInfo() const {
+ if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit)
+ return TypeInfo;
+
+ return nullptr;
+ }
+
+ /// Retrieve the name of the entity being initialized.
+ DeclarationName getName() const;
+
+ /// Retrieve the variable, parameter, or field being
+ /// initialized.
+ ValueDecl *getDecl() const;
+
+ /// Retrieve the ObjectiveC method being initialized.
+ ObjCMethodDecl *getMethodDecl() const { return MethodDecl; }
+
+ /// Determine whether this initialization allows the named return
+ /// value optimization, which also applies to thrown objects.
+ bool allowsNRVO() const;
+
+ bool isParameterKind() const {
+ return (getKind() == EK_Parameter ||
+ getKind() == EK_Parameter_CF_Audited);
+ }
+
+ bool isParamOrTemplateParamKind() const {
+ return isParameterKind() || getKind() == EK_TemplateParameter;
+ }
+
+ /// Determine whether this initialization consumes the
+ /// parameter.
+ bool isParameterConsumed() const {
+ assert(isParameterKind() && "Not a parameter");
+ return Parameter.getInt();
+ }
+
+ /// Retrieve the base specifier.
+ const CXXBaseSpecifier *getBaseSpecifier() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return Base.getPointer();
+ }
+
+ /// Return whether the base is an inherited virtual base.
+ bool isInheritedVirtualBase() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return Base.getInt();
+ }
+
+ /// Determine whether this is an array new with an unknown bound.
+ bool isVariableLengthArrayNew() const {
+ return getKind() == EK_New && isa_and_nonnull<IncompleteArrayType>(
+ getType()->getAsArrayTypeUnsafe());
+ }
+
+ /// Is this the implicit initialization of a member of a class from
+ /// a defaulted constructor?
+ bool isImplicitMemberInitializer() const {
+ return getKind() == EK_Member && Variable.IsImplicitFieldInit;
+ }
+
+ /// Is this the default member initializer of a member (specified inside
+ /// the class definition)?
+ bool isDefaultMemberInitializer() const {
+ return getKind() == EK_Member && Variable.IsDefaultMemberInit;
+ }
+
+ /// Determine the location of the 'return' keyword when initializing
+ /// the result of a function call.
+ SourceLocation getReturnLoc() const {
+ assert(getKind() == EK_Result && "No 'return' location!");
+ return LocAndNRVO.Location;
+ }
+
+ /// Determine the location of the 'throw' keyword when initializing
+ /// an exception object.
+ SourceLocation getThrowLoc() const {
+ assert(getKind() == EK_Exception && "No 'throw' location!");
+ return LocAndNRVO.Location;
+ }
+
+ /// If this is an array, vector, or complex number element, get the
+ /// element's index.
+ unsigned getElementIndex() const {
+ assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
+ getKind() == EK_ComplexElement);
+ return Index;
+ }
+
+ /// If this is already the initializer for an array or vector
+ /// element, sets the element index.
+ void setElementIndex(unsigned Index) {
+ assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement ||
+ getKind() == EK_ComplexElement);
+ this->Index = Index;
+ }
+
+ /// For a lambda capture, return the capture's name.
+ StringRef getCapturedVarName() const {
+ assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
+ return Capture.VarID ? Capture.VarID->getName() : "this";
+ }
+
+ /// Determine the location of the capture when initializing
+ /// field from a captured variable in a lambda.
+ SourceLocation getCaptureLoc() const {
+ assert(getKind() == EK_LambdaCapture && "Not a lambda capture!");
+ return Capture.Location;
+ }
+
+ void setParameterCFAudited() {
+ Kind = EK_Parameter_CF_Audited;
+ }
+
+ unsigned allocateManglingNumber() const { return ++ManglingNumber; }
+
+ /// Dump a representation of the initialized entity to standard error,
+ /// for debugging purposes.
+ void dump() const;
+
+private:
+ unsigned dumpImpl(raw_ostream &OS) const;
+};
+
+/// Describes the kind of initialization being performed, along with
+/// location information for tokens related to the initialization (equal sign,
+/// parentheses).
+class InitializationKind {
+public:
+ /// The kind of initialization being performed.
+ enum InitKind {
+ /// Direct initialization
+ IK_Direct,
+
+ /// Direct list-initialization
+ IK_DirectList,
+
+ /// Copy initialization
+ IK_Copy,
+
+ /// Default initialization
+ IK_Default,
+
+ /// Value initialization
+ IK_Value
+ };
+
+private:
+ /// The context of the initialization.
+ enum InitContext {
+ /// Normal context
+ IC_Normal,
+
+ /// Normal context, but allows explicit conversion functionss
+ IC_ExplicitConvs,
+
+ /// Implicit context (value initialization)
+ IC_Implicit,
+
+ /// Static cast context
+ IC_StaticCast,
+
+ /// C-style cast context
+ IC_CStyleCast,
+
+ /// Functional cast context
+ IC_FunctionalCast
+ };
+
+ /// The kind of initialization being performed.
+ InitKind Kind : 8;
+
+ /// The context of the initialization.
+ InitContext Context : 8;
+
+ /// The source locations involved in the initialization.
+ SourceLocation Locations[3];
+
+ InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1,
+ SourceLocation Loc2, SourceLocation Loc3)
+ : Kind(Kind), Context(Context) {
+ Locations[0] = Loc1;
+ Locations[1] = Loc2;
+ Locations[2] = Loc3;
+ }
+
+public:
+ /// Create a direct initialization.
+ static InitializationKind CreateDirect(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc) {
+ return InitializationKind(IK_Direct, IC_Normal,
+ InitLoc, LParenLoc, RParenLoc);
+ }
+
+ static InitializationKind CreateDirectList(SourceLocation InitLoc) {
+ return InitializationKind(IK_DirectList, IC_Normal, InitLoc, InitLoc,
+ InitLoc);
+ }
+
+ static InitializationKind CreateDirectList(SourceLocation InitLoc,
+ SourceLocation LBraceLoc,
+ SourceLocation RBraceLoc) {
+ return InitializationKind(IK_DirectList, IC_Normal, InitLoc, LBraceLoc,
+ RBraceLoc);
+ }
+
+ /// Create a direct initialization due to a cast that isn't a C-style
+ /// or functional cast.
+ static InitializationKind CreateCast(SourceRange TypeRange) {
+ return InitializationKind(IK_Direct, IC_StaticCast, TypeRange.getBegin(),
+ TypeRange.getBegin(), TypeRange.getEnd());
+ }
+
+ /// Create a direct initialization for a C-style cast.
+ static InitializationKind CreateCStyleCast(SourceLocation StartLoc,
+ SourceRange TypeRange,
+ bool InitList) {
+ // C++ cast syntax doesn't permit init lists, but C compound literals are
+ // exactly that.
+ return InitializationKind(InitList ? IK_DirectList : IK_Direct,
+ IC_CStyleCast, StartLoc, TypeRange.getBegin(),
+ TypeRange.getEnd());
+ }
+
+ /// Create a direct initialization for a functional cast.
+ static InitializationKind CreateFunctionalCast(SourceRange TypeRange,
+ bool InitList) {
+ return InitializationKind(InitList ? IK_DirectList : IK_Direct,
+ IC_FunctionalCast, TypeRange.getBegin(),
+ TypeRange.getBegin(), TypeRange.getEnd());
+ }
+
+ /// Create a copy initialization.
+ static InitializationKind CreateCopy(SourceLocation InitLoc,
+ SourceLocation EqualLoc,
+ bool AllowExplicitConvs = false) {
+ return InitializationKind(IK_Copy,
+ AllowExplicitConvs? IC_ExplicitConvs : IC_Normal,
+ InitLoc, EqualLoc, EqualLoc);
+ }
+
+ /// Create a default initialization.
+ static InitializationKind CreateDefault(SourceLocation InitLoc) {
+ return InitializationKind(IK_Default, IC_Normal, InitLoc, InitLoc, InitLoc);
+ }
+
+ /// Create a value initialization.
+ static InitializationKind CreateValue(SourceLocation InitLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ bool isImplicit = false) {
+ return InitializationKind(IK_Value, isImplicit ? IC_Implicit : IC_Normal,
+ InitLoc, LParenLoc, RParenLoc);
+ }
+
+ /// Create an initialization from an initializer (which, for direct
+ /// initialization from a parenthesized list, will be a ParenListExpr).
+ static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit,
+ Expr *Init) {
+ if (!Init) return CreateDefault(Loc);
+ if (!DirectInit)
+ return CreateCopy(Loc, Init->getBeginLoc());
+ if (isa<InitListExpr>(Init))
+ return CreateDirectList(Loc, Init->getBeginLoc(), Init->getEndLoc());
+ return CreateDirect(Loc, Init->getBeginLoc(), Init->getEndLoc());
+ }
+
+ /// Determine the initialization kind.
+ InitKind getKind() const {
+ return Kind;
+ }
+
+ /// Determine whether this initialization is an explicit cast.
+ bool isExplicitCast() const {
+ return Context >= IC_StaticCast;
+ }
+
+ /// Determine whether this initialization is a static cast.
+ bool isStaticCast() const { return Context == IC_StaticCast; }
+
+ /// Determine whether this initialization is a C-style cast.
+ bool isCStyleOrFunctionalCast() const {
+ return Context >= IC_CStyleCast;
+ }
+
+ /// Determine whether this is a C-style cast.
+ bool isCStyleCast() const {
+ return Context == IC_CStyleCast;
+ }
+
+ /// Determine whether this is a functional-style cast.
+ bool isFunctionalCast() const {
+ return Context == IC_FunctionalCast;
+ }
+
+ /// Determine whether this initialization is an implicit
+ /// value-initialization, e.g., as occurs during aggregate
+ /// initialization.
+ bool isImplicitValueInit() const { return Context == IC_Implicit; }
+
+ /// Retrieve the location at which initialization is occurring.
+ SourceLocation getLocation() const { return Locations[0]; }
+
+ /// Retrieve the source range that covers the initialization.
+ SourceRange getRange() const {
+ return SourceRange(Locations[0], Locations[2]);
+ }
+
+ /// Retrieve the location of the equal sign for copy initialization
+ /// (if present).
+ SourceLocation getEqualLoc() const {
+ assert(Kind == IK_Copy && "Only copy initialization has an '='");
+ return Locations[1];
+ }
+
+ bool isCopyInit() const { return Kind == IK_Copy; }
+
+ /// Retrieve whether this initialization allows the use of explicit
+ /// constructors.
+ bool AllowExplicit() const { return !isCopyInit(); }
+
+ /// Retrieve whether this initialization allows the use of explicit
+ /// conversion functions when binding a reference. If the reference is the
+ /// first parameter in a copy or move constructor, such conversions are
+ /// permitted even though we are performing copy-initialization.
+ bool allowExplicitConversionFunctionsInRefBinding() const {
+ return !isCopyInit() || Context == IC_ExplicitConvs;
+ }
+
+ /// Determine whether this initialization has a source range containing the
+ /// locations of open and closing parentheses or braces.
+ bool hasParenOrBraceRange() const {
+ return Kind == IK_Direct || Kind == IK_Value || Kind == IK_DirectList;
+ }
+
+ /// Retrieve the source range containing the locations of the open
+ /// and closing parentheses or braces for value, direct, and direct list
+ /// initializations.
+ SourceRange getParenOrBraceRange() const {
+ assert(hasParenOrBraceRange() && "Only direct, value, and direct-list "
+ "initialization have parentheses or "
+ "braces");
+ return SourceRange(Locations[1], Locations[2]);
+ }
+};
+
+/// Describes the sequence of initializations required to initialize
+/// a given object or reference with a set of arguments.
+class InitializationSequence {
+public:
+ /// Describes the kind of initialization sequence computed.
+ enum SequenceKind {
+ /// A failed initialization sequence. The failure kind tells what
+ /// happened.
+ FailedSequence = 0,
+
+ /// A dependent initialization, which could not be
+ /// type-checked due to the presence of dependent types or
+ /// dependently-typed expressions.
+ DependentSequence,
+
+ /// A normal sequence.
+ NormalSequence
+ };
+
+ /// Describes the kind of a particular step in an initialization
+ /// sequence.
+ enum StepKind {
+ /// Resolve the address of an overloaded function to a specific
+ /// function declaration.
+ SK_ResolveAddressOfOverloadedFunction,
+
+ /// Perform a derived-to-base cast, producing an rvalue.
+ SK_CastDerivedToBasePRValue,
+
+ /// Perform a derived-to-base cast, producing an xvalue.
+ SK_CastDerivedToBaseXValue,
+
+ /// Perform a derived-to-base cast, producing an lvalue.
+ SK_CastDerivedToBaseLValue,
+
+ /// Reference binding to an lvalue.
+ SK_BindReference,
+
+ /// Reference binding to a temporary.
+ SK_BindReferenceToTemporary,
+
+ /// An optional copy of a temporary object to another
+ /// temporary object, which is permitted (but not required) by
+ /// C++98/03 but not C++0x.
+ SK_ExtraneousCopyToTemporary,
+
+ /// Direct-initialization from a reference-related object in the
+ /// final stage of class copy-initialization.
+ SK_FinalCopy,
+
+ /// Perform a user-defined conversion, either via a conversion
+ /// function or via a constructor.
+ SK_UserConversion,
+
+ /// Perform a qualification conversion, producing a prvalue.
+ SK_QualificationConversionPRValue,
+
+ /// Perform a qualification conversion, producing an xvalue.
+ SK_QualificationConversionXValue,
+
+ /// Perform a qualification conversion, producing an lvalue.
+ SK_QualificationConversionLValue,
+
+ /// Perform a function reference conversion, see [dcl.init.ref]p4.
+ SK_FunctionReferenceConversion,
+
+ /// Perform a conversion adding _Atomic to a type.
+ SK_AtomicConversion,
+
+ /// Perform an implicit conversion sequence.
+ SK_ConversionSequence,
+
+ /// Perform an implicit conversion sequence without narrowing.
+ SK_ConversionSequenceNoNarrowing,
+
+ /// Perform list-initialization without a constructor.
+ SK_ListInitialization,
+
+ /// Unwrap the single-element initializer list for a reference.
+ SK_UnwrapInitList,
+
+ /// Rewrap the single-element initializer list for a reference.
+ SK_RewrapInitList,
+
+ /// Perform initialization via a constructor.
+ SK_ConstructorInitialization,
+
+ /// Perform initialization via a constructor, taking arguments from
+ /// a single InitListExpr.
+ SK_ConstructorInitializationFromList,
+
+ /// Zero-initialize the object
+ SK_ZeroInitialization,
+
+ /// C assignment
+ SK_CAssignment,
+
+ /// Initialization by string
+ SK_StringInit,
+
+ /// An initialization that "converts" an Objective-C object
+ /// (not a point to an object) to another Objective-C object type.
+ SK_ObjCObjectConversion,
+
+ /// Array indexing for initialization by elementwise copy.
+ SK_ArrayLoopIndex,
+
+ /// Array initialization by elementwise copy.
+ SK_ArrayLoopInit,
+
+ /// Array initialization (from an array rvalue).
+ SK_ArrayInit,
+
+ /// Array initialization (from an array rvalue) as a GNU extension.
+ SK_GNUArrayInit,
+
+ /// Array initialization from a parenthesized initializer list.
+ /// This is a GNU C++ extension.
+ SK_ParenthesizedArrayInit,
+
+ /// Pass an object by indirect copy-and-restore.
+ SK_PassByIndirectCopyRestore,
+
+ /// Pass an object by indirect restore.
+ SK_PassByIndirectRestore,
+
+ /// Produce an Objective-C object pointer.
+ SK_ProduceObjCObject,
+
+ /// Construct a std::initializer_list from an initializer list.
+ SK_StdInitializerList,
+
+ /// Perform initialization via a constructor taking a single
+ /// std::initializer_list argument.
+ SK_StdInitializerListConstructorCall,
+
+ /// Initialize an OpenCL sampler from an integer.
+ SK_OCLSamplerInit,
+
+ /// Initialize an opaque OpenCL type (event_t, queue_t, etc.) with zero
+ SK_OCLZeroOpaqueType,
+
+ /// Initialize an aggreagate with parenthesized list of values.
+ /// This is a C++20 feature.
+ SK_ParenthesizedListInit
+ };
+
+ /// A single step in the initialization sequence.
+ class Step {
+ public:
+ /// The kind of conversion or initialization step we are taking.
+ StepKind Kind;
+
+ // The type that results from this initialization.
+ QualType Type;
+
+ struct F {
+ bool HadMultipleCandidates;
+ FunctionDecl *Function;
+ DeclAccessPair FoundDecl;
+ };
+
+ union {
+ /// When Kind == SK_ResolvedOverloadedFunction or Kind ==
+ /// SK_UserConversion, the function that the expression should be
+ /// resolved to or the conversion function to call, respectively.
+ /// When Kind == SK_ConstructorInitialization or SK_ListConstruction,
+ /// the constructor to be called.
+ ///
+ /// Always a FunctionDecl, plus a Boolean flag telling if it was
+ /// selected from an overloaded set having size greater than 1.
+ /// For conversion decls, the naming class is the source type.
+ /// For construct decls, the naming class is the target type.
+ struct F Function;
+
+ /// When Kind = SK_ConversionSequence, the implicit conversion
+ /// sequence.
+ ImplicitConversionSequence *ICS;
+
+ /// When Kind = SK_RewrapInitList, the syntactic form of the
+ /// wrapping list.
+ InitListExpr *WrappingSyntacticList;
+ };
+
+ void Destroy();
+ };
+
+private:
+ /// The kind of initialization sequence computed.
+ enum SequenceKind SequenceKind;
+
+ /// Steps taken by this initialization.
+ SmallVector<Step, 4> Steps;
+
+public:
+ /// Describes why initialization failed.
+ enum FailureKind {
+ /// Too many initializers provided for a reference.
+ FK_TooManyInitsForReference,
+
+ /// Reference initialized from a parenthesized initializer list.
+ FK_ParenthesizedListInitForReference,
+
+ /// Array must be initialized with an initializer list.
+ FK_ArrayNeedsInitList,
+
+ /// Array must be initialized with an initializer list or a
+ /// string literal.
+ FK_ArrayNeedsInitListOrStringLiteral,
+
+ /// Array must be initialized with an initializer list or a
+ /// wide string literal.
+ FK_ArrayNeedsInitListOrWideStringLiteral,
+
+ /// Initializing a wide char array with narrow string literal.
+ FK_NarrowStringIntoWideCharArray,
+
+ /// Initializing char array with wide string literal.
+ FK_WideStringIntoCharArray,
+
+ /// Initializing wide char array with incompatible wide string
+ /// literal.
+ FK_IncompatWideStringIntoWideChar,
+
+ /// Initializing char8_t array with plain string literal.
+ FK_PlainStringIntoUTF8Char,
+
+ /// Initializing char array with UTF-8 string literal.
+ FK_UTF8StringIntoPlainChar,
+
+ /// Array type mismatch.
+ FK_ArrayTypeMismatch,
+
+ /// Non-constant array initializer
+ FK_NonConstantArrayInit,
+
+ /// Cannot resolve the address of an overloaded function.
+ FK_AddressOfOverloadFailed,
+
+ /// Overloading due to reference initialization failed.
+ FK_ReferenceInitOverloadFailed,
+
+ /// Non-const lvalue reference binding to a temporary.
+ FK_NonConstLValueReferenceBindingToTemporary,
+
+ /// Non-const lvalue reference binding to a bit-field.
+ FK_NonConstLValueReferenceBindingToBitfield,
+
+ /// Non-const lvalue reference binding to a vector element.
+ FK_NonConstLValueReferenceBindingToVectorElement,
+
+ /// Non-const lvalue reference binding to a matrix element.
+ FK_NonConstLValueReferenceBindingToMatrixElement,
+
+ /// Non-const lvalue reference binding to an lvalue of unrelated
+ /// type.
+ FK_NonConstLValueReferenceBindingToUnrelated,
+
+ /// Rvalue reference binding to an lvalue.
+ FK_RValueReferenceBindingToLValue,
+
+ /// Reference binding drops qualifiers.
+ FK_ReferenceInitDropsQualifiers,
+
+ /// Reference with mismatching address space binding to temporary.
+ FK_ReferenceAddrspaceMismatchTemporary,
+
+ /// Reference binding failed.
+ FK_ReferenceInitFailed,
+
+ /// Implicit conversion failed.
+ FK_ConversionFailed,
+
+ /// Implicit conversion failed.
+ FK_ConversionFromPropertyFailed,
+
+ /// Too many initializers for scalar
+ FK_TooManyInitsForScalar,
+
+ /// Scalar initialized from a parenthesized initializer list.
+ FK_ParenthesizedListInitForScalar,
+
+ /// Reference initialization from an initializer list
+ FK_ReferenceBindingToInitList,
+
+ /// Initialization of some unused destination type with an
+ /// initializer list.
+ FK_InitListBadDestinationType,
+
+ /// Overloading for a user-defined conversion failed.
+ FK_UserConversionOverloadFailed,
+
+ /// Overloading for initialization by constructor failed.
+ FK_ConstructorOverloadFailed,
+
+ /// Overloading for list-initialization by constructor failed.
+ FK_ListConstructorOverloadFailed,
+
+ /// Default-initialization of a 'const' object.
+ FK_DefaultInitOfConst,
+
+ /// Initialization of an incomplete type.
+ FK_Incomplete,
+
+ /// Variable-length array must not have an initializer.
+ FK_VariableLengthArrayHasInitializer,
+
+ /// List initialization failed at some point.
+ FK_ListInitializationFailed,
+
+ /// Initializer has a placeholder type which cannot be
+ /// resolved by initialization.
+ FK_PlaceholderType,
+
+ /// Trying to take the address of a function that doesn't support
+ /// having its address taken.
+ FK_AddressOfUnaddressableFunction,
+
+ /// List-copy-initialization chose an explicit constructor.
+ FK_ExplicitConstructor,
+
+ /// Parenthesized list initialization failed at some point.
+ /// This is a C++20 feature.
+ FK_ParenthesizedListInitFailed,
+ };
+
+private:
+ /// The reason why initialization failed.
+ FailureKind Failure;
+
+ /// The failed result of overload resolution.
+ OverloadingResult FailedOverloadResult;
+
+ /// The candidate set created when initialization failed.
+ OverloadCandidateSet FailedCandidateSet;
+
+ /// The incomplete type that caused a failure.
+ QualType FailedIncompleteType;
+
+ /// The fixit that needs to be applied to make this initialization
+ /// succeed.
+ std::string ZeroInitializationFixit;
+ SourceLocation ZeroInitializationFixitLoc;
+
+public:
+ /// Call for initializations are invalid but that would be valid
+ /// zero initialzations if Fixit was applied.
+ void SetZeroInitializationFixit(const std::string& Fixit, SourceLocation L) {
+ ZeroInitializationFixit = Fixit;
+ ZeroInitializationFixitLoc = L;
+ }
+
+private:
+ /// Prints a follow-up note that highlights the location of
+ /// the initialized entity, if it's remote.
+ void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity);
+
+public:
+ /// Try to perform initialization of the given entity, creating a
+ /// record of the steps required to perform the initialization.
+ ///
+ /// The generated initialization sequence will either contain enough
+ /// information to diagnose
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization.
+ ///
+ /// \param TopLevelOfInitList true if we are initializing from an expression
+ /// at the top level inside an initializer list. This disallows
+ /// narrowing conversions in C++11 onwards.
+ /// \param TreatUnavailableAsInvalid true if we want to treat unavailable
+ /// as invalid.
+ InitializationSequence(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ bool TopLevelOfInitList = false,
+ bool TreatUnavailableAsInvalid = true);
+ void InitializeFrom(Sema &S, const InitializedEntity &Entity,
+ const InitializationKind &Kind, MultiExprArg Args,
+ bool TopLevelOfInitList, bool TreatUnavailableAsInvalid);
+
+ ~InitializationSequence();
+
+ /// Perform the actual initialization of the given entity based on
+ /// the computed initialization sequence.
+ ///
+ /// \param S the semantic analysis object.
+ ///
+ /// \param Entity the entity being initialized.
+ ///
+ /// \param Kind the kind of initialization being performed.
+ ///
+ /// \param Args the argument(s) provided for initialization, ownership of
+ /// which is transferred into the routine.
+ ///
+ /// \param ResultType if non-NULL, will be set to the type of the
+ /// initialized object, which is the type of the declaration in most
+ /// cases. However, when the initialized object is a variable of
+ /// incomplete array type and the initializer is an initializer
+ /// list, this type will be set to the completed array type.
+ ///
+ /// \returns an expression that performs the actual object initialization, if
+ /// the initialization is well-formed. Otherwise, emits diagnostics
+ /// and returns an invalid expression.
+ ExprResult Perform(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ QualType *ResultType = nullptr);
+
+ /// Diagnose an potentially-invalid initialization sequence.
+ ///
+ /// \returns true if the initialization sequence was ill-formed,
+ /// false otherwise.
+ bool Diagnose(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ ArrayRef<Expr *> Args);
+
+ /// Determine the kind of initialization sequence computed.
+ enum SequenceKind getKind() const { return SequenceKind; }
+
+ /// Set the kind of sequence computed.
+ void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
+
+ /// Determine whether the initialization sequence is valid.
+ explicit operator bool() const { return !Failed(); }
+
+ /// Determine whether the initialization sequence is invalid.
+ bool Failed() const { return SequenceKind == FailedSequence; }
+
+ using step_iterator = SmallVectorImpl<Step>::const_iterator;
+
+ step_iterator step_begin() const { return Steps.begin(); }
+ step_iterator step_end() const { return Steps.end(); }
+
+ using step_range = llvm::iterator_range<step_iterator>;
+
+ step_range steps() const { return {step_begin(), step_end()}; }
+
+ /// Determine whether this initialization is a direct reference
+ /// binding (C++ [dcl.init.ref]).
+ bool isDirectReferenceBinding() const;
+
+ /// Determine whether this initialization failed due to an ambiguity.
+ bool isAmbiguous() const;
+
+ /// Determine whether this initialization is direct call to a
+ /// constructor.
+ bool isConstructorInitialization() const;
+
+ /// Add a new step in the initialization that resolves the address
+ /// of an overloaded function to a specific function declaration.
+ ///
+ /// \param Function the function to which the overloaded function reference
+ /// resolves.
+ void AddAddressOverloadResolutionStep(FunctionDecl *Function,
+ DeclAccessPair Found,
+ bool HadMultipleCandidates);
+
+ /// Add a new step in the initialization that performs a derived-to-
+ /// base cast.
+ ///
+ /// \param BaseType the base type to which we will be casting.
+ ///
+ /// \param Category Indicates whether the result will be treated as an
+ /// rvalue, an xvalue, or an lvalue.
+ void AddDerivedToBaseCastStep(QualType BaseType,
+ ExprValueKind Category);
+
+ /// Add a new step binding a reference to an object.
+ ///
+ /// \param BindingTemporary True if we are binding a reference to a temporary
+ /// object (thereby extending its lifetime); false if we are binding to an
+ /// lvalue or an lvalue treated as an rvalue.
+ void AddReferenceBindingStep(QualType T, bool BindingTemporary);
+
+ /// Add a new step that makes an extraneous copy of the input
+ /// to a temporary of the same class type.
+ ///
+ /// This extraneous copy only occurs during reference binding in
+ /// C++98/03, where we are permitted (but not required) to introduce
+ /// an extra copy. At a bare minimum, we must check that we could
+ /// call the copy constructor, and produce a diagnostic if the copy
+ /// constructor is inaccessible or no copy constructor matches.
+ //
+ /// \param T The type of the temporary being created.
+ void AddExtraneousCopyToTemporary(QualType T);
+
+ /// Add a new step that makes a copy of the input to an object of
+ /// the given type, as the final step in class copy-initialization.
+ void AddFinalCopy(QualType T);
+
+ /// Add a new step invoking a conversion function, which is either
+ /// a constructor or a conversion function.
+ void AddUserConversionStep(FunctionDecl *Function,
+ DeclAccessPair FoundDecl,
+ QualType T,
+ bool HadMultipleCandidates);
+
+ /// Add a new step that performs a qualification conversion to the
+ /// given type.
+ void AddQualificationConversionStep(QualType Ty,
+ ExprValueKind Category);
+
+ /// Add a new step that performs a function reference conversion to the
+ /// given type.
+ void AddFunctionReferenceConversionStep(QualType Ty);
+
+ /// Add a new step that performs conversion from non-atomic to atomic
+ /// type.
+ void AddAtomicConversionStep(QualType Ty);
+
+ /// Add a new step that applies an implicit conversion sequence.
+ void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
+ QualType T, bool TopLevelOfInitList = false);
+
+ /// Add a list-initialization step.
+ void AddListInitializationStep(QualType T);
+
+ /// Add a constructor-initialization step.
+ ///
+ /// \param FromInitList The constructor call is syntactically an initializer
+ /// list.
+ /// \param AsInitList The constructor is called as an init list constructor.
+ void AddConstructorInitializationStep(DeclAccessPair FoundDecl,
+ CXXConstructorDecl *Constructor,
+ QualType T,
+ bool HadMultipleCandidates,
+ bool FromInitList, bool AsInitList);
+
+ /// Add a zero-initialization step.
+ void AddZeroInitializationStep(QualType T);
+
+ /// Add a C assignment step.
+ //
+ // FIXME: It isn't clear whether this should ever be needed;
+ // ideally, we would handle everything needed in C in the common
+ // path. However, that isn't the case yet.
+ void AddCAssignmentStep(QualType T);
+
+ /// Add a string init step.
+ void AddStringInitStep(QualType T);
+
+ /// Add an Objective-C object conversion step, which is
+ /// always a no-op.
+ void AddObjCObjectConversionStep(QualType T);
+
+ /// Add an array initialization loop step.
+ void AddArrayInitLoopStep(QualType T, QualType EltTy);
+
+ /// Add an array initialization step.
+ void AddArrayInitStep(QualType T, bool IsGNUExtension);
+
+ /// Add a parenthesized array initialization step.
+ void AddParenthesizedArrayInitStep(QualType T);
+
+ /// Add a step to pass an object by indirect copy-restore.
+ void AddPassByIndirectCopyRestoreStep(QualType T, bool shouldCopy);
+
+ /// Add a step to "produce" an Objective-C object (by
+ /// retaining it).
+ void AddProduceObjCObjectStep(QualType T);
+
+ /// Add a step to construct a std::initializer_list object from an
+ /// initializer list.
+ void AddStdInitializerListConstructionStep(QualType T);
+
+ /// Add a step to initialize an OpenCL sampler from an integer
+ /// constant.
+ void AddOCLSamplerInitStep(QualType T);
+
+ /// Add a step to initialzie an OpenCL opaque type (event_t, queue_t, etc.)
+ /// from a zero constant.
+ void AddOCLZeroOpaqueTypeStep(QualType T);
+
+ void AddParenthesizedListInitStep(QualType T);
+
+ /// Add steps to unwrap a initializer list for a reference around a
+ /// single element and rewrap it at the end.
+ void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);
+
+ /// Note that this initialization sequence failed.
+ void SetFailed(FailureKind Failure) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ assert((Failure != FK_Incomplete || !FailedIncompleteType.isNull()) &&
+ "Incomplete type failure requires a type!");
+ }
+
+ /// Note that this initialization sequence failed due to failed
+ /// overload resolution.
+ void SetOverloadFailure(FailureKind Failure, OverloadingResult Result);
+
+ /// Retrieve a reference to the candidate set when overload
+ /// resolution fails.
+ OverloadCandidateSet &getFailedCandidateSet() {
+ return FailedCandidateSet;
+ }
+
+ /// Get the overloading result, for when the initialization
+ /// sequence failed due to a bad overload.
+ OverloadingResult getFailedOverloadResult() const {
+ return FailedOverloadResult;
+ }
+
+ /// Note that this initialization sequence failed due to an
+ /// incomplete type.
+ void setIncompleteTypeFailure(QualType IncompleteType) {
+ FailedIncompleteType = IncompleteType;
+ SetFailed(FK_Incomplete);
+ }
+
+ /// Determine why initialization failed.
+ FailureKind getFailureKind() const {
+ assert(Failed() && "Not an initialization failure!");
+ return Failure;
+ }
+
+ /// Dump a representation of this initialization sequence to
+ /// the given stream, for debugging purposes.
+ void dump(raw_ostream &OS) const;
+
+ /// Dump a representation of this initialization sequence to
+ /// standard error, for debugging purposes.
+ void dump() const;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_INITIALIZATION_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Lookup.h b/contrib/libs/clang16/include/clang/Sema/Lookup.h
new file mode 100644
index 0000000000..e3378daa0e
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Lookup.h
@@ -0,0 +1,863 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Lookup.h - Classes for name lookup -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LookupResult class, which is integral to
+// Sema's name-lookup subsystem.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_LOOKUP_H
+#define LLVM_CLANG_SEMA_LOOKUP_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <optional>
+#include <utility>
+
+namespace clang {
+
+class CXXBasePaths;
+
+/// Represents the results of name lookup.
+///
+/// An instance of the LookupResult class captures the results of a
+/// single name lookup, which can return no result (nothing found),
+/// a single declaration, a set of overloaded functions, or an
+/// ambiguity. Use the getKind() method to determine which of these
+/// results occurred for a given lookup.
+class LookupResult {
+public:
+ enum LookupResultKind {
+ /// No entity found met the criteria.
+ NotFound = 0,
+
+ /// No entity found met the criteria within the current
+ /// instantiation,, but there were dependent base classes of the
+ /// current instantiation that could not be searched.
+ NotFoundInCurrentInstantiation,
+
+ /// Name lookup found a single declaration that met the
+ /// criteria. getFoundDecl() will return this declaration.
+ Found,
+
+ /// Name lookup found a set of overloaded functions that
+ /// met the criteria.
+ FoundOverloaded,
+
+ /// Name lookup found an unresolvable value declaration
+ /// and cannot yet complete. This only happens in C++ dependent
+ /// contexts with dependent using declarations.
+ FoundUnresolvedValue,
+
+ /// Name lookup results in an ambiguity; use
+ /// getAmbiguityKind to figure out what kind of ambiguity
+ /// we have.
+ Ambiguous
+ };
+
+ enum AmbiguityKind {
+ /// Name lookup results in an ambiguity because multiple
+ /// entities that meet the lookup criteria were found in
+ /// subobjects of different types. For example:
+ /// @code
+ /// struct A { void f(int); }
+ /// struct B { void f(double); }
+ /// struct C : A, B { };
+ /// void test(C c) {
+ /// c.f(0); // error: A::f and B::f come from subobjects of different
+ /// // types. overload resolution is not performed.
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjectTypes,
+
+ /// Name lookup results in an ambiguity because multiple
+ /// nonstatic entities that meet the lookup criteria were found
+ /// in different subobjects of the same type. For example:
+ /// @code
+ /// struct A { int x; };
+ /// struct B : A { };
+ /// struct C : A { };
+ /// struct D : B, C { };
+ /// int test(D d) {
+ /// return d.x; // error: 'x' is found in two A subobjects (of B and C)
+ /// }
+ /// @endcode
+ AmbiguousBaseSubobjects,
+
+ /// Name lookup results in an ambiguity because multiple definitions
+ /// of entity that meet the lookup criteria were found in different
+ /// declaration contexts.
+ /// @code
+ /// namespace A {
+ /// int i;
+ /// namespace B { int i; }
+ /// int test() {
+ /// using namespace B;
+ /// return i; // error 'i' is found in namespace A and A::B
+ /// }
+ /// }
+ /// @endcode
+ AmbiguousReference,
+
+ /// Name lookup results in an ambiguity because an entity with a
+ /// tag name was hidden by an entity with an ordinary name from
+ /// a different context.
+ /// @code
+ /// namespace A { struct Foo {}; }
+ /// namespace B { void Foo(); }
+ /// namespace C {
+ /// using namespace A;
+ /// using namespace B;
+ /// }
+ /// void test() {
+ /// C::Foo(); // error: tag 'A::Foo' is hidden by an object in a
+ /// // different namespace
+ /// }
+ /// @endcode
+ AmbiguousTagHiding
+ };
+
+ /// A little identifier for flagging temporary lookup results.
+ enum TemporaryToken {
+ Temporary
+ };
+
+ using iterator = UnresolvedSetImpl::iterator;
+
+ LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo,
+ Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
+ Diagnose(Redecl == Sema::NotForRedeclaration) {
+ configure();
+ }
+
+ // TODO: consider whether this constructor should be restricted to take
+ // as input a const IdentifierInfo* (instead of Name),
+ // forcing other cases towards the constructor taking a DNInfo.
+ LookupResult(Sema &SemaRef, DeclarationName Name,
+ SourceLocation NameLoc, Sema::LookupNameKind LookupKind,
+ Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
+ : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind),
+ Redecl(Redecl != Sema::NotForRedeclaration),
+ ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
+ Diagnose(Redecl == Sema::NotForRedeclaration) {
+ configure();
+ }
+
+ /// Creates a temporary lookup result, initializing its core data
+ /// using the information from another result. Diagnostics are always
+ /// disabled.
+ LookupResult(TemporaryToken _, const LookupResult &Other)
+ : SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo),
+ LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl),
+ ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags),
+ AllowHidden(Other.AllowHidden),
+ TemplateNameLookup(Other.TemplateNameLookup) {}
+
+ // FIXME: Remove these deleted methods once the default build includes
+ // -Wdeprecated.
+ LookupResult(const LookupResult &) = delete;
+ LookupResult &operator=(const LookupResult &) = delete;
+
+ LookupResult(LookupResult &&Other)
+ : ResultKind(std::move(Other.ResultKind)),
+ Ambiguity(std::move(Other.Ambiguity)), Decls(std::move(Other.Decls)),
+ Paths(std::move(Other.Paths)),
+ NamingClass(std::move(Other.NamingClass)),
+ BaseObjectType(std::move(Other.BaseObjectType)),
+ SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)),
+ NameContextRange(std::move(Other.NameContextRange)),
+ LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)),
+ Redecl(std::move(Other.Redecl)),
+ ExternalRedecl(std::move(Other.ExternalRedecl)),
+ HideTags(std::move(Other.HideTags)),
+ Diagnose(std::move(Other.Diagnose)),
+ AllowHidden(std::move(Other.AllowHidden)),
+ Shadowed(std::move(Other.Shadowed)),
+ TemplateNameLookup(std::move(Other.TemplateNameLookup)) {
+ Other.Paths = nullptr;
+ Other.Diagnose = false;
+ }
+
+ LookupResult &operator=(LookupResult &&Other) {
+ ResultKind = std::move(Other.ResultKind);
+ Ambiguity = std::move(Other.Ambiguity);
+ Decls = std::move(Other.Decls);
+ Paths = std::move(Other.Paths);
+ NamingClass = std::move(Other.NamingClass);
+ BaseObjectType = std::move(Other.BaseObjectType);
+ SemaPtr = std::move(Other.SemaPtr);
+ NameInfo = std::move(Other.NameInfo);
+ NameContextRange = std::move(Other.NameContextRange);
+ LookupKind = std::move(Other.LookupKind);
+ IDNS = std::move(Other.IDNS);
+ Redecl = std::move(Other.Redecl);
+ ExternalRedecl = std::move(Other.ExternalRedecl);
+ HideTags = std::move(Other.HideTags);
+ Diagnose = std::move(Other.Diagnose);
+ AllowHidden = std::move(Other.AllowHidden);
+ Shadowed = std::move(Other.Shadowed);
+ TemplateNameLookup = std::move(Other.TemplateNameLookup);
+ Other.Paths = nullptr;
+ Other.Diagnose = false;
+ return *this;
+ }
+
+ ~LookupResult() {
+ if (Diagnose) diagnose();
+ if (Paths) deletePaths(Paths);
+ }
+
+ /// Gets the name info to look up.
+ const DeclarationNameInfo &getLookupNameInfo() const {
+ return NameInfo;
+ }
+
+ /// Sets the name info to look up.
+ void setLookupNameInfo(const DeclarationNameInfo &NameInfo) {
+ this->NameInfo = NameInfo;
+ }
+
+ /// Gets the name to look up.
+ DeclarationName getLookupName() const {
+ return NameInfo.getName();
+ }
+
+ /// Sets the name to look up.
+ void setLookupName(DeclarationName Name) {
+ NameInfo.setName(Name);
+ }
+
+ /// Gets the kind of lookup to perform.
+ Sema::LookupNameKind getLookupKind() const {
+ return LookupKind;
+ }
+
+ /// True if this lookup is just looking for an existing declaration.
+ bool isForRedeclaration() const {
+ return Redecl;
+ }
+
+ /// True if this lookup is just looking for an existing declaration to link
+ /// against a declaration with external linkage.
+ bool isForExternalRedeclaration() const {
+ return ExternalRedecl;
+ }
+
+ Sema::RedeclarationKind redeclarationKind() const {
+ return ExternalRedecl ? Sema::ForExternalRedeclaration :
+ Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration;
+ }
+
+ /// Specify whether hidden declarations are visible, e.g.,
+ /// for recovery reasons.
+ void setAllowHidden(bool AH) {
+ AllowHidden = AH;
+ }
+
+ /// Determine whether this lookup is permitted to see hidden
+ /// declarations, such as those in modules that have not yet been imported.
+ bool isHiddenDeclarationVisible(NamedDecl *ND) const {
+ return AllowHidden ||
+ (isForExternalRedeclaration() && ND->isExternallyDeclarable());
+ }
+
+ /// Sets whether tag declarations should be hidden by non-tag
+ /// declarations during resolution. The default is true.
+ void setHideTags(bool Hide) {
+ HideTags = Hide;
+ }
+
+ /// Sets whether this is a template-name lookup. For template-name lookups,
+ /// injected-class-names are treated as naming a template rather than a
+ /// template specialization.
+ void setTemplateNameLookup(bool TemplateName) {
+ TemplateNameLookup = TemplateName;
+ }
+
+ bool isTemplateNameLookup() const { return TemplateNameLookup; }
+
+ bool isAmbiguous() const {
+ return getResultKind() == Ambiguous;
+ }
+
+ /// Determines if this names a single result which is not an
+ /// unresolved value using decl. If so, it is safe to call
+ /// getFoundDecl().
+ bool isSingleResult() const {
+ return getResultKind() == Found;
+ }
+
+ /// Determines if the results are overloaded.
+ bool isOverloadedResult() const {
+ return getResultKind() == FoundOverloaded;
+ }
+
+ bool isUnresolvableResult() const {
+ return getResultKind() == FoundUnresolvedValue;
+ }
+
+ LookupResultKind getResultKind() const {
+ assert(checkDebugAssumptions());
+ return ResultKind;
+ }
+
+ AmbiguityKind getAmbiguityKind() const {
+ assert(isAmbiguous());
+ return Ambiguity;
+ }
+
+ const UnresolvedSetImpl &asUnresolvedSet() const {
+ return Decls;
+ }
+
+ iterator begin() const { return iterator(Decls.begin()); }
+ iterator end() const { return iterator(Decls.end()); }
+
+ /// Return true if no decls were found
+ bool empty() const { return Decls.empty(); }
+
+ /// Return the base paths structure that's associated with
+ /// these results, or null if none is.
+ CXXBasePaths *getBasePaths() const {
+ return Paths;
+ }
+
+ /// Determine whether the given declaration is visible to the
+ /// program.
+ static bool isVisible(Sema &SemaRef, NamedDecl *D);
+
+ static bool isReachable(Sema &SemaRef, NamedDecl *D);
+
+ static bool isAcceptable(Sema &SemaRef, NamedDecl *D,
+ Sema::AcceptableKind Kind) {
+ return Kind == Sema::AcceptableKind::Visible ? isVisible(SemaRef, D)
+ : isReachable(SemaRef, D);
+ }
+
+ /// Determine whether this lookup is permitted to see the declaration.
+ /// Note that a reachable but not visible declaration inhabiting a namespace
+ /// is not allowed to be seen during name lookup.
+ ///
+ /// For example:
+ /// ```
+ /// // m.cppm
+ /// export module m;
+ /// struct reachable { int v; }
+ /// export auto func() { return reachable{43}; }
+ /// // Use.cpp
+ /// import m;
+ /// auto Use() {
+ /// // Not valid. We couldn't see reachable here.
+ /// // So isAvailableForLookup would return false when we look
+ /// up 'reachable' here.
+ /// // return reachable(43).v;
+ /// // Valid. The field name 'v' is allowed during name lookup.
+ /// // So isAvailableForLookup would return true when we look up 'v' here.
+ /// return func().v;
+ /// }
+ /// ```
+ static bool isAvailableForLookup(Sema &SemaRef, NamedDecl *ND);
+
+ /// Retrieve the accepted (re)declaration of the given declaration,
+ /// if there is one.
+ NamedDecl *getAcceptableDecl(NamedDecl *D) const {
+ if (!D->isInIdentifierNamespace(IDNS))
+ return nullptr;
+
+ if (isAvailableForLookup(getSema(), D) || isHiddenDeclarationVisible(D))
+ return D;
+
+ return getAcceptableDeclSlow(D);
+ }
+
+private:
+ static bool isAcceptableSlow(Sema &SemaRef, NamedDecl *D,
+ Sema::AcceptableKind Kind);
+ static bool isReachableSlow(Sema &SemaRef, NamedDecl *D);
+ NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
+
+public:
+ /// Returns the identifier namespace mask for this lookup.
+ unsigned getIdentifierNamespace() const {
+ return IDNS;
+ }
+
+ /// Returns whether these results arose from performing a
+ /// lookup into a class.
+ bool isClassLookup() const {
+ return NamingClass != nullptr;
+ }
+
+ /// Returns the 'naming class' for this lookup, i.e. the
+ /// class which was looked into to find these results.
+ ///
+ /// C++0x [class.access.base]p5:
+ /// The access to a member is affected by the class in which the
+ /// member is named. This naming class is the class in which the
+ /// member name was looked up and found. [Note: this class can be
+ /// explicit, e.g., when a qualified-id is used, or implicit,
+ /// e.g., when a class member access operator (5.2.5) is used
+ /// (including cases where an implicit "this->" is added). If both
+ /// a class member access operator and a qualified-id are used to
+ /// name the member (as in p->T::m), the class naming the member
+ /// is the class named by the nested-name-specifier of the
+ /// qualified-id (that is, T). -- end note ]
+ ///
+ /// This is set by the lookup routines when they find results in a class.
+ CXXRecordDecl *getNamingClass() const {
+ return NamingClass;
+ }
+
+ /// Sets the 'naming class' for this lookup.
+ void setNamingClass(CXXRecordDecl *Record) {
+ NamingClass = Record;
+ }
+
+ /// Returns the base object type associated with this lookup;
+ /// important for [class.protected]. Most lookups do not have an
+ /// associated base object.
+ QualType getBaseObjectType() const {
+ return BaseObjectType;
+ }
+
+ /// Sets the base object type for this lookup.
+ void setBaseObjectType(QualType T) {
+ BaseObjectType = T;
+ }
+
+ /// Add a declaration to these results with its natural access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D) {
+ addDecl(D, D->getAccess());
+ }
+
+ /// Add a declaration to these results with the given access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D, AccessSpecifier AS) {
+ Decls.addDecl(D, AS);
+ ResultKind = Found;
+ }
+
+ /// Add all the declarations from another set of lookup
+ /// results.
+ void addAllDecls(const LookupResult &Other) {
+ Decls.append(Other.Decls.begin(), Other.Decls.end());
+ ResultKind = Found;
+ }
+
+ /// Determine whether no result was found because we could not
+ /// search into dependent base classes of the current instantiation.
+ bool wasNotFoundInCurrentInstantiation() const {
+ return ResultKind == NotFoundInCurrentInstantiation;
+ }
+
+ /// Note that while no result was found in the current instantiation,
+ /// there were dependent base classes that could not be searched.
+ void setNotFoundInCurrentInstantiation() {
+ assert(ResultKind == NotFound && Decls.empty());
+ ResultKind = NotFoundInCurrentInstantiation;
+ }
+
+ /// Determine whether the lookup result was shadowed by some other
+ /// declaration that lookup ignored.
+ bool isShadowed() const { return Shadowed; }
+
+ /// Note that we found and ignored a declaration while performing
+ /// lookup.
+ void setShadowed() { Shadowed = true; }
+
+ /// Resolves the result kind of the lookup, possibly hiding
+ /// decls.
+ ///
+ /// This should be called in any environment where lookup might
+ /// generate multiple lookup results.
+ void resolveKind();
+
+ /// Re-resolves the result kind of the lookup after a set of
+ /// removals has been performed.
+ void resolveKindAfterFilter() {
+ if (Decls.empty()) {
+ if (ResultKind != NotFoundInCurrentInstantiation)
+ ResultKind = NotFound;
+
+ if (Paths) {
+ deletePaths(Paths);
+ Paths = nullptr;
+ }
+ } else {
+ std::optional<AmbiguityKind> SavedAK;
+ bool WasAmbiguous = false;
+ if (ResultKind == Ambiguous) {
+ SavedAK = Ambiguity;
+ WasAmbiguous = true;
+ }
+ ResultKind = Found;
+ resolveKind();
+
+ // If we didn't make the lookup unambiguous, restore the old
+ // ambiguity kind.
+ if (ResultKind == Ambiguous) {
+ (void)WasAmbiguous;
+ assert(WasAmbiguous);
+ Ambiguity = *SavedAK;
+ } else if (Paths) {
+ deletePaths(Paths);
+ Paths = nullptr;
+ }
+ }
+ }
+
+ template <class DeclClass>
+ DeclClass *getAsSingle() const {
+ if (getResultKind() != Found) return nullptr;
+ return dyn_cast<DeclClass>(getFoundDecl());
+ }
+
+ /// Fetch the unique decl found by this lookup. Asserts
+ /// that one was found.
+ ///
+ /// This is intended for users who have examined the result kind
+ /// and are certain that there is only one result.
+ NamedDecl *getFoundDecl() const {
+ assert(getResultKind() == Found
+ && "getFoundDecl called on non-unique result");
+ return (*begin())->getUnderlyingDecl();
+ }
+
+ /// Fetches a representative decl. Useful for lazy diagnostics.
+ NamedDecl *getRepresentativeDecl() const {
+ assert(!Decls.empty() && "cannot get representative of empty set");
+ return *begin();
+ }
+
+ /// Asks if the result is a single tag decl.
+ bool isSingleTagDecl() const {
+ return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
+ }
+
+ /// Make these results show that the name was found in
+ /// base classes of different types.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
+
+ /// Make these results show that the name was found in
+ /// distinct base classes of the same type.
+ ///
+ /// The given paths object is copied and invalidated.
+ void setAmbiguousBaseSubobjects(CXXBasePaths &P);
+
+ /// Make these results show that the name was found in
+ /// different contexts and a tag decl was hidden by an ordinary
+ /// decl in a different context.
+ void setAmbiguousQualifiedTagHiding() {
+ setAmbiguous(AmbiguousTagHiding);
+ }
+
+ /// Clears out any current state.
+ LLVM_ATTRIBUTE_REINITIALIZES void clear() {
+ ResultKind = NotFound;
+ Decls.clear();
+ if (Paths) deletePaths(Paths);
+ Paths = nullptr;
+ NamingClass = nullptr;
+ Shadowed = false;
+ }
+
+ /// Clears out any current state and re-initializes for a
+ /// different kind of lookup.
+ void clear(Sema::LookupNameKind Kind) {
+ clear();
+ LookupKind = Kind;
+ configure();
+ }
+
+ /// Change this lookup's redeclaration kind.
+ void setRedeclarationKind(Sema::RedeclarationKind RK) {
+ Redecl = (RK != Sema::NotForRedeclaration);
+ ExternalRedecl = (RK == Sema::ForExternalRedeclaration);
+ configure();
+ }
+
+ void dump();
+ void print(raw_ostream &);
+
+ /// Suppress the diagnostics that would normally fire because of this
+ /// lookup. This happens during (e.g.) redeclaration lookups.
+ void suppressDiagnostics() {
+ Diagnose = false;
+ }
+
+ /// Determines whether this lookup is suppressing diagnostics.
+ bool isSuppressingDiagnostics() const {
+ return !Diagnose;
+ }
+
+ /// Sets a 'context' source range.
+ void setContextRange(SourceRange SR) {
+ NameContextRange = SR;
+ }
+
+ /// Gets the source range of the context of this name; for C++
+ /// qualified lookups, this is the source range of the scope
+ /// specifier.
+ SourceRange getContextRange() const {
+ return NameContextRange;
+ }
+
+ /// Gets the location of the identifier. This isn't always defined:
+ /// sometimes we're doing lookups on synthesized names.
+ SourceLocation getNameLoc() const {
+ return NameInfo.getLoc();
+ }
+
+ /// Get the Sema object that this lookup result is searching
+ /// with.
+ Sema &getSema() const { return *SemaPtr; }
+
+ /// A class for iterating through a result set and possibly
+ /// filtering out results. The results returned are possibly
+ /// sugared.
+ class Filter {
+ friend class LookupResult;
+
+ LookupResult &Results;
+ LookupResult::iterator I;
+ bool Changed = false;
+ bool CalledDone = false;
+
+ Filter(LookupResult &Results) : Results(Results), I(Results.begin()) {}
+
+ public:
+ Filter(Filter &&F)
+ : Results(F.Results), I(F.I), Changed(F.Changed),
+ CalledDone(F.CalledDone) {
+ F.CalledDone = true;
+ }
+
+ ~Filter() {
+ assert(CalledDone &&
+ "LookupResult::Filter destroyed without done() call");
+ }
+
+ bool hasNext() const {
+ return I != Results.end();
+ }
+
+ NamedDecl *next() {
+ assert(I != Results.end() && "next() called on empty filter");
+ return *I++;
+ }
+
+ /// Restart the iteration.
+ void restart() {
+ I = Results.begin();
+ }
+
+ /// Erase the last element returned from this iterator.
+ void erase() {
+ Results.Decls.erase(--I);
+ Changed = true;
+ }
+
+ /// Replaces the current entry with the given one, preserving the
+ /// access bits.
+ void replace(NamedDecl *D) {
+ Results.Decls.replace(I-1, D);
+ Changed = true;
+ }
+
+ /// Replaces the current entry with the given one.
+ void replace(NamedDecl *D, AccessSpecifier AS) {
+ Results.Decls.replace(I-1, D, AS);
+ Changed = true;
+ }
+
+ void done() {
+ assert(!CalledDone && "done() called twice");
+ CalledDone = true;
+
+ if (Changed)
+ Results.resolveKindAfterFilter();
+ }
+ };
+
+ /// Create a filter for this result set.
+ Filter makeFilter() {
+ return Filter(*this);
+ }
+
+ void setFindLocalExtern(bool FindLocalExtern) {
+ if (FindLocalExtern)
+ IDNS |= Decl::IDNS_LocalExtern;
+ else
+ IDNS &= ~Decl::IDNS_LocalExtern;
+ }
+
+private:
+ void diagnose() {
+ if (isAmbiguous())
+ getSema().DiagnoseAmbiguousLookup(*this);
+ else if (isClassLookup() && getSema().getLangOpts().AccessControl)
+ getSema().CheckLookupAccess(*this);
+ }
+
+ void setAmbiguous(AmbiguityKind AK) {
+ ResultKind = Ambiguous;
+ Ambiguity = AK;
+ }
+
+ void addDeclsFromBasePaths(const CXXBasePaths &P);
+ void configure();
+
+ bool checkDebugAssumptions() const;
+
+ bool checkUnresolved() const {
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ if (isa<UnresolvedUsingValueDecl>((*I)->getUnderlyingDecl()))
+ return true;
+ return false;
+ }
+
+ static void deletePaths(CXXBasePaths *);
+
+ // Results.
+ LookupResultKind ResultKind = NotFound;
+ // ill-defined unless ambiguous. Still need to be initialized it will be
+ // copied/moved.
+ AmbiguityKind Ambiguity = {};
+ UnresolvedSet<8> Decls;
+ CXXBasePaths *Paths = nullptr;
+ CXXRecordDecl *NamingClass = nullptr;
+ QualType BaseObjectType;
+
+ // Parameters.
+ Sema *SemaPtr;
+ DeclarationNameInfo NameInfo;
+ SourceRange NameContextRange;
+ Sema::LookupNameKind LookupKind;
+ unsigned IDNS = 0; // set by configure()
+
+ bool Redecl;
+ bool ExternalRedecl;
+
+ /// True if tag declarations should be hidden if non-tags
+ /// are present
+ bool HideTags = true;
+
+ bool Diagnose = false;
+
+ /// True if we should allow hidden declarations to be 'visible'.
+ bool AllowHidden = false;
+
+ /// True if the found declarations were shadowed by some other
+ /// declaration that we skipped. This only happens when \c LookupKind
+ /// is \c LookupRedeclarationWithLinkage.
+ bool Shadowed = false;
+
+ /// True if we're looking up a template-name.
+ bool TemplateNameLookup = false;
+};
+
+/// Consumes visible declarations found when searching for
+/// all visible names within a given scope or context.
+///
+/// This abstract class is meant to be subclassed by clients of \c
+/// Sema::LookupVisibleDecls(), each of which should override the \c
+/// FoundDecl() function to process declarations as they are found.
+class VisibleDeclConsumer {
+public:
+ /// Destroys the visible declaration consumer.
+ virtual ~VisibleDeclConsumer();
+
+ /// Determine whether hidden declarations (from unimported
+ /// modules) should be given to this consumer. By default, they
+ /// are not included.
+ virtual bool includeHiddenDecls() const;
+
+ /// Invoked each time \p Sema::LookupVisibleDecls() finds a
+ /// declaration visible from the current scope or context.
+ ///
+ /// \param ND the declaration found.
+ ///
+ /// \param Hiding a declaration that hides the declaration \p ND,
+ /// or NULL if no such declaration exists.
+ ///
+ /// \param Ctx the original context from which the lookup started.
+ ///
+ /// \param InBaseClass whether this declaration was found in base
+ /// class of the context we searched.
+ virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) = 0;
+
+ /// Callback to inform the client that Sema entered into a new context
+ /// to find a visible declaration.
+ //
+ /// \param Ctx the context which Sema entered.
+ virtual void EnteredContext(DeclContext *Ctx) {}
+};
+
+/// A class for storing results from argument-dependent lookup.
+class ADLResult {
+private:
+ /// A map from canonical decls to the 'most recent' decl.
+ llvm::MapVector<NamedDecl*, NamedDecl*> Decls;
+
+ struct select_second {
+ NamedDecl *operator()(std::pair<NamedDecl*, NamedDecl*> P) const {
+ return P.second;
+ }
+ };
+
+public:
+ /// Adds a new ADL candidate to this map.
+ void insert(NamedDecl *D);
+
+ /// Removes any data associated with a given decl.
+ void erase(NamedDecl *D) {
+ Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
+ }
+
+ using iterator =
+ llvm::mapped_iterator<decltype(Decls)::iterator, select_second>;
+
+ iterator begin() { return iterator(Decls.begin(), select_second()); }
+ iterator end() { return iterator(Decls.end(), select_second()); }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_LOOKUP_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/MultiplexExternalSemaSource.h b/contrib/libs/clang16/include/clang/Sema/MultiplexExternalSemaSource.h
new file mode 100644
index 0000000000..80022b97e5
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -0,0 +1,385 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- MultiplexExternalSemaSource.h - External Sema Interface-*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ExternalSemaSource interface, dispatching to all clients
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_MULTIPLEXEXTERNALSEMASOURCE_H
+#define LLVM_CLANG_SEMA_MULTIPLEXEXTERNALSEMASOURCE_H
+
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/Weak.h"
+#include "llvm/ADT/SmallVector.h"
+#include <utility>
+
+namespace clang {
+
+ class CXXConstructorDecl;
+ class CXXRecordDecl;
+ class DeclaratorDecl;
+ struct ExternalVTableUse;
+ class LookupResult;
+ class NamespaceDecl;
+ class Scope;
+ class Sema;
+ class TypedefNameDecl;
+ class ValueDecl;
+ class VarDecl;
+
+
+/// An abstract interface that should be implemented by
+/// external AST sources that also provide information for semantic
+/// analysis.
+class MultiplexExternalSemaSource : public ExternalSemaSource {
+ /// LLVM-style RTTI.
+ static char ID;
+
+private:
+ SmallVector<ExternalSemaSource *, 2> Sources;
+
+public:
+ /// Constructs a new multiplexing external sema source and appends the
+ /// given element to it.
+ ///
+ ///\param[in] S1 - A non-null (old) ExternalSemaSource.
+ ///\param[in] S2 - A non-null (new) ExternalSemaSource.
+ ///
+ MultiplexExternalSemaSource(ExternalSemaSource *S1, ExternalSemaSource *S2);
+
+ ~MultiplexExternalSemaSource() override;
+
+ /// Appends new source to the source list.
+ ///
+ ///\param[in] Source - An ExternalSemaSource.
+ ///
+ void AddSource(ExternalSemaSource *Source);
+
+ //===--------------------------------------------------------------------===//
+ // ExternalASTSource.
+ //===--------------------------------------------------------------------===//
+
+ /// Resolve a declaration ID into a declaration, potentially
+ /// building a new declaration.
+ Decl *GetExternalDecl(uint32_t ID) override;
+
+ /// Complete the redeclaration chain if it's been extended since the
+ /// previous generation of the AST source.
+ void CompleteRedeclChain(const Decl *D) override;
+
+ /// Resolve a selector ID into a selector.
+ Selector GetExternalSelector(uint32_t ID) override;
+
+ /// Returns the number of selectors known to the external AST
+ /// source.
+ uint32_t GetNumExternalSelectors() override;
+
+ /// Resolve the offset of a statement in the decl stream into
+ /// a statement.
+ Stmt *GetExternalDeclStmt(uint64_t Offset) override;
+
+ /// Resolve the offset of a set of C++ base specifiers in the decl
+ /// stream into an array of specifiers.
+ CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override;
+
+ /// Resolve a handle to a list of ctor initializers into the list of
+ /// initializers themselves.
+ CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
+
+ ExtKind hasExternalDefinitions(const Decl *D) override;
+
+ /// Find all declarations with the given name in the
+ /// given context.
+ bool FindExternalVisibleDeclsByName(const DeclContext *DC,
+ DeclarationName Name) override;
+
+ /// Ensures that the table of all visible declarations inside this
+ /// context is up to date.
+ void completeVisibleDeclsMap(const DeclContext *DC) override;
+
+ /// Finds all declarations lexically contained within the given
+ /// DeclContext, after applying an optional filter predicate.
+ ///
+ /// \param IsKindWeWant a predicate function that returns true if the passed
+ /// declaration kind is one we are looking for.
+ void
+ FindExternalLexicalDecls(const DeclContext *DC,
+ llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
+ SmallVectorImpl<Decl *> &Result) override;
+
+ /// Get the decls that are contained in a file in the Offset/Length
+ /// range. \p Length can be 0 to indicate a point at \p Offset instead of
+ /// a range.
+ void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length,
+ SmallVectorImpl<Decl *> &Decls) override;
+
+ /// Gives the external AST source an opportunity to complete
+ /// an incomplete type.
+ void CompleteType(TagDecl *Tag) override;
+
+ /// Gives the external AST source an opportunity to complete an
+ /// incomplete Objective-C class.
+ ///
+ /// This routine will only be invoked if the "externally completed" bit is
+ /// set on the ObjCInterfaceDecl via the function
+ /// \c ObjCInterfaceDecl::setExternallyCompleted().
+ void CompleteType(ObjCInterfaceDecl *Class) override;
+
+ /// Loads comment ranges.
+ void ReadComments() override;
+
+ /// Notify ExternalASTSource that we started deserialization of
+ /// a decl or type so until FinishedDeserializing is called there may be
+ /// decls that are initializing. Must be paired with FinishedDeserializing.
+ void StartedDeserializing() override;
+
+ /// Notify ExternalASTSource that we finished the deserialization of
+ /// a decl or type. Must be paired with StartedDeserializing.
+ void FinishedDeserializing() override;
+
+ /// Function that will be invoked when we begin parsing a new
+ /// translation unit involving this external AST source.
+ void StartTranslationUnit(ASTConsumer *Consumer) override;
+
+ /// Print any statistics that have been gathered regarding
+ /// the external AST source.
+ void PrintStats() override;
+
+ /// Retrieve the module that corresponds to the given module ID.
+ Module *getModule(unsigned ID) override;
+
+ /// Perform layout on the given record.
+ ///
+ /// This routine allows the external AST source to provide an specific
+ /// layout for a record, overriding the layout that would normally be
+ /// constructed. It is intended for clients who receive specific layout
+ /// details rather than source code (such as LLDB). The client is expected
+ /// to fill in the field offsets, base offsets, virtual base offsets, and
+ /// complete object size.
+ ///
+ /// \param Record The record whose layout is being requested.
+ ///
+ /// \param Size The final size of the record, in bits.
+ ///
+ /// \param Alignment The final alignment of the record, in bits.
+ ///
+ /// \param FieldOffsets The offset of each of the fields within the record,
+ /// expressed in bits. All of the fields must be provided with offsets.
+ ///
+ /// \param BaseOffsets The offset of each of the direct, non-virtual base
+ /// classes. If any bases are not given offsets, the bases will be laid
+ /// out according to the ABI.
+ ///
+ /// \param VirtualBaseOffsets The offset of each of the virtual base classes
+ /// (either direct or not). If any bases are not given offsets, the bases will
+ /// be laid out according to the ABI.
+ ///
+ /// \returns true if the record layout was provided, false otherwise.
+ bool
+ layoutRecordType(const RecordDecl *Record,
+ uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
+ llvm::DenseMap<const CXXRecordDecl *,
+ CharUnits> &VirtualBaseOffsets) override;
+
+ /// Return the amount of memory used by memory buffers, breaking down
+ /// by heap-backed versus mmap'ed memory.
+ void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override;
+
+ //===--------------------------------------------------------------------===//
+ // ExternalSemaSource.
+ //===--------------------------------------------------------------------===//
+
+ /// Initialize the semantic source with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ void InitializeSema(Sema &S) override;
+
+ /// Inform the semantic consumer that Sema is no longer available.
+ void ForgetSema() override;
+
+ /// Load the contents of the global method pool for a given
+ /// selector.
+ void ReadMethodPool(Selector Sel) override;
+
+ /// Load the contents of the global method pool for a given
+ /// selector if necessary.
+ void updateOutOfDateSelector(Selector Sel) override;
+
+ /// Load the set of namespaces that are known to the external source,
+ /// which will be used during typo correction.
+ void
+ ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces) override;
+
+ /// Load the set of used but not defined functions or variables with
+ /// internal linkage, or used but not defined inline functions.
+ void ReadUndefinedButUsed(
+ llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) override;
+
+ void ReadMismatchingDeleteExpressions(llvm::MapVector<
+ FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &
+ Exprs) override;
+
+ /// Do last resort, unqualified lookup on a LookupResult that
+ /// Sema cannot find.
+ ///
+ /// \param R a LookupResult that is being recovered.
+ ///
+ /// \param S the Scope of the identifier occurrence.
+ ///
+ /// \return true to tell Sema to recover using the LookupResult.
+ bool LookupUnqualified(LookupResult &R, Scope *S) override;
+
+ /// Read the set of tentative definitions known to the external Sema
+ /// source.
+ ///
+ /// The external source should append its own tentative definitions to the
+ /// given vector of tentative definitions. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs) override;
+
+ /// Read the set of unused file-scope declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own unused, filed-scope to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadUnusedFileScopedDecls(
+ SmallVectorImpl<const DeclaratorDecl*> &Decls) override;
+
+ /// Read the set of delegating constructors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own delegating constructors to the
+ /// given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadDelegatingConstructors(
+ SmallVectorImpl<CXXConstructorDecl*> &Decls) override;
+
+ /// Read the set of ext_vector type declarations known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own ext_vector type declarations to
+ /// the given vector of declarations. Note that this routine may be
+ /// invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override;
+
+ /// Read the set of potentially unused typedefs known to the source.
+ ///
+ /// The external source should append its own potentially unused local
+ /// typedefs to the given vector of declarations. Note that this routine may
+ /// be invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadUnusedLocalTypedefNameCandidates(
+ llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override;
+
+ /// Read the set of referenced selectors known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own referenced selectors to the
+ /// given vector of selectors. Note that this routine
+ /// may be invoked multiple times; the external source should take care not
+ /// to introduce the same selectors repeatedly.
+ void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector,
+ SourceLocation> > &Sels) override;
+
+ /// Read the set of weak, undeclared identifiers known to the
+ /// external Sema source.
+ ///
+ /// The external source should append its own weak, undeclared identifiers to
+ /// the given vector. Note that this routine may be invoked multiple times;
+ /// the external source should take care not to introduce the same identifiers
+ /// repeatedly.
+ void ReadWeakUndeclaredIdentifiers(
+ SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) override;
+
+ /// Read the set of used vtables known to the external Sema source.
+ ///
+ /// The external source should append its own used vtables to the given
+ /// vector. Note that this routine may be invoked multiple times; the external
+ /// source should take care not to introduce the same vtables repeatedly.
+ void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override;
+
+ /// Read the set of pending instantiations known to the external
+ /// Sema source.
+ ///
+ /// The external source should append its own pending instantiations to the
+ /// given vector. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same instantiations
+ /// repeatedly.
+ void ReadPendingInstantiations(
+ SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override;
+
+ /// Read the set of late parsed template functions for this source.
+ ///
+ /// The external source should insert its own late parsed template functions
+ /// into the map. Note that this routine may be invoked multiple times; the
+ /// external source should take care not to introduce the same map entries
+ /// repeatedly.
+ void ReadLateParsedTemplates(
+ llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
+ &LPTMap) override;
+
+ /// Read the set of decls to be checked for deferred diags.
+ ///
+ /// The external source should append its own potentially emitted function
+ /// and variable decls which may cause deferred diags. Note that this routine
+ /// may be invoked multiple times; the external source should take care not to
+ /// introduce the same declarations repeatedly.
+ void ReadDeclsToCheckForDeferredDiags(
+ llvm::SmallSetVector<Decl *, 4> &Decls) override;
+
+ /// \copydoc ExternalSemaSource::CorrectTypo
+ /// \note Returns the first nonempty correction.
+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ int LookupKind, Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext,
+ const ObjCObjectPointerType *OPT) override;
+
+ /// Produces a diagnostic note if one of the attached sources
+ /// contains a complete definition for \p T. Queries the sources in list
+ /// order until the first one claims that a diagnostic was produced.
+ ///
+ /// \param Loc the location at which a complete type was required but not
+ /// provided
+ ///
+ /// \param T the \c QualType that should have been complete at \p Loc
+ ///
+ /// \return true if a diagnostic was produced, false otherwise.
+ bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
+ QualType T) override;
+
+ /// LLVM-style RTTI.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || ExternalSemaSource::isA(ClassID);
+ }
+ static bool classof(const ExternalASTSource *S) { return S->isA(&ID); }
+ /// \}
+};
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/ObjCMethodList.h b/contrib/libs/clang16/include/clang/Sema/ObjCMethodList.h
new file mode 100644
index 0000000000..de81fae49a
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/ObjCMethodList.h
@@ -0,0 +1,78 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- ObjCMethodList.h - A singly linked list of methods -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ObjCMethodList, a singly-linked list of methods.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OBJCMETHODLIST_H
+#define LLVM_CLANG_SEMA_OBJCMETHODLIST_H
+
+#include "clang/AST/DeclObjC.h"
+#include "llvm/ADT/PointerIntPair.h"
+
+namespace clang {
+
+class ObjCMethodDecl;
+
+/// a linked list of methods with the same selector name but different
+/// signatures.
+struct ObjCMethodList {
+ // NOTE: If you add any members to this struct, make sure to serialize them.
+ /// If there is more than one decl with this signature.
+ llvm::PointerIntPair<ObjCMethodDecl *, 1> MethodAndHasMoreThanOneDecl;
+ /// The next list object and 2 bits for extra info.
+ llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits;
+
+ ObjCMethodList() { }
+ ObjCMethodList(ObjCMethodDecl *M)
+ : MethodAndHasMoreThanOneDecl(M, 0) {}
+ ObjCMethodList(const ObjCMethodList &L)
+ : MethodAndHasMoreThanOneDecl(L.MethodAndHasMoreThanOneDecl),
+ NextAndExtraBits(L.NextAndExtraBits) {}
+
+ ObjCMethodList &operator=(const ObjCMethodList &L) {
+ MethodAndHasMoreThanOneDecl = L.MethodAndHasMoreThanOneDecl;
+ NextAndExtraBits = L.NextAndExtraBits;
+ return *this;
+ }
+
+ ObjCMethodList *getNext() const { return NextAndExtraBits.getPointer(); }
+ unsigned getBits() const { return NextAndExtraBits.getInt(); }
+ void setNext(ObjCMethodList *L) { NextAndExtraBits.setPointer(L); }
+ void setBits(unsigned B) { NextAndExtraBits.setInt(B); }
+
+ ObjCMethodDecl *getMethod() const {
+ return MethodAndHasMoreThanOneDecl.getPointer();
+ }
+ void setMethod(ObjCMethodDecl *M) {
+ return MethodAndHasMoreThanOneDecl.setPointer(M);
+ }
+
+ bool hasMoreThanOneDecl() const {
+ return MethodAndHasMoreThanOneDecl.getInt();
+ }
+ void setHasMoreThanOneDecl(bool B) {
+ return MethodAndHasMoreThanOneDecl.setInt(B);
+ }
+};
+
+}
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Overload.h b/contrib/libs/clang16/include/clang/Sema/Overload.h
new file mode 100644
index 0000000000..b84f66e8c8
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Overload.h
@@ -0,0 +1,1255 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Overload.h - C++ Overloading -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the data structures and types used in C++
+// overload resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OVERLOAD_H
+#define LLVM_CLANG_SEMA_OVERLOAD_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/SemaFixItUtils.h"
+#include "clang/Sema/TemplateDeduction.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
+
+namespace clang {
+
+class APValue;
+class ASTContext;
+class Sema;
+
+ /// OverloadingResult - Capture the result of performing overload
+ /// resolution.
+ enum OverloadingResult {
+ /// Overload resolution succeeded.
+ OR_Success,
+
+ /// No viable function found.
+ OR_No_Viable_Function,
+
+ /// Ambiguous candidates found.
+ OR_Ambiguous,
+
+ /// Succeeded, but refers to a deleted function.
+ OR_Deleted
+ };
+
+ enum OverloadCandidateDisplayKind {
+ /// Requests that all candidates be shown. Viable candidates will
+ /// be printed first.
+ OCD_AllCandidates,
+
+ /// Requests that only viable candidates be shown.
+ OCD_ViableCandidates,
+
+ /// Requests that only tied-for-best candidates be shown.
+ OCD_AmbiguousCandidates
+ };
+
+ /// The parameter ordering that will be used for the candidate. This is
+ /// used to represent C++20 binary operator rewrites that reverse the order
+ /// of the arguments. If the parameter ordering is Reversed, the Args list is
+ /// reversed (but obviously the ParamDecls for the function are not).
+ ///
+ /// After forming an OverloadCandidate with reversed parameters, the list
+ /// of conversions will (as always) be indexed by argument, so will be
+ /// in reverse parameter order.
+ enum class OverloadCandidateParamOrder : char { Normal, Reversed };
+
+ /// The kinds of rewrite we perform on overload candidates. Note that the
+ /// values here are chosen to serve as both bitflags and as a rank (lower
+ /// values are preferred by overload resolution).
+ enum OverloadCandidateRewriteKind : unsigned {
+ /// Candidate is not a rewritten candidate.
+ CRK_None = 0x0,
+
+ /// Candidate is a rewritten candidate with a different operator name.
+ CRK_DifferentOperator = 0x1,
+
+ /// Candidate is a rewritten candidate with a reversed order of parameters.
+ CRK_Reversed = 0x2,
+ };
+
+ /// ImplicitConversionKind - The kind of implicit conversion used to
+ /// convert an argument to a parameter's type. The enumerator values
+ /// match with the table titled 'Conversions' in [over.ics.scs] and are listed
+ /// such that better conversion kinds have smaller values.
+ enum ImplicitConversionKind {
+ /// Identity conversion (no conversion)
+ ICK_Identity = 0,
+
+ /// Lvalue-to-rvalue conversion (C++ [conv.lval])
+ ICK_Lvalue_To_Rvalue,
+
+ /// Array-to-pointer conversion (C++ [conv.array])
+ ICK_Array_To_Pointer,
+
+ /// Function-to-pointer (C++ [conv.array])
+ ICK_Function_To_Pointer,
+
+ /// Function pointer conversion (C++17 [conv.fctptr])
+ ICK_Function_Conversion,
+
+ /// Qualification conversions (C++ [conv.qual])
+ ICK_Qualification,
+
+ /// Integral promotions (C++ [conv.prom])
+ ICK_Integral_Promotion,
+
+ /// Floating point promotions (C++ [conv.fpprom])
+ ICK_Floating_Promotion,
+
+ /// Complex promotions (Clang extension)
+ ICK_Complex_Promotion,
+
+ /// Integral conversions (C++ [conv.integral])
+ ICK_Integral_Conversion,
+
+ /// Floating point conversions (C++ [conv.double]
+ ICK_Floating_Conversion,
+
+ /// Complex conversions (C99 6.3.1.6)
+ ICK_Complex_Conversion,
+
+ /// Floating-integral conversions (C++ [conv.fpint])
+ ICK_Floating_Integral,
+
+ /// Pointer conversions (C++ [conv.ptr])
+ ICK_Pointer_Conversion,
+
+ /// Pointer-to-member conversions (C++ [conv.mem])
+ ICK_Pointer_Member,
+
+ /// Boolean conversions (C++ [conv.bool])
+ ICK_Boolean_Conversion,
+
+ /// Conversions between compatible types in C99
+ ICK_Compatible_Conversion,
+
+ /// Derived-to-base (C++ [over.best.ics])
+ ICK_Derived_To_Base,
+
+ /// Vector conversions
+ ICK_Vector_Conversion,
+
+ /// Arm SVE Vector conversions
+ ICK_SVE_Vector_Conversion,
+
+ /// A vector splat from an arithmetic type
+ ICK_Vector_Splat,
+
+ /// Complex-real conversions (C99 6.3.1.7)
+ ICK_Complex_Real,
+
+ /// Block Pointer conversions
+ ICK_Block_Pointer_Conversion,
+
+ /// Transparent Union Conversions
+ ICK_TransparentUnionConversion,
+
+ /// Objective-C ARC writeback conversion
+ ICK_Writeback_Conversion,
+
+ /// Zero constant to event (OpenCL1.2 6.12.10)
+ ICK_Zero_Event_Conversion,
+
+ /// Zero constant to queue
+ ICK_Zero_Queue_Conversion,
+
+ /// Conversions allowed in C, but not C++
+ ICK_C_Only_Conversion,
+
+ /// C-only conversion between pointers with incompatible types
+ ICK_Incompatible_Pointer_Conversion,
+
+ /// The number of conversion kinds
+ ICK_Num_Conversion_Kinds,
+ };
+
+ /// ImplicitConversionRank - The rank of an implicit conversion
+ /// kind. The enumerator values match with Table 9 of (C++
+ /// 13.3.3.1.1) and are listed such that better conversion ranks
+ /// have smaller values.
+ enum ImplicitConversionRank {
+ /// Exact Match
+ ICR_Exact_Match = 0,
+
+ /// Promotion
+ ICR_Promotion,
+
+ /// Conversion
+ ICR_Conversion,
+
+ /// OpenCL Scalar Widening
+ ICR_OCL_Scalar_Widening,
+
+ /// Complex <-> Real conversion
+ ICR_Complex_Real_Conversion,
+
+ /// ObjC ARC writeback conversion
+ ICR_Writeback_Conversion,
+
+ /// Conversion only allowed in the C standard (e.g. void* to char*).
+ ICR_C_Conversion,
+
+ /// Conversion not allowed by the C standard, but that we accept as an
+ /// extension anyway.
+ ICR_C_Conversion_Extension
+ };
+
+ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
+
+ /// NarrowingKind - The kind of narrowing conversion being performed by a
+ /// standard conversion sequence according to C++11 [dcl.init.list]p7.
+ enum NarrowingKind {
+ /// Not a narrowing conversion.
+ NK_Not_Narrowing,
+
+ /// A narrowing conversion by virtue of the source and destination types.
+ NK_Type_Narrowing,
+
+ /// A narrowing conversion, because a constant expression got narrowed.
+ NK_Constant_Narrowing,
+
+ /// A narrowing conversion, because a non-constant-expression variable might
+ /// have got narrowed.
+ NK_Variable_Narrowing,
+
+ /// Cannot tell whether this is a narrowing conversion because the
+ /// expression is value-dependent.
+ NK_Dependent_Narrowing,
+ };
+
+ /// StandardConversionSequence - represents a standard conversion
+ /// sequence (C++ 13.3.3.1.1). A standard conversion sequence
+ /// contains between zero and three conversions. If a particular
+ /// conversion is not needed, it will be set to the identity conversion
+ /// (ICK_Identity). Note that the three conversions are
+ /// specified as separate members (rather than in an array) so that
+ /// we can keep the size of a standard conversion sequence to a
+ /// single word.
+ class StandardConversionSequence {
+ public:
+ /// First -- The first conversion can be an lvalue-to-rvalue
+ /// conversion, array-to-pointer conversion, or
+ /// function-to-pointer conversion.
+ ImplicitConversionKind First : 8;
+
+ /// Second - The second conversion can be an integral promotion,
+ /// floating point promotion, integral conversion, floating point
+ /// conversion, floating-integral conversion, pointer conversion,
+ /// pointer-to-member conversion, or boolean conversion.
+ ImplicitConversionKind Second : 8;
+
+ /// Third - The third conversion can be a qualification conversion
+ /// or a function conversion.
+ ImplicitConversionKind Third : 8;
+
+ /// Whether this is the deprecated conversion of a
+ /// string literal to a pointer to non-const character data
+ /// (C++ 4.2p2).
+ unsigned DeprecatedStringLiteralToCharPtr : 1;
+
+ /// Whether the qualification conversion involves a change in the
+ /// Objective-C lifetime (for automatic reference counting).
+ unsigned QualificationIncludesObjCLifetime : 1;
+
+ /// IncompatibleObjC - Whether this is an Objective-C conversion
+ /// that we should warn about (if we actually use it).
+ unsigned IncompatibleObjC : 1;
+
+ /// ReferenceBinding - True when this is a reference binding
+ /// (C++ [over.ics.ref]).
+ unsigned ReferenceBinding : 1;
+
+ /// DirectBinding - True when this is a reference binding that is a
+ /// direct binding (C++ [dcl.init.ref]).
+ unsigned DirectBinding : 1;
+
+ /// Whether this is an lvalue reference binding (otherwise, it's
+ /// an rvalue reference binding).
+ unsigned IsLvalueReference : 1;
+
+ /// Whether we're binding to a function lvalue.
+ unsigned BindsToFunctionLvalue : 1;
+
+ /// Whether we're binding to an rvalue.
+ unsigned BindsToRvalue : 1;
+
+ /// Whether this binds an implicit object argument to a
+ /// non-static member function without a ref-qualifier.
+ unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1;
+
+ /// Whether this binds a reference to an object with a different
+ /// Objective-C lifetime qualifier.
+ unsigned ObjCLifetimeConversionBinding : 1;
+
+ /// FromType - The type that this conversion is converting
+ /// from. This is an opaque pointer that can be translated into a
+ /// QualType.
+ void *FromTypePtr;
+
+ /// ToType - The types that this conversion is converting to in
+ /// each step. This is an opaque pointer that can be translated
+ /// into a QualType.
+ void *ToTypePtrs[3];
+
+ /// CopyConstructor - The copy constructor that is used to perform
+ /// this conversion, when the conversion is actually just the
+ /// initialization of an object via copy constructor. Such
+ /// conversions are either identity conversions or derived-to-base
+ /// conversions.
+ CXXConstructorDecl *CopyConstructor;
+ DeclAccessPair FoundCopyConstructor;
+
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+
+ void setToType(unsigned Idx, QualType T) {
+ assert(Idx < 3 && "To type index is out of range");
+ ToTypePtrs[Idx] = T.getAsOpaquePtr();
+ }
+
+ void setAllToTypes(QualType T) {
+ ToTypePtrs[0] = T.getAsOpaquePtr();
+ ToTypePtrs[1] = ToTypePtrs[0];
+ ToTypePtrs[2] = ToTypePtrs[0];
+ }
+
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+
+ QualType getToType(unsigned Idx) const {
+ assert(Idx < 3 && "To type index is out of range");
+ return QualType::getFromOpaquePtr(ToTypePtrs[Idx]);
+ }
+
+ void setAsIdentityConversion();
+
+ bool isIdentityConversion() const {
+ return Second == ICK_Identity && Third == ICK_Identity;
+ }
+
+ ImplicitConversionRank getRank() const;
+ NarrowingKind
+ getNarrowingKind(ASTContext &Context, const Expr *Converted,
+ APValue &ConstantValue, QualType &ConstantType,
+ bool IgnoreFloatToIntegralConversion = false) const;
+ bool isPointerConversionToBool() const;
+ bool isPointerConversionToVoidPointer(ASTContext& Context) const;
+ void dump() const;
+ };
+
+ /// UserDefinedConversionSequence - Represents a user-defined
+ /// conversion sequence (C++ 13.3.3.1.2).
+ struct UserDefinedConversionSequence {
+ /// Represents the standard conversion that occurs before
+ /// the actual user-defined conversion.
+ ///
+ /// C++11 13.3.3.1.2p1:
+ /// If the user-defined conversion is specified by a constructor
+ /// (12.3.1), the initial standard conversion sequence converts
+ /// the source type to the type required by the argument of the
+ /// constructor. If the user-defined conversion is specified by
+ /// a conversion function (12.3.2), the initial standard
+ /// conversion sequence converts the source type to the implicit
+ /// object parameter of the conversion function.
+ StandardConversionSequence Before;
+
+ /// EllipsisConversion - When this is true, it means user-defined
+ /// conversion sequence starts with a ... (ellipsis) conversion, instead of
+ /// a standard conversion. In this case, 'Before' field must be ignored.
+ // FIXME. I much rather put this as the first field. But there seems to be
+ // a gcc code gen. bug which causes a crash in a test. Putting it here seems
+ // to work around the crash.
+ bool EllipsisConversion : 1;
+
+ /// HadMultipleCandidates - When this is true, it means that the
+ /// conversion function was resolved from an overloaded set having
+ /// size greater than 1.
+ bool HadMultipleCandidates : 1;
+
+ /// After - Represents the standard conversion that occurs after
+ /// the actual user-defined conversion.
+ StandardConversionSequence After;
+
+ /// ConversionFunction - The function that will perform the
+ /// user-defined conversion. Null if the conversion is an
+ /// aggregate initialization from an initializer list.
+ FunctionDecl* ConversionFunction;
+
+ /// The declaration that we found via name lookup, which might be
+ /// the same as \c ConversionFunction or it might be a using declaration
+ /// that refers to \c ConversionFunction.
+ DeclAccessPair FoundConversionFunction;
+
+ void dump() const;
+ };
+
+ /// Represents an ambiguous user-defined conversion sequence.
+ struct AmbiguousConversionSequence {
+ using ConversionSet =
+ SmallVector<std::pair<NamedDecl *, FunctionDecl *>, 4>;
+
+ void *FromTypePtr;
+ void *ToTypePtr;
+ char Buffer[sizeof(ConversionSet)];
+
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+
+ QualType getToType() const {
+ return QualType::getFromOpaquePtr(ToTypePtr);
+ }
+
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+
+ ConversionSet &conversions() {
+ return *reinterpret_cast<ConversionSet*>(Buffer);
+ }
+
+ const ConversionSet &conversions() const {
+ return *reinterpret_cast<const ConversionSet*>(Buffer);
+ }
+
+ void addConversion(NamedDecl *Found, FunctionDecl *D) {
+ conversions().push_back(std::make_pair(Found, D));
+ }
+
+ using iterator = ConversionSet::iterator;
+
+ iterator begin() { return conversions().begin(); }
+ iterator end() { return conversions().end(); }
+
+ using const_iterator = ConversionSet::const_iterator;
+
+ const_iterator begin() const { return conversions().begin(); }
+ const_iterator end() const { return conversions().end(); }
+
+ void construct();
+ void destruct();
+ void copyFrom(const AmbiguousConversionSequence &);
+ };
+
+ /// BadConversionSequence - Records information about an invalid
+ /// conversion sequence.
+ struct BadConversionSequence {
+ enum FailureKind {
+ no_conversion,
+ unrelated_class,
+ bad_qualifiers,
+ lvalue_ref_to_rvalue,
+ rvalue_ref_to_lvalue,
+ too_few_initializers,
+ too_many_initializers,
+ };
+
+ // This can be null, e.g. for implicit object arguments.
+ Expr *FromExpr;
+
+ FailureKind Kind;
+
+ private:
+ // The type we're converting from (an opaque QualType).
+ void *FromTy;
+
+ // The type we're converting to (an opaque QualType).
+ void *ToTy;
+
+ public:
+ void init(FailureKind K, Expr *From, QualType To) {
+ init(K, From->getType(), To);
+ FromExpr = From;
+ }
+
+ void init(FailureKind K, QualType From, QualType To) {
+ Kind = K;
+ FromExpr = nullptr;
+ setFromType(From);
+ setToType(To);
+ }
+
+ QualType getFromType() const { return QualType::getFromOpaquePtr(FromTy); }
+ QualType getToType() const { return QualType::getFromOpaquePtr(ToTy); }
+
+ void setFromExpr(Expr *E) {
+ FromExpr = E;
+ setFromType(E->getType());
+ }
+
+ void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); }
+ };
+
+ /// ImplicitConversionSequence - Represents an implicit conversion
+ /// sequence, which may be a standard conversion sequence
+ /// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2),
+ /// or an ellipsis conversion sequence (C++ 13.3.3.1.3).
+ class ImplicitConversionSequence {
+ public:
+ /// Kind - The kind of implicit conversion sequence. BadConversion
+ /// specifies that there is no conversion from the source type to
+ /// the target type. AmbiguousConversion represents the unique
+ /// ambiguous conversion (C++0x [over.best.ics]p10).
+ /// StaticObjectArgumentConversion represents the conversion rules for
+ /// the synthesized first argument of calls to static member functions
+ /// ([over.best.ics.general]p8).
+ enum Kind {
+ StandardConversion = 0,
+ StaticObjectArgumentConversion,
+ UserDefinedConversion,
+ AmbiguousConversion,
+ EllipsisConversion,
+ BadConversion
+ };
+
+ private:
+ enum {
+ Uninitialized = BadConversion + 1
+ };
+
+ /// ConversionKind - The kind of implicit conversion sequence.
+ unsigned ConversionKind : 31;
+
+ // Whether the initializer list was of an incomplete array.
+ unsigned InitializerListOfIncompleteArray : 1;
+
+ /// When initializing an array or std::initializer_list from an
+ /// initializer-list, this is the array or std::initializer_list type being
+ /// initialized. The remainder of the conversion sequence, including ToType,
+ /// describe the worst conversion of an initializer to an element of the
+ /// array or std::initializer_list. (Note, 'worst' is not well defined.)
+ QualType InitializerListContainerType;
+
+ void setKind(Kind K) {
+ destruct();
+ ConversionKind = K;
+ }
+
+ void destruct() {
+ if (ConversionKind == AmbiguousConversion) Ambiguous.destruct();
+ }
+
+ public:
+ union {
+ /// When ConversionKind == StandardConversion, provides the
+ /// details of the standard conversion sequence.
+ StandardConversionSequence Standard;
+
+ /// When ConversionKind == UserDefinedConversion, provides the
+ /// details of the user-defined conversion sequence.
+ UserDefinedConversionSequence UserDefined;
+
+ /// When ConversionKind == AmbiguousConversion, provides the
+ /// details of the ambiguous conversion.
+ AmbiguousConversionSequence Ambiguous;
+
+ /// When ConversionKind == BadConversion, provides the details
+ /// of the bad conversion.
+ BadConversionSequence Bad;
+ };
+
+ ImplicitConversionSequence()
+ : ConversionKind(Uninitialized),
+ InitializerListOfIncompleteArray(false) {
+ Standard.setAsIdentityConversion();
+ }
+
+ ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+ : ConversionKind(Other.ConversionKind),
+ InitializerListOfIncompleteArray(
+ Other.InitializerListOfIncompleteArray),
+ InitializerListContainerType(Other.InitializerListContainerType) {
+ switch (ConversionKind) {
+ case Uninitialized: break;
+ case StandardConversion: Standard = Other.Standard; break;
+ case StaticObjectArgumentConversion:
+ break;
+ case UserDefinedConversion: UserDefined = Other.UserDefined; break;
+ case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break;
+ case EllipsisConversion: break;
+ case BadConversion: Bad = Other.Bad; break;
+ }
+ }
+
+ ImplicitConversionSequence &
+ operator=(const ImplicitConversionSequence &Other) {
+ destruct();
+ new (this) ImplicitConversionSequence(Other);
+ return *this;
+ }
+
+ ~ImplicitConversionSequence() {
+ destruct();
+ }
+
+ Kind getKind() const {
+ assert(isInitialized() && "querying uninitialized conversion");
+ return Kind(ConversionKind);
+ }
+
+ /// Return a ranking of the implicit conversion sequence
+ /// kind, where smaller ranks represent better conversion
+ /// sequences.
+ ///
+ /// In particular, this routine gives user-defined conversion
+ /// sequences and ambiguous conversion sequences the same rank,
+ /// per C++ [over.best.ics]p10.
+ unsigned getKindRank() const {
+ switch (getKind()) {
+ case StandardConversion:
+ case StaticObjectArgumentConversion:
+ return 0;
+
+ case UserDefinedConversion:
+ case AmbiguousConversion:
+ return 1;
+
+ case EllipsisConversion:
+ return 2;
+
+ case BadConversion:
+ return 3;
+ }
+
+ llvm_unreachable("Invalid ImplicitConversionSequence::Kind!");
+ }
+
+ bool isBad() const { return getKind() == BadConversion; }
+ bool isStandard() const { return getKind() == StandardConversion; }
+ bool isStaticObjectArgument() const {
+ return getKind() == StaticObjectArgumentConversion;
+ }
+ bool isEllipsis() const { return getKind() == EllipsisConversion; }
+ bool isAmbiguous() const { return getKind() == AmbiguousConversion; }
+ bool isUserDefined() const { return getKind() == UserDefinedConversion; }
+ bool isFailure() const { return isBad() || isAmbiguous(); }
+
+ /// Determines whether this conversion sequence has been
+ /// initialized. Most operations should never need to query
+ /// uninitialized conversions and should assert as above.
+ bool isInitialized() const { return ConversionKind != Uninitialized; }
+
+ /// Sets this sequence as a bad conversion for an explicit argument.
+ void setBad(BadConversionSequence::FailureKind Failure,
+ Expr *FromExpr, QualType ToType) {
+ setKind(BadConversion);
+ Bad.init(Failure, FromExpr, ToType);
+ }
+
+ /// Sets this sequence as a bad conversion for an implicit argument.
+ void setBad(BadConversionSequence::FailureKind Failure,
+ QualType FromType, QualType ToType) {
+ setKind(BadConversion);
+ Bad.init(Failure, FromType, ToType);
+ }
+
+ void setStandard() { setKind(StandardConversion); }
+ void setStaticObjectArgument() { setKind(StaticObjectArgumentConversion); }
+ void setEllipsis() { setKind(EllipsisConversion); }
+ void setUserDefined() { setKind(UserDefinedConversion); }
+
+ void setAmbiguous() {
+ if (ConversionKind == AmbiguousConversion) return;
+ ConversionKind = AmbiguousConversion;
+ Ambiguous.construct();
+ }
+
+ void setAsIdentityConversion(QualType T) {
+ setStandard();
+ Standard.setAsIdentityConversion();
+ Standard.setFromType(T);
+ Standard.setAllToTypes(T);
+ }
+
+ // True iff this is a conversion sequence from an initializer list to an
+ // array or std::initializer.
+ bool hasInitializerListContainerType() const {
+ return !InitializerListContainerType.isNull();
+ }
+ void setInitializerListContainerType(QualType T, bool IA) {
+ InitializerListContainerType = T;
+ InitializerListOfIncompleteArray = IA;
+ }
+ bool isInitializerListOfIncompleteArray() const {
+ return InitializerListOfIncompleteArray;
+ }
+ QualType getInitializerListContainerType() const {
+ assert(hasInitializerListContainerType() &&
+ "not initializer list container");
+ return InitializerListContainerType;
+ }
+
+ /// Form an "implicit" conversion sequence from nullptr_t to bool, for a
+ /// direct-initialization of a bool object from nullptr_t.
+ static ImplicitConversionSequence getNullptrToBool(QualType SourceType,
+ QualType DestType,
+ bool NeedLValToRVal) {
+ ImplicitConversionSequence ICS;
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+ ICS.Standard.setFromType(SourceType);
+ if (NeedLValToRVal)
+ ICS.Standard.First = ICK_Lvalue_To_Rvalue;
+ ICS.Standard.setToType(0, SourceType);
+ ICS.Standard.Second = ICK_Boolean_Conversion;
+ ICS.Standard.setToType(1, DestType);
+ ICS.Standard.setToType(2, DestType);
+ return ICS;
+ }
+
+ // The result of a comparison between implicit conversion
+ // sequences. Use Sema::CompareImplicitConversionSequences to
+ // actually perform the comparison.
+ enum CompareKind {
+ Better = -1,
+ Indistinguishable = 0,
+ Worse = 1
+ };
+
+ void DiagnoseAmbiguousConversion(Sema &S,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag) const;
+
+ void dump() const;
+ };
+
+ enum OverloadFailureKind {
+ ovl_fail_too_many_arguments,
+ ovl_fail_too_few_arguments,
+ ovl_fail_bad_conversion,
+ ovl_fail_bad_deduction,
+
+ /// This conversion candidate was not considered because it
+ /// duplicates the work of a trivial or derived-to-base
+ /// conversion.
+ ovl_fail_trivial_conversion,
+
+ /// This conversion candidate was not considered because it is
+ /// an illegal instantiation of a constructor temploid: it is
+ /// callable with one argument, we only have one argument, and
+ /// its first parameter type is exactly the type of the class.
+ ///
+ /// Defining such a constructor directly is illegal, and
+ /// template-argument deduction is supposed to ignore such
+ /// instantiations, but we can still get one with the right
+ /// kind of implicit instantiation.
+ ovl_fail_illegal_constructor,
+
+ /// This conversion candidate is not viable because its result
+ /// type is not implicitly convertible to the desired type.
+ ovl_fail_bad_final_conversion,
+
+ /// This conversion function template specialization candidate is not
+ /// viable because the final conversion was not an exact match.
+ ovl_fail_final_conversion_not_exact,
+
+ /// (CUDA) This candidate was not viable because the callee
+ /// was not accessible from the caller's target (i.e. host->device,
+ /// global->host, device->host).
+ ovl_fail_bad_target,
+
+ /// This candidate function was not viable because an enable_if
+ /// attribute disabled it.
+ ovl_fail_enable_if,
+
+ /// This candidate constructor or conversion function is explicit but
+ /// the context doesn't permit explicit functions.
+ ovl_fail_explicit,
+
+ /// This candidate was not viable because its address could not be taken.
+ ovl_fail_addr_not_available,
+
+ /// This inherited constructor is not viable because it would slice the
+ /// argument.
+ ovl_fail_inhctor_slice,
+
+ /// This candidate was not viable because it is a non-default multiversioned
+ /// function.
+ ovl_non_default_multiversion_function,
+
+ /// This constructor/conversion candidate fail due to an address space
+ /// mismatch between the object being constructed and the overload
+ /// candidate.
+ ovl_fail_object_addrspace_mismatch,
+
+ /// This candidate was not viable because its associated constraints were
+ /// not satisfied.
+ ovl_fail_constraints_not_satisfied,
+
+ /// This candidate was not viable because it has internal linkage and is
+ /// from a different module unit than the use.
+ ovl_fail_module_mismatched,
+ };
+
+ /// A list of implicit conversion sequences for the arguments of an
+ /// OverloadCandidate.
+ using ConversionSequenceList =
+ llvm::MutableArrayRef<ImplicitConversionSequence>;
+
+ /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
+ struct OverloadCandidate {
+ /// Function - The actual function that this candidate
+ /// represents. When NULL, this is a built-in candidate
+ /// (C++ [over.oper]) or a surrogate for a conversion to a
+ /// function pointer or reference (C++ [over.call.object]).
+ FunctionDecl *Function;
+
+ /// FoundDecl - The original declaration that was looked up /
+ /// invented / otherwise found, together with its access.
+ /// Might be a UsingShadowDecl or a FunctionTemplateDecl.
+ DeclAccessPair FoundDecl;
+
+ /// BuiltinParamTypes - Provides the parameter types of a built-in overload
+ /// candidate. Only valid when Function is NULL.
+ QualType BuiltinParamTypes[3];
+
+ /// Surrogate - The conversion function for which this candidate
+ /// is a surrogate, but only if IsSurrogate is true.
+ CXXConversionDecl *Surrogate;
+
+ /// The conversion sequences used to convert the function arguments
+ /// to the function parameters. Note that these are indexed by argument,
+ /// so may not match the parameter order of Function.
+ ConversionSequenceList Conversions;
+
+ /// The FixIt hints which can be used to fix the Bad candidate.
+ ConversionFixItGenerator Fix;
+
+ /// Viable - True to indicate that this overload candidate is viable.
+ bool Viable : 1;
+
+ /// Whether this candidate is the best viable function, or tied for being
+ /// the best viable function.
+ ///
+ /// For an ambiguous overload resolution, indicates whether this candidate
+ /// was part of the ambiguity kernel: the minimal non-empty set of viable
+ /// candidates such that all elements of the ambiguity kernel are better
+ /// than all viable candidates not in the ambiguity kernel.
+ bool Best : 1;
+
+ /// IsSurrogate - True to indicate that this candidate is a
+ /// surrogate for a conversion to a function pointer or reference
+ /// (C++ [over.call.object]).
+ bool IsSurrogate : 1;
+
+ /// IgnoreObjectArgument - True to indicate that the first
+ /// argument's conversion, which for this function represents the
+ /// implicit object argument, should be ignored. This will be true
+ /// when the candidate is a static member function (where the
+ /// implicit object argument is just a placeholder) or a
+ /// non-static member function when the call doesn't have an
+ /// object argument.
+ bool IgnoreObjectArgument : 1;
+
+ /// True if the candidate was found using ADL.
+ CallExpr::ADLCallKind IsADLCandidate : 1;
+
+ /// Whether this is a rewritten candidate, and if so, of what kind?
+ unsigned RewriteKind : 2;
+
+ /// FailureKind - The reason why this candidate is not viable.
+ /// Actually an OverloadFailureKind.
+ unsigned char FailureKind;
+
+ /// The number of call arguments that were explicitly provided,
+ /// to be used while performing partial ordering of function templates.
+ unsigned ExplicitCallArguments;
+
+ union {
+ DeductionFailureInfo DeductionFailure;
+
+ /// FinalConversion - For a conversion function (where Function is
+ /// a CXXConversionDecl), the standard conversion that occurs
+ /// after the call to the overload candidate to convert the result
+ /// of calling the conversion function to the required type.
+ StandardConversionSequence FinalConversion;
+ };
+
+ /// Get RewriteKind value in OverloadCandidateRewriteKind type (This
+ /// function is to workaround the spurious GCC bitfield enum warning)
+ OverloadCandidateRewriteKind getRewriteKind() const {
+ return static_cast<OverloadCandidateRewriteKind>(RewriteKind);
+ }
+
+ bool isReversed() const { return getRewriteKind() & CRK_Reversed; }
+
+ /// hasAmbiguousConversion - Returns whether this overload
+ /// candidate requires an ambiguous conversion or not.
+ bool hasAmbiguousConversion() const {
+ for (auto &C : Conversions) {
+ if (!C.isInitialized()) return false;
+ if (C.isAmbiguous()) return true;
+ }
+ return false;
+ }
+
+ bool TryToFixBadConversion(unsigned Idx, Sema &S) {
+ bool CanFix = Fix.tryToFixConversion(
+ Conversions[Idx].Bad.FromExpr,
+ Conversions[Idx].Bad.getFromType(),
+ Conversions[Idx].Bad.getToType(), S);
+
+ // If at least one conversion fails, the candidate cannot be fixed.
+ if (!CanFix)
+ Fix.clear();
+
+ return CanFix;
+ }
+
+ unsigned getNumParams() const {
+ if (IsSurrogate) {
+ QualType STy = Surrogate->getConversionType();
+ while (STy->isPointerType() || STy->isReferenceType())
+ STy = STy->getPointeeType();
+ return STy->castAs<FunctionProtoType>()->getNumParams();
+ }
+ if (Function)
+ return Function->getNumParams();
+ return ExplicitCallArguments;
+ }
+
+ bool NotValidBecauseConstraintExprHasError() const;
+
+ private:
+ friend class OverloadCandidateSet;
+ OverloadCandidate()
+ : IsSurrogate(false), IsADLCandidate(CallExpr::NotADL), RewriteKind(CRK_None) {}
+ };
+
+ /// OverloadCandidateSet - A set of overload candidates, used in C++
+ /// overload resolution (C++ 13.3).
+ class OverloadCandidateSet {
+ public:
+ enum CandidateSetKind {
+ /// Normal lookup.
+ CSK_Normal,
+
+ /// C++ [over.match.oper]:
+ /// Lookup of operator function candidates in a call using operator
+ /// syntax. Candidates that have no parameters of class type will be
+ /// skipped unless there is a parameter of (reference to) enum type and
+ /// the corresponding argument is of the same enum type.
+ CSK_Operator,
+
+ /// C++ [over.match.copy]:
+ /// Copy-initialization of an object of class type by user-defined
+ /// conversion.
+ CSK_InitByUserDefinedConversion,
+
+ /// C++ [over.match.ctor], [over.match.list]
+ /// Initialization of an object of class type by constructor,
+ /// using either a parenthesized or braced list of arguments.
+ CSK_InitByConstructor,
+ };
+
+ /// Information about operator rewrites to consider when adding operator
+ /// functions to a candidate set.
+ struct OperatorRewriteInfo {
+ OperatorRewriteInfo()
+ : OriginalOperator(OO_None), OpLoc(), AllowRewrittenCandidates(false) {}
+ OperatorRewriteInfo(OverloadedOperatorKind Op, SourceLocation OpLoc,
+ bool AllowRewritten)
+ : OriginalOperator(Op), OpLoc(OpLoc),
+ AllowRewrittenCandidates(AllowRewritten) {}
+
+ /// The original operator as written in the source.
+ OverloadedOperatorKind OriginalOperator;
+ /// The source location of the operator.
+ SourceLocation OpLoc;
+ /// Whether we should include rewritten candidates in the overload set.
+ bool AllowRewrittenCandidates;
+
+ /// Would use of this function result in a rewrite using a different
+ /// operator?
+ bool isRewrittenOperator(const FunctionDecl *FD) {
+ return OriginalOperator &&
+ FD->getDeclName().getCXXOverloadedOperator() != OriginalOperator;
+ }
+
+ bool isAcceptableCandidate(const FunctionDecl *FD) {
+ if (!OriginalOperator)
+ return true;
+
+ // For an overloaded operator, we can have candidates with a different
+ // name in our unqualified lookup set. Make sure we only consider the
+ // ones we're supposed to.
+ OverloadedOperatorKind OO =
+ FD->getDeclName().getCXXOverloadedOperator();
+ return OO && (OO == OriginalOperator ||
+ (AllowRewrittenCandidates &&
+ OO == getRewrittenOverloadedOperator(OriginalOperator)));
+ }
+
+ /// Determine the kind of rewrite that should be performed for this
+ /// candidate.
+ OverloadCandidateRewriteKind
+ getRewriteKind(const FunctionDecl *FD, OverloadCandidateParamOrder PO) {
+ OverloadCandidateRewriteKind CRK = CRK_None;
+ if (isRewrittenOperator(FD))
+ CRK = OverloadCandidateRewriteKind(CRK | CRK_DifferentOperator);
+ if (PO == OverloadCandidateParamOrder::Reversed)
+ CRK = OverloadCandidateRewriteKind(CRK | CRK_Reversed);
+ return CRK;
+ }
+ /// Determines whether this operator could be implemented by a function
+ /// with reversed parameter order.
+ bool isReversible() {
+ return AllowRewrittenCandidates && OriginalOperator &&
+ (getRewrittenOverloadedOperator(OriginalOperator) != OO_None ||
+ allowsReversed(OriginalOperator));
+ }
+
+ /// Determine whether reversing parameter order is allowed for operator
+ /// Op.
+ bool allowsReversed(OverloadedOperatorKind Op);
+
+ /// Determine whether we should add a rewritten candidate for \p FD with
+ /// reversed parameter order.
+ /// \param OriginalArgs are the original non reversed arguments.
+ bool shouldAddReversed(Sema &S, ArrayRef<Expr *> OriginalArgs,
+ FunctionDecl *FD);
+ };
+
+ private:
+ SmallVector<OverloadCandidate, 16> Candidates;
+ llvm::SmallPtrSet<uintptr_t, 16> Functions;
+
+ // Allocator for ConversionSequenceLists. We store the first few of these
+ // inline to avoid allocation for small sets.
+ llvm::BumpPtrAllocator SlabAllocator;
+
+ SourceLocation Loc;
+ CandidateSetKind Kind;
+ OperatorRewriteInfo RewriteInfo;
+
+ constexpr static unsigned NumInlineBytes =
+ 24 * sizeof(ImplicitConversionSequence);
+ unsigned NumInlineBytesUsed = 0;
+ alignas(void *) char InlineSpace[NumInlineBytes];
+
+ // Address space of the object being constructed.
+ LangAS DestAS = LangAS::Default;
+
+ /// If we have space, allocates from inline storage. Otherwise, allocates
+ /// from the slab allocator.
+ /// FIXME: It would probably be nice to have a SmallBumpPtrAllocator
+ /// instead.
+ /// FIXME: Now that this only allocates ImplicitConversionSequences, do we
+ /// want to un-generalize this?
+ template <typename T>
+ T *slabAllocate(unsigned N) {
+ // It's simpler if this doesn't need to consider alignment.
+ static_assert(alignof(T) == alignof(void *),
+ "Only works for pointer-aligned types.");
+ static_assert(std::is_trivial<T>::value ||
+ std::is_same<ImplicitConversionSequence, T>::value,
+ "Add destruction logic to OverloadCandidateSet::clear().");
+
+ unsigned NBytes = sizeof(T) * N;
+ if (NBytes > NumInlineBytes - NumInlineBytesUsed)
+ return SlabAllocator.Allocate<T>(N);
+ char *FreeSpaceStart = InlineSpace + NumInlineBytesUsed;
+ assert(uintptr_t(FreeSpaceStart) % alignof(void *) == 0 &&
+ "Misaligned storage!");
+
+ NumInlineBytesUsed += NBytes;
+ return reinterpret_cast<T *>(FreeSpaceStart);
+ }
+
+ void destroyCandidates();
+
+ public:
+ OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK,
+ OperatorRewriteInfo RewriteInfo = {})
+ : Loc(Loc), Kind(CSK), RewriteInfo(RewriteInfo) {}
+ OverloadCandidateSet(const OverloadCandidateSet &) = delete;
+ OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
+ ~OverloadCandidateSet() { destroyCandidates(); }
+
+ SourceLocation getLocation() const { return Loc; }
+ CandidateSetKind getKind() const { return Kind; }
+ OperatorRewriteInfo getRewriteInfo() const { return RewriteInfo; }
+
+ /// Whether diagnostics should be deferred.
+ bool shouldDeferDiags(Sema &S, ArrayRef<Expr *> Args, SourceLocation OpLoc);
+
+ /// Determine when this overload candidate will be new to the
+ /// overload set.
+ bool isNewCandidate(Decl *F, OverloadCandidateParamOrder PO =
+ OverloadCandidateParamOrder::Normal) {
+ uintptr_t Key = reinterpret_cast<uintptr_t>(F->getCanonicalDecl());
+ Key |= static_cast<uintptr_t>(PO);
+ return Functions.insert(Key).second;
+ }
+
+ /// Exclude a function from being considered by overload resolution.
+ void exclude(Decl *F) {
+ isNewCandidate(F, OverloadCandidateParamOrder::Normal);
+ isNewCandidate(F, OverloadCandidateParamOrder::Reversed);
+ }
+
+ /// Clear out all of the candidates.
+ void clear(CandidateSetKind CSK);
+
+ using iterator = SmallVectorImpl<OverloadCandidate>::iterator;
+
+ iterator begin() { return Candidates.begin(); }
+ iterator end() { return Candidates.end(); }
+
+ size_t size() const { return Candidates.size(); }
+ bool empty() const { return Candidates.empty(); }
+
+ /// Allocate storage for conversion sequences for NumConversions
+ /// conversions.
+ ConversionSequenceList
+ allocateConversionSequences(unsigned NumConversions) {
+ ImplicitConversionSequence *Conversions =
+ slabAllocate<ImplicitConversionSequence>(NumConversions);
+
+ // Construct the new objects.
+ for (unsigned I = 0; I != NumConversions; ++I)
+ new (&Conversions[I]) ImplicitConversionSequence();
+
+ return ConversionSequenceList(Conversions, NumConversions);
+ }
+
+ /// Add a new candidate with NumConversions conversion sequence slots
+ /// to the overload set.
+ OverloadCandidate &
+ addCandidate(unsigned NumConversions = 0,
+ ConversionSequenceList Conversions = std::nullopt) {
+ assert((Conversions.empty() || Conversions.size() == NumConversions) &&
+ "preallocated conversion sequence has wrong length");
+
+ Candidates.push_back(OverloadCandidate());
+ OverloadCandidate &C = Candidates.back();
+ C.Conversions = Conversions.empty()
+ ? allocateConversionSequences(NumConversions)
+ : Conversions;
+ return C;
+ }
+
+ /// Find the best viable function on this overload set, if it exists.
+ OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc,
+ OverloadCandidateSet::iterator& Best);
+
+ SmallVector<OverloadCandidate *, 32> CompleteCandidates(
+ Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,
+ SourceLocation OpLoc = SourceLocation(),
+ llvm::function_ref<bool(OverloadCandidate &)> Filter =
+ [](OverloadCandidate &) { return true; });
+
+ void NoteCandidates(
+ PartialDiagnosticAt PA, Sema &S, OverloadCandidateDisplayKind OCD,
+ ArrayRef<Expr *> Args, StringRef Opc = "",
+ SourceLocation Loc = SourceLocation(),
+ llvm::function_ref<bool(OverloadCandidate &)> Filter =
+ [](OverloadCandidate &) { return true; });
+
+ void NoteCandidates(Sema &S, ArrayRef<Expr *> Args,
+ ArrayRef<OverloadCandidate *> Cands,
+ StringRef Opc = "",
+ SourceLocation OpLoc = SourceLocation());
+
+ LangAS getDestAS() { return DestAS; }
+
+ void setDestAS(LangAS AS) {
+ assert((Kind == CSK_InitByConstructor ||
+ Kind == CSK_InitByUserDefinedConversion) &&
+ "can't set the destination address space when not constructing an "
+ "object");
+ DestAS = AS;
+ }
+
+ };
+
+ bool isBetterOverloadCandidate(Sema &S,
+ const OverloadCandidate &Cand1,
+ const OverloadCandidate &Cand2,
+ SourceLocation Loc,
+ OverloadCandidateSet::CandidateSetKind Kind);
+
+ struct ConstructorInfo {
+ DeclAccessPair FoundDecl;
+ CXXConstructorDecl *Constructor;
+ FunctionTemplateDecl *ConstructorTmpl;
+
+ explicit operator bool() const { return Constructor; }
+ };
+
+ // FIXME: Add an AddOverloadCandidate / AddTemplateOverloadCandidate overload
+ // that takes one of these.
+ inline ConstructorInfo getConstructorInfo(NamedDecl *ND) {
+ if (isa<UsingDecl>(ND))
+ return ConstructorInfo{};
+
+ // For constructors, the access check is performed against the underlying
+ // declaration, not the found declaration.
+ auto *D = ND->getUnderlyingDecl();
+ ConstructorInfo Info = {DeclAccessPair::make(ND, D->getAccess()), nullptr,
+ nullptr};
+ Info.ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ if (Info.ConstructorTmpl)
+ D = Info.ConstructorTmpl->getTemplatedDecl();
+ Info.Constructor = dyn_cast<CXXConstructorDecl>(D);
+ return Info;
+ }
+
+ // Returns false if signature help is relevant despite number of arguments
+ // exceeding parameters. Specifically, it returns false when
+ // PartialOverloading is true and one of the following:
+ // * Function is variadic
+ // * Function is template variadic
+ // * Function is an instantiation of template variadic function
+ // The last case may seem strange. The idea is that if we added one more
+ // argument, we'd end up with a function similar to Function. Since, in the
+ // context of signature help and/or code completion, we do not know what the
+ // type of the next argument (that the user is typing) will be, this is as
+ // good candidate as we can get, despite the fact that it takes one less
+ // parameter.
+ bool shouldEnforceArgLimit(bool PartialOverloading, FunctionDecl *Function);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_OVERLOAD_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Ownership.h b/contrib/libs/clang16/include/clang/Sema/Ownership.h
new file mode 100644
index 0000000000..3c965bf853
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Ownership.h
@@ -0,0 +1,315 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Ownership.h - Parser ownership helpers -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains classes for managing ownership of Stmt and Expr nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H
+#define LLVM_CLANG_SEMA_OWNERSHIP_H
+
+#include "clang/AST/Expr.h"
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+//===----------------------------------------------------------------------===//
+// OpaquePtr
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+
+class CXXBaseSpecifier;
+class CXXCtorInitializer;
+class Decl;
+class Expr;
+class ParsedTemplateArgument;
+class QualType;
+class Stmt;
+class TemplateName;
+class TemplateParameterList;
+
+ /// Wrapper for void* pointer.
+ /// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like
+ /// a pointer.
+ ///
+ /// This is a very simple POD type that wraps a pointer that the Parser
+ /// doesn't know about but that Sema or another client does. The PtrTy
+ /// template argument is used to make sure that "Decl" pointers are not
+ /// compatible with "Type" pointers for example.
+ template <class PtrTy>
+ class OpaquePtr {
+ void *Ptr = nullptr;
+
+ explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {}
+
+ using Traits = llvm::PointerLikeTypeTraits<PtrTy>;
+
+ public:
+ OpaquePtr(std::nullptr_t = nullptr) {}
+
+ static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; }
+
+ /// Returns plain pointer to the entity pointed by this wrapper.
+ /// \tparam PointeeT Type of pointed entity.
+ ///
+ /// It is identical to getPtrAs<PointeeT*>.
+ template <typename PointeeT> PointeeT* getPtrTo() const {
+ return get();
+ }
+
+ /// Returns pointer converted to the specified type.
+ /// \tparam PtrT Result pointer type. There must be implicit conversion
+ /// from PtrTy to PtrT.
+ ///
+ /// In contrast to getPtrTo, this method allows the return type to be
+ /// a smart pointer.
+ template <typename PtrT> PtrT getPtrAs() const {
+ return get();
+ }
+
+ PtrTy get() const {
+ return Traits::getFromVoidPointer(Ptr);
+ }
+
+ void set(PtrTy P) {
+ Ptr = Traits::getAsVoidPointer(P);
+ }
+
+ explicit operator bool() const { return Ptr != nullptr; }
+
+ void *getAsOpaquePtr() const { return Ptr; }
+ static OpaquePtr getFromOpaquePtr(void *P) { return OpaquePtr(P); }
+ };
+
+ /// UnionOpaquePtr - A version of OpaquePtr suitable for membership
+ /// in a union.
+ template <class T> struct UnionOpaquePtr {
+ void *Ptr;
+
+ static UnionOpaquePtr make(OpaquePtr<T> P) {
+ UnionOpaquePtr OP = { P.getAsOpaquePtr() };
+ return OP;
+ }
+
+ OpaquePtr<T> get() const { return OpaquePtr<T>::getFromOpaquePtr(Ptr); }
+ operator OpaquePtr<T>() const { return get(); }
+
+ UnionOpaquePtr &operator=(OpaquePtr<T> P) {
+ Ptr = P.getAsOpaquePtr();
+ return *this;
+ }
+ };
+
+} // namespace clang
+
+namespace llvm {
+
+ template <class T>
+ struct PointerLikeTypeTraits<clang::OpaquePtr<T>> {
+ static constexpr int NumLowBitsAvailable = 0;
+
+ static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) {
+ // FIXME: Doesn't work? return P.getAs< void >();
+ return P.getAsOpaquePtr();
+ }
+
+ static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) {
+ return clang::OpaquePtr<T>::getFromOpaquePtr(P);
+ }
+ };
+
+} // namespace llvm
+
+namespace clang {
+
+ // Basic
+class StreamingDiagnostic;
+
+// Determines whether the low bit of the result pointer for the
+// given UID is always zero. If so, ActionResult will use that bit
+// for it's "invalid" flag.
+template <class Ptr> struct IsResultPtrLowBitFree {
+ static const bool value = false;
+ };
+
+ /// ActionResult - This structure is used while parsing/acting on
+ /// expressions, stmts, etc. It encapsulates both the object returned by
+ /// the action, plus a sense of whether or not it is valid.
+ /// When CompressInvalid is true, the "invalid" flag will be
+ /// stored in the low bit of the Val pointer.
+ template<class PtrTy,
+ bool CompressInvalid = IsResultPtrLowBitFree<PtrTy>::value>
+ class ActionResult {
+ PtrTy Val;
+ bool Invalid;
+
+ public:
+ ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {}
+ ActionResult(PtrTy val) : Val(val), Invalid(false) {}
+ ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {}
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *) = delete;
+ ActionResult(volatile void *) = delete;
+
+ bool isInvalid() const { return Invalid; }
+ bool isUsable() const { return !Invalid && Val; }
+ bool isUnset() const { return !Invalid && !Val; }
+
+ PtrTy get() const { return Val; }
+ template <typename T> T *getAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) { Val = V; }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ Val = RHS;
+ Invalid = false;
+ return *this;
+ }
+ };
+
+ // This ActionResult partial specialization places the "invalid"
+ // flag into the low bit of the pointer.
+ template<typename PtrTy>
+ class ActionResult<PtrTy, true> {
+ // A pointer whose low bit is 1 if this result is invalid, 0
+ // otherwise.
+ uintptr_t PtrWithInvalid;
+
+ using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>;
+
+ public:
+ ActionResult(bool Invalid = false)
+ : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) {}
+
+ ActionResult(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) {}
+
+ // These two overloads prevent void* -> bool conversions.
+ ActionResult(const void *) = delete;
+ ActionResult(volatile void *) = delete;
+
+ bool isInvalid() const { return PtrWithInvalid & 0x01; }
+ bool isUsable() const { return PtrWithInvalid > 0x01; }
+ bool isUnset() const { return PtrWithInvalid == 0; }
+
+ PtrTy get() const {
+ void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01);
+ return PtrTraits::getFromVoidPointer(VP);
+ }
+
+ template <typename T> T *getAs() { return static_cast<T*>(get()); }
+
+ void set(PtrTy V) {
+ void *VP = PtrTraits::getAsVoidPointer(V);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ }
+
+ const ActionResult &operator=(PtrTy RHS) {
+ void *VP = PtrTraits::getAsVoidPointer(RHS);
+ PtrWithInvalid = reinterpret_cast<uintptr_t>(VP);
+ assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer");
+ return *this;
+ }
+
+ // For types where we can fit a flag in with the pointer, provide
+ // conversions to/from pointer type.
+ static ActionResult getFromOpaquePointer(void *P) {
+ ActionResult Result;
+ Result.PtrWithInvalid = (uintptr_t)P;
+ return Result;
+ }
+ void *getAsOpaquePointer() const { return (void*)PtrWithInvalid; }
+ };
+
+ /// An opaque type for threading parsed type information through the
+ /// parser.
+ using ParsedType = OpaquePtr<QualType>;
+ using UnionParsedType = UnionOpaquePtr<QualType>;
+
+ // We can re-use the low bit of expression, statement, base, and
+ // member-initializer pointers for the "invalid" flag of
+ // ActionResult.
+ template<> struct IsResultPtrLowBitFree<Expr*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<Stmt*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXBaseSpecifier*> {
+ static const bool value = true;
+ };
+ template<> struct IsResultPtrLowBitFree<CXXCtorInitializer*> {
+ static const bool value = true;
+ };
+
+ using ExprResult = ActionResult<Expr *>;
+ using StmtResult = ActionResult<Stmt *>;
+ using TypeResult = ActionResult<ParsedType>;
+ using BaseResult = ActionResult<CXXBaseSpecifier *>;
+ using MemInitResult = ActionResult<CXXCtorInitializer *>;
+
+ using DeclResult = ActionResult<Decl *>;
+ using ParsedTemplateTy = OpaquePtr<TemplateName>;
+ using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>;
+
+ using MultiExprArg = MutableArrayRef<Expr *>;
+ using MultiStmtArg = MutableArrayRef<Stmt *>;
+ using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>;
+ using MultiTypeArg = MutableArrayRef<ParsedType>;
+ using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>;
+
+ inline ExprResult ExprError() { return ExprResult(true); }
+ inline StmtResult StmtError() { return StmtResult(true); }
+ inline TypeResult TypeError() { return TypeResult(true); }
+
+ inline ExprResult ExprError(const StreamingDiagnostic &) {
+ return ExprError();
+ }
+ inline StmtResult StmtError(const StreamingDiagnostic &) {
+ return StmtError();
+ }
+
+ inline ExprResult ExprEmpty() { return ExprResult(false); }
+ inline StmtResult StmtEmpty() { return StmtResult(false); }
+
+ inline Expr *AssertSuccess(ExprResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+
+ inline Stmt *AssertSuccess(StmtResult R) {
+ assert(!R.isInvalid() && "operation was asserted to never fail!");
+ return R.get();
+ }
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_OWNERSHIP_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/ParsedAttr.h b/contrib/libs/clang16/include/clang/Sema/ParsedAttr.h
new file mode 100644
index 0000000000..18392aee49
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/ParsedAttr.h
@@ -0,0 +1,1220 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//======- ParsedAttr.h - Parsed attribute sets ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ParsedAttr class, which is used to collect
+// parsed attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_PARSEDATTR_H
+#define LLVM_CLANG_SEMA_PARSEDATTR_H
+
+#include "clang/Basic/AttrSubjectMatchRules.h"
+#include "clang/Basic/AttributeCommonInfo.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Registry.h"
+#include "llvm/Support/VersionTuple.h"
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <utility>
+
+namespace clang {
+
+class ASTContext;
+class Decl;
+class Expr;
+class IdentifierInfo;
+class LangOptions;
+class ParsedAttr;
+class Sema;
+class Stmt;
+class TargetInfo;
+
+struct ParsedAttrInfo {
+ /// Corresponds to the Kind enum.
+ unsigned AttrKind : 16;
+ /// The number of required arguments of this attribute.
+ unsigned NumArgs : 4;
+ /// The number of optional arguments of this attributes.
+ unsigned OptArgs : 4;
+ /// The number of non-fake arguments specified in the attribute definition.
+ unsigned NumArgMembers : 4;
+ /// True if the parsing does not match the semantic content.
+ unsigned HasCustomParsing : 1;
+ // True if this attribute accepts expression parameter pack expansions.
+ unsigned AcceptsExprPack : 1;
+ /// True if this attribute is only available for certain targets.
+ unsigned IsTargetSpecific : 1;
+ /// True if this attribute applies to types.
+ unsigned IsType : 1;
+ /// True if this attribute applies to statements.
+ unsigned IsStmt : 1;
+ /// True if this attribute has any spellings that are known to gcc.
+ unsigned IsKnownToGCC : 1;
+ /// True if this attribute is supported by #pragma clang attribute.
+ unsigned IsSupportedByPragmaAttribute : 1;
+ /// The syntaxes supported by this attribute and how they're spelled.
+ struct Spelling {
+ AttributeCommonInfo::Syntax Syntax;
+ const char *NormalizedFullName;
+ };
+ ArrayRef<Spelling> Spellings;
+ // The names of the known arguments of this attribute.
+ ArrayRef<const char *> ArgNames;
+
+protected:
+ constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind =
+ AttributeCommonInfo::NoSemaHandlerAttribute)
+ : AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0),
+ HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0),
+ IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {}
+
+ constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs,
+ unsigned OptArgs, unsigned NumArgMembers,
+ unsigned HasCustomParsing, unsigned AcceptsExprPack,
+ unsigned IsTargetSpecific, unsigned IsType,
+ unsigned IsStmt, unsigned IsKnownToGCC,
+ unsigned IsSupportedByPragmaAttribute,
+ ArrayRef<Spelling> Spellings,
+ ArrayRef<const char *> ArgNames)
+ : AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs),
+ NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing),
+ AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific),
+ IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC),
+ IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute),
+ Spellings(Spellings), ArgNames(ArgNames) {}
+
+public:
+ virtual ~ParsedAttrInfo() = default;
+
+ /// Check if this attribute appertains to D, and issue a diagnostic if not.
+ virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr,
+ const Decl *D) const {
+ return true;
+ }
+ /// Check if this attribute appertains to St, and issue a diagnostic if not.
+ virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr,
+ const Stmt *St) const {
+ return true;
+ }
+ /// Check if the given attribute is mutually exclusive with other attributes
+ /// already applied to the given declaration.
+ virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A,
+ const Decl *D) const {
+ return true;
+ }
+ /// Check if this attribute is allowed by the language we are compiling.
+ virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; }
+
+ /// Check if this attribute is allowed when compiling for the given target.
+ virtual bool existsInTarget(const TargetInfo &Target) const {
+ return true;
+ }
+ /// Convert the spelling index of Attr to a semantic spelling enum value.
+ virtual unsigned
+ spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const {
+ return UINT_MAX;
+ }
+ /// Returns true if the specified parameter index for this attribute in
+ /// Attr.td is an ExprArgument or VariadicExprArgument, or a subclass thereof;
+ /// returns false otherwise.
+ virtual bool isParamExpr(size_t N) const { return false; }
+ /// Populate Rules with the match rules of this attribute.
+ virtual void getPragmaAttributeMatchRules(
+ llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
+ const LangOptions &LangOpts) const {
+ }
+ enum AttrHandling {
+ NotHandled,
+ AttributeApplied,
+ AttributeNotApplied
+ };
+ /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this
+ /// Decl then do so and return either AttributeApplied if it was applied or
+ /// AttributeNotApplied if it wasn't. Otherwise return NotHandled.
+ virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D,
+ const ParsedAttr &Attr) const {
+ return NotHandled;
+ }
+
+ static const ParsedAttrInfo &get(const AttributeCommonInfo &A);
+ static ArrayRef<const ParsedAttrInfo *> getAllBuiltin();
+};
+
+typedef llvm::Registry<ParsedAttrInfo> ParsedAttrInfoRegistry;
+
+/// Represents information about a change in availability for
+/// an entity, which is part of the encoding of the 'availability'
+/// attribute.
+struct AvailabilityChange {
+ /// The location of the keyword indicating the kind of change.
+ SourceLocation KeywordLoc;
+
+ /// The version number at which the change occurred.
+ VersionTuple Version;
+
+ /// The source range covering the version number.
+ SourceRange VersionRange;
+
+ /// Determine whether this availability change is valid.
+ bool isValid() const { return !Version.empty(); }
+};
+
+namespace detail {
+enum AvailabilitySlot {
+ IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots
+};
+
+/// Describes the trailing object for Availability attribute in ParsedAttr.
+struct AvailabilityData {
+ AvailabilityChange Changes[NumAvailabilitySlots];
+ SourceLocation StrictLoc;
+ const Expr *Replacement;
+
+ AvailabilityData(const AvailabilityChange &Introduced,
+ const AvailabilityChange &Deprecated,
+ const AvailabilityChange &Obsoleted,
+ SourceLocation Strict, const Expr *ReplaceExpr)
+ : StrictLoc(Strict), Replacement(ReplaceExpr) {
+ Changes[IntroducedSlot] = Introduced;
+ Changes[DeprecatedSlot] = Deprecated;
+ Changes[ObsoletedSlot] = Obsoleted;
+ }
+};
+
+struct TypeTagForDatatypeData {
+ ParsedType MatchingCType;
+ unsigned LayoutCompatible : 1;
+ unsigned MustBeNull : 1;
+};
+struct PropertyData {
+ IdentifierInfo *GetterId, *SetterId;
+
+ PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId)
+ : GetterId(getterId), SetterId(setterId) {}
+};
+
+} // namespace
+
+/// Wraps an identifier and optional source location for the identifier.
+struct IdentifierLoc {
+ SourceLocation Loc;
+ IdentifierInfo *Ident;
+
+ static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc,
+ IdentifierInfo *Ident);
+};
+
+/// A union of the various pointer types that can be passed to an
+/// ParsedAttr as an argument.
+using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>;
+using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>;
+
+/// ParsedAttr - Represents a syntactic attribute.
+///
+/// For a GNU attribute, there are four forms of this construct:
+///
+/// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused.
+/// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused.
+/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used.
+/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used.
+///
+class ParsedAttr final
+ : public AttributeCommonInfo,
+ private llvm::TrailingObjects<
+ ParsedAttr, ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> {
+ friend TrailingObjects;
+
+ size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; }
+ size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const {
+ return IsAvailability;
+ }
+ size_t
+ numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const {
+ return IsTypeTagForDatatype;
+ }
+ size_t numTrailingObjects(OverloadToken<ParsedType>) const {
+ return HasParsedType;
+ }
+ size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const {
+ return IsProperty;
+ }
+
+private:
+ IdentifierInfo *MacroII = nullptr;
+ SourceLocation MacroExpansionLoc;
+ SourceLocation EllipsisLoc;
+
+ /// The number of expression arguments this attribute has.
+ /// The expressions themselves are stored after the object.
+ unsigned NumArgs : 16;
+
+ /// True if already diagnosed as invalid.
+ mutable unsigned Invalid : 1;
+
+ /// True if this attribute was used as a type attribute.
+ mutable unsigned UsedAsTypeAttr : 1;
+
+ /// True if this has the extra information associated with an
+ /// availability attribute.
+ unsigned IsAvailability : 1;
+
+ /// True if this has extra information associated with a
+ /// type_tag_for_datatype attribute.
+ unsigned IsTypeTagForDatatype : 1;
+
+ /// True if this has extra information associated with a
+ /// Microsoft __delcspec(property) attribute.
+ unsigned IsProperty : 1;
+
+ /// True if this has a ParsedType
+ unsigned HasParsedType : 1;
+
+ /// True if the processing cache is valid.
+ mutable unsigned HasProcessingCache : 1;
+
+ /// A cached value.
+ mutable unsigned ProcessingCache : 8;
+
+ /// True if the attribute is specified using '#pragma clang attribute'.
+ mutable unsigned IsPragmaClangAttribute : 1;
+
+ /// The location of the 'unavailable' keyword in an
+ /// availability attribute.
+ SourceLocation UnavailableLoc;
+
+ const Expr *MessageExpr;
+
+ const ParsedAttrInfo &Info;
+
+ ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); }
+ ArgsUnion const *getArgsBuffer() const {
+ return getTrailingObjects<ArgsUnion>();
+ }
+
+ detail::AvailabilityData *getAvailabilityData() {
+ return getTrailingObjects<detail::AvailabilityData>();
+ }
+ const detail::AvailabilityData *getAvailabilityData() const {
+ return getTrailingObjects<detail::AvailabilityData>();
+ }
+
+private:
+ friend class AttributeFactory;
+ friend class AttributePool;
+
+ /// Constructor for attributes with expression arguments.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed,
+ SourceLocation ellipsisLoc)
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false),
+ Info(ParsedAttrInfo::get(*this)) {
+ if (numArgs)
+ memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
+ }
+
+ /// Constructor for availability attributes.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Parm, const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted, SourceLocation unavailable,
+ const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict,
+ const Expr *replacementExpr)
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false),
+ UnavailableLoc(unavailable), MessageExpr(messageExpr),
+ Info(ParsedAttrInfo::get(*this)) {
+ ArgsUnion PVal(Parm);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
+ new (getAvailabilityData()) detail::AvailabilityData(
+ introduced, deprecated, obsoleted, strict, replacementExpr);
+ }
+
+ /// Constructor for objc_bridge_related attributes.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
+ Syntax syntaxUsed)
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(3), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(false), HasProcessingCache(false),
+ IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
+ ArgsUnion *Args = getArgsBuffer();
+ Args[0] = Parm1;
+ Args[1] = Parm2;
+ Args[2] = Parm3;
+ }
+
+ /// Constructor for type_tag_for_datatype attribute.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *ArgKind, ParsedType matchingCType,
+ bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed)
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(1), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false),
+ HasParsedType(false), HasProcessingCache(false),
+ IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
+ ArgsUnion PVal(ArgKind);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
+ detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
+ new (&ExtraData.MatchingCType) ParsedType(matchingCType);
+ ExtraData.LayoutCompatible = layoutCompatible;
+ ExtraData.MustBeNull = mustBeNull;
+ }
+
+ /// Constructor for attributes with a single type argument.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg, Syntax syntaxUsed)
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(true), HasProcessingCache(false),
+ IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
+ new (&getTypeBuffer()) ParsedType(typeArg);
+ }
+
+ /// Constructor for microsoft __declspec(property) attribute.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ Syntax syntaxUsed)
+ : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc,
+ syntaxUsed),
+ NumArgs(0), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true),
+ HasParsedType(false), HasProcessingCache(false),
+ IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) {
+ new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
+ }
+
+ /// Type tag information is stored immediately following the arguments, if
+ /// any, at the end of the object. They are mutually exclusive with
+ /// availability slots.
+ detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() {
+ return *getTrailingObjects<detail::TypeTagForDatatypeData>();
+ }
+ const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const {
+ return *getTrailingObjects<detail::TypeTagForDatatypeData>();
+ }
+
+ /// The type buffer immediately follows the object and are mutually exclusive
+ /// with arguments.
+ ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); }
+ const ParsedType &getTypeBuffer() const {
+ return *getTrailingObjects<ParsedType>();
+ }
+
+ /// The property data immediately follows the object is mutually exclusive
+ /// with arguments.
+ detail::PropertyData &getPropertyDataBuffer() {
+ assert(IsProperty);
+ return *getTrailingObjects<detail::PropertyData>();
+ }
+ const detail::PropertyData &getPropertyDataBuffer() const {
+ assert(IsProperty);
+ return *getTrailingObjects<detail::PropertyData>();
+ }
+
+ size_t allocated_size() const;
+
+public:
+ ParsedAttr(const ParsedAttr &) = delete;
+ ParsedAttr(ParsedAttr &&) = delete;
+ ParsedAttr &operator=(const ParsedAttr &) = delete;
+ ParsedAttr &operator=(ParsedAttr &&) = delete;
+ ~ParsedAttr() = delete;
+
+ void operator delete(void *) = delete;
+
+ bool hasParsedType() const { return HasParsedType; }
+
+ /// Is this the Microsoft __declspec(property) attribute?
+ bool isDeclspecPropertyAttribute() const {
+ return IsProperty;
+ }
+
+ bool isInvalid() const { return Invalid; }
+ void setInvalid(bool b = true) const { Invalid = b; }
+
+ bool hasProcessingCache() const { return HasProcessingCache; }
+
+ unsigned getProcessingCache() const {
+ assert(hasProcessingCache());
+ return ProcessingCache;
+ }
+
+ void setProcessingCache(unsigned value) const {
+ ProcessingCache = value;
+ HasProcessingCache = true;
+ }
+
+ bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; }
+ void setUsedAsTypeAttr(bool Used = true) { UsedAsTypeAttr = Used; }
+
+ /// True if the attribute is specified using '#pragma clang attribute'.
+ bool isPragmaClangAttribute() const { return IsPragmaClangAttribute; }
+
+ void setIsPragmaClangAttribute() { IsPragmaClangAttribute = true; }
+
+ bool isPackExpansion() const { return EllipsisLoc.isValid(); }
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// getNumArgs - Return the number of actual arguments to this attribute.
+ unsigned getNumArgs() const { return NumArgs; }
+
+ /// getArg - Return the specified argument.
+ ArgsUnion getArg(unsigned Arg) const {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ return getArgsBuffer()[Arg];
+ }
+
+ bool isArgExpr(unsigned Arg) const {
+ return Arg < NumArgs && getArg(Arg).is<Expr*>();
+ }
+
+ Expr *getArgAsExpr(unsigned Arg) const {
+ return getArg(Arg).get<Expr*>();
+ }
+
+ bool isArgIdent(unsigned Arg) const {
+ return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>();
+ }
+
+ IdentifierLoc *getArgAsIdent(unsigned Arg) const {
+ return getArg(Arg).get<IdentifierLoc*>();
+ }
+
+ const AvailabilityChange &getAvailabilityIntroduced() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return getAvailabilityData()->Changes[detail::IntroducedSlot];
+ }
+
+ const AvailabilityChange &getAvailabilityDeprecated() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return getAvailabilityData()->Changes[detail::DeprecatedSlot];
+ }
+
+ const AvailabilityChange &getAvailabilityObsoleted() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return getAvailabilityData()->Changes[detail::ObsoletedSlot];
+ }
+
+ SourceLocation getStrictLoc() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return getAvailabilityData()->StrictLoc;
+ }
+
+ SourceLocation getUnavailableLoc() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return UnavailableLoc;
+ }
+
+ const Expr * getMessageExpr() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return MessageExpr;
+ }
+
+ const Expr *getReplacementExpr() const {
+ assert(getParsedKind() == AT_Availability &&
+ "Not an availability attribute");
+ return getAvailabilityData()->Replacement;
+ }
+
+ const ParsedType &getMatchingCType() const {
+ assert(getParsedKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().MatchingCType;
+ }
+
+ bool getLayoutCompatible() const {
+ assert(getParsedKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().LayoutCompatible;
+ }
+
+ bool getMustBeNull() const {
+ assert(getParsedKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().MustBeNull;
+ }
+
+ const ParsedType &getTypeArg() const {
+ assert(HasParsedType && "Not a type attribute");
+ return getTypeBuffer();
+ }
+
+ IdentifierInfo *getPropertyDataGetter() const {
+ assert(isDeclspecPropertyAttribute() &&
+ "Not a __delcspec(property) attribute");
+ return getPropertyDataBuffer().GetterId;
+ }
+
+ IdentifierInfo *getPropertyDataSetter() const {
+ assert(isDeclspecPropertyAttribute() &&
+ "Not a __delcspec(property) attribute");
+ return getPropertyDataBuffer().SetterId;
+ }
+
+ /// Set the macro identifier info object that this parsed attribute was
+ /// declared in if it was declared in a macro. Also set the expansion location
+ /// of the macro.
+ void setMacroIdentifier(IdentifierInfo *MacroName, SourceLocation Loc) {
+ MacroII = MacroName;
+ MacroExpansionLoc = Loc;
+ }
+
+ /// Returns true if this attribute was declared in a macro.
+ bool hasMacroIdentifier() const { return MacroII != nullptr; }
+
+ /// Return the macro identifier if this attribute was declared in a macro.
+ /// nullptr is returned if it was not declared in a macro.
+ IdentifierInfo *getMacroIdentifier() const { return MacroII; }
+
+ SourceLocation getMacroExpansionLoc() const {
+ assert(hasMacroIdentifier() && "Can only get the macro expansion location "
+ "if this attribute has a macro identifier.");
+ return MacroExpansionLoc;
+ }
+
+ /// Check if the attribute has exactly as many args as Num. May output an
+ /// error. Returns false if a diagnostic is produced.
+ bool checkExactlyNumArgs(class Sema &S, unsigned Num) const;
+ /// Check if the attribute has at least as many args as Num. May output an
+ /// error. Returns false if a diagnostic is produced.
+ bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const;
+ /// Check if the attribute has at most as many args as Num. May output an
+ /// error. Returns false if a diagnostic is produced.
+ bool checkAtMostNumArgs(class Sema &S, unsigned Num) const;
+
+ bool isTargetSpecificAttr() const;
+ bool isTypeAttr() const;
+ bool isStmtAttr() const;
+
+ bool hasCustomParsing() const;
+ bool acceptsExprPack() const;
+ bool isParamExpr(size_t N) const;
+ unsigned getMinArgs() const;
+ unsigned getMaxArgs() const;
+ unsigned getNumArgMembers() const;
+ bool hasVariadicArg() const;
+ void handleAttrWithDelayedArgs(Sema &S, Decl *D) const;
+ bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
+ bool diagnoseAppertainsTo(class Sema &S, const Stmt *St) const;
+ bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const;
+ // This function stub exists for parity with the declaration checking code so
+ // that checkCommonAttributeFeatures() can work generically on declarations
+ // or statements.
+ bool diagnoseMutualExclusion(class Sema &S, const Stmt *St) const {
+ return true;
+ }
+ bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const;
+ void getMatchRules(const LangOptions &LangOpts,
+ SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>>
+ &MatchRules) const;
+ bool diagnoseLangOpts(class Sema &S) const;
+ bool existsInTarget(const TargetInfo &Target) const;
+ bool isKnownToGCC() const;
+ bool isSupportedByPragmaAttribute() const;
+
+ /// Returns whether a [[]] attribute, if specified ahead of a declaration,
+ /// should be applied to the decl-specifier-seq instead (i.e. whether it
+ /// "slides" to the decl-specifier-seq).
+ ///
+ /// By the standard, attributes specified before the declaration always
+ /// appertain to the declaration, but historically we have allowed some of
+ /// these attributes to slide to the decl-specifier-seq, so we need to keep
+ /// supporting this behavior.
+ ///
+ /// This may only be called if isStandardAttributeSyntax() returns true.
+ bool slidesFromDeclToDeclSpecLegacyBehavior() const;
+
+ /// If the parsed attribute has a semantic equivalent, and it would
+ /// have a semantic Spelling enumeration (due to having semantically-distinct
+ /// spelling variations), return the value of that semantic spelling. If the
+ /// parsed attribute does not have a semantic equivalent, or would not have
+ /// a Spelling enumeration, the value UINT_MAX is returned.
+ unsigned getSemanticSpelling() const;
+
+ /// If this is an OpenCL address space attribute, returns its representation
+ /// in LangAS, otherwise returns default address space.
+ LangAS asOpenCLLangAS() const {
+ switch (getParsedKind()) {
+ case ParsedAttr::AT_OpenCLConstantAddressSpace:
+ return LangAS::opencl_constant;
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
+ return LangAS::opencl_global;
+ case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace:
+ return LangAS::opencl_global_device;
+ case ParsedAttr::AT_OpenCLGlobalHostAddressSpace:
+ return LangAS::opencl_global_host;
+ case ParsedAttr::AT_OpenCLLocalAddressSpace:
+ return LangAS::opencl_local;
+ case ParsedAttr::AT_OpenCLPrivateAddressSpace:
+ return LangAS::opencl_private;
+ case ParsedAttr::AT_OpenCLGenericAddressSpace:
+ return LangAS::opencl_generic;
+ default:
+ return LangAS::Default;
+ }
+ }
+
+ /// If this is an OpenCL address space attribute, returns its SYCL
+ /// representation in LangAS, otherwise returns default address space.
+ LangAS asSYCLLangAS() const {
+ switch (getKind()) {
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
+ return LangAS::sycl_global;
+ case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace:
+ return LangAS::sycl_global_device;
+ case ParsedAttr::AT_OpenCLGlobalHostAddressSpace:
+ return LangAS::sycl_global_host;
+ case ParsedAttr::AT_OpenCLLocalAddressSpace:
+ return LangAS::sycl_local;
+ case ParsedAttr::AT_OpenCLPrivateAddressSpace:
+ return LangAS::sycl_private;
+ case ParsedAttr::AT_OpenCLGenericAddressSpace:
+ default:
+ return LangAS::Default;
+ }
+ }
+
+ /// If this is an HLSL address space attribute, returns its representation
+ /// in LangAS, otherwise returns default address space.
+ LangAS asHLSLLangAS() const {
+ switch (getParsedKind()) {
+ case ParsedAttr::AT_HLSLGroupSharedAddressSpace:
+ return LangAS::hlsl_groupshared;
+ default:
+ return LangAS::Default;
+ }
+ }
+
+ AttributeCommonInfo::Kind getKind() const {
+ return AttributeCommonInfo::Kind(Info.AttrKind);
+ }
+ const ParsedAttrInfo &getInfo() const { return Info; }
+};
+
+class AttributePool;
+/// A factory, from which one makes pools, from which one creates
+/// individual attributes which are deallocated with the pool.
+///
+/// Note that it's tolerably cheap to create and destroy one of
+/// these as long as you don't actually allocate anything in it.
+class AttributeFactory {
+public:
+ enum {
+ AvailabilityAllocSize =
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(1, 1, 0, 0, 0),
+ TypeTagForDatatypeAllocSize =
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(1, 0, 1, 0, 0),
+ PropertyAllocSize =
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(0, 0, 0, 0, 1),
+ };
+
+private:
+ enum {
+ /// The number of free lists we want to be sure to support
+ /// inline. This is just enough that availability attributes
+ /// don't surpass it. It's actually very unlikely we'll see an
+ /// attribute that needs more than that; on x86-64 you'd need 10
+ /// expression arguments, and on i386 you'd need 19.
+ InlineFreeListsCapacity =
+ 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *)
+ };
+
+ llvm::BumpPtrAllocator Alloc;
+
+ /// Free lists. The index is determined by the following formula:
+ /// (size - sizeof(ParsedAttr)) / sizeof(void*)
+ SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists;
+
+ // The following are the private interface used by AttributePool.
+ friend class AttributePool;
+
+ /// Allocate an attribute of the given size.
+ void *allocate(size_t size);
+
+ void deallocate(ParsedAttr *AL);
+
+ /// Reclaim all the attributes in the given pool chain, which is
+ /// non-empty. Note that the current implementation is safe
+ /// against reclaiming things which were not actually allocated
+ /// with the allocator, although of course it's important to make
+ /// sure that their allocator lives at least as long as this one.
+ void reclaimPool(AttributePool &head);
+
+public:
+ AttributeFactory();
+ ~AttributeFactory();
+};
+
+class AttributePool {
+ friend class AttributeFactory;
+ friend class ParsedAttributes;
+ AttributeFactory &Factory;
+ llvm::SmallVector<ParsedAttr *> Attrs;
+
+ void *allocate(size_t size) {
+ return Factory.allocate(size);
+ }
+
+ ParsedAttr *add(ParsedAttr *attr) {
+ Attrs.push_back(attr);
+ return attr;
+ }
+
+ void remove(ParsedAttr *attr) {
+ assert(llvm::is_contained(Attrs, attr) &&
+ "Can't take attribute from a pool that doesn't own it!");
+ Attrs.erase(llvm::find(Attrs, attr));
+ }
+
+ void takePool(AttributePool &pool);
+
+public:
+ /// Create a new pool for a factory.
+ AttributePool(AttributeFactory &factory) : Factory(factory) {}
+
+ AttributePool(const AttributePool &) = delete;
+
+ ~AttributePool() { Factory.reclaimPool(*this); }
+
+ /// Move the given pool's allocations to this pool.
+ AttributePool(AttributePool &&pool) = default;
+
+ AttributeFactory &getFactory() const { return Factory; }
+
+ void clear() {
+ Factory.reclaimPool(*this);
+ Attrs.clear();
+ }
+
+ /// Take the given pool's allocations and add them to this pool.
+ void takeAllFrom(AttributePool &pool) {
+ takePool(pool);
+ pool.Attrs.clear();
+ }
+
+ ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs,
+ ParsedAttr::Syntax syntax,
+ SourceLocation ellipsisLoc = SourceLocation()) {
+ size_t temp =
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(numArgs, 0, 0, 0, 0);
+ (void)temp;
+ void *memory = allocate(
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(numArgs, 0, 0, 0,
+ 0));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ args, numArgs, syntax, ellipsisLoc));
+ }
+
+ ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param, const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted,
+ SourceLocation unavailable, const Expr *MessageExpr,
+ ParsedAttr::Syntax syntax, SourceLocation strict,
+ const Expr *ReplacementExpr) {
+ void *memory = allocate(AttributeFactory::AvailabilityAllocSize);
+ return add(new (memory) ParsedAttr(
+ attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
+ obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr));
+ }
+
+ ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param1, IdentifierLoc *Param2,
+ IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
+ void *memory = allocate(
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(3, 0, 0, 0, 0));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ Param1, Param2, Param3, syntax));
+ }
+
+ ParsedAttr *
+ createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *argumentKind,
+ ParsedType matchingCType, bool layoutCompatible,
+ bool mustBeNull, ParsedAttr::Syntax syntax) {
+ void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize);
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ argumentKind, matchingCType,
+ layoutCompatible, mustBeNull, syntax));
+ }
+
+ ParsedAttr *createTypeAttribute(IdentifierInfo *attrName,
+ SourceRange attrRange,
+ IdentifierInfo *scopeName,
+ SourceLocation scopeLoc, ParsedType typeArg,
+ ParsedAttr::Syntax syntaxUsed) {
+ void *memory = allocate(
+ ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
+ detail::TypeTagForDatatypeData, ParsedType,
+ detail::PropertyData>(0, 0, 0, 1, 0));
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ typeArg, syntaxUsed));
+ }
+
+ ParsedAttr *
+ createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ ParsedAttr::Syntax syntaxUsed) {
+ void *memory = allocate(AttributeFactory::PropertyAllocSize);
+ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc,
+ getterId, setterId, syntaxUsed));
+ }
+};
+
+class ParsedAttributesView {
+ using VecTy = llvm::SmallVector<ParsedAttr *>;
+ using SizeType = decltype(std::declval<VecTy>().size());
+
+public:
+ SourceRange Range;
+
+ static const ParsedAttributesView &none() {
+ static const ParsedAttributesView Attrs;
+ return Attrs;
+ }
+
+ bool empty() const { return AttrList.empty(); }
+ SizeType size() const { return AttrList.size(); }
+ ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; }
+ const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; }
+
+ void addAtEnd(ParsedAttr *newAttr) {
+ assert(newAttr);
+ AttrList.push_back(newAttr);
+ }
+
+ void remove(ParsedAttr *ToBeRemoved) {
+ assert(is_contained(AttrList, ToBeRemoved) &&
+ "Cannot remove attribute that isn't in the list");
+ AttrList.erase(llvm::find(AttrList, ToBeRemoved));
+ }
+
+ void clearListOnly() { AttrList.clear(); }
+
+ struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator,
+ std::random_access_iterator_tag,
+ ParsedAttr> {
+ iterator() : iterator_adaptor_base(nullptr) {}
+ iterator(VecTy::iterator I) : iterator_adaptor_base(I) {}
+ reference operator*() const { return **I; }
+ friend class ParsedAttributesView;
+ };
+ struct const_iterator
+ : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator,
+ std::random_access_iterator_tag,
+ ParsedAttr> {
+ const_iterator() : iterator_adaptor_base(nullptr) {}
+ const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {}
+
+ reference operator*() const { return **I; }
+ friend class ParsedAttributesView;
+ };
+
+ void addAll(iterator B, iterator E) {
+ AttrList.insert(AttrList.begin(), B.I, E.I);
+ }
+
+ void addAll(const_iterator B, const_iterator E) {
+ AttrList.insert(AttrList.begin(), B.I, E.I);
+ }
+
+ void addAllAtEnd(iterator B, iterator E) {
+ AttrList.insert(AttrList.end(), B.I, E.I);
+ }
+
+ void addAllAtEnd(const_iterator B, const_iterator E) {
+ AttrList.insert(AttrList.end(), B.I, E.I);
+ }
+
+ iterator begin() { return iterator(AttrList.begin()); }
+ const_iterator begin() const { return const_iterator(AttrList.begin()); }
+ iterator end() { return iterator(AttrList.end()); }
+ const_iterator end() const { return const_iterator(AttrList.end()); }
+
+ ParsedAttr &front() {
+ assert(!empty());
+ return *AttrList.front();
+ }
+ const ParsedAttr &front() const {
+ assert(!empty());
+ return *AttrList.front();
+ }
+ ParsedAttr &back() {
+ assert(!empty());
+ return *AttrList.back();
+ }
+ const ParsedAttr &back() const {
+ assert(!empty());
+ return *AttrList.back();
+ }
+
+ bool hasAttribute(ParsedAttr::Kind K) const {
+ return llvm::any_of(AttrList, [K](const ParsedAttr *AL) {
+ return AL->getParsedKind() == K;
+ });
+ }
+
+private:
+ VecTy AttrList;
+};
+
+/// ParsedAttributes - A collection of parsed attributes. Currently
+/// we don't differentiate between the various attribute syntaxes,
+/// which is basically silly.
+///
+/// Right now this is a very lightweight container, but the expectation
+/// is that this will become significantly more serious.
+class ParsedAttributes : public ParsedAttributesView {
+public:
+ ParsedAttributes(AttributeFactory &factory) : pool(factory) {}
+ ParsedAttributes(const ParsedAttributes &) = delete;
+
+ AttributePool &getPool() const { return pool; }
+
+ void takeAllFrom(ParsedAttributes &Other) {
+ assert(&Other != this &&
+ "ParsedAttributes can't take attributes from itself");
+ addAll(Other.begin(), Other.end());
+ Other.clearListOnly();
+ pool.takeAllFrom(Other.pool);
+ }
+
+ void takeOneFrom(ParsedAttributes &Other, ParsedAttr *PA) {
+ assert(&Other != this &&
+ "ParsedAttributes can't take attribute from itself");
+ Other.getPool().remove(PA);
+ Other.remove(PA);
+ getPool().add(PA);
+ addAtEnd(PA);
+ }
+
+ void clear() {
+ clearListOnly();
+ pool.clear();
+ Range = SourceRange();
+ }
+
+ /// Add attribute with expression arguments.
+ ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ArgsUnion *args, unsigned numArgs,
+ ParsedAttr::Syntax syntax,
+ SourceLocation ellipsisLoc = SourceLocation()) {
+ ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
+ args, numArgs, syntax, ellipsisLoc);
+ addAtEnd(attr);
+ return attr;
+ }
+
+ /// Add availability attribute.
+ ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param, const AvailabilityChange &introduced,
+ const AvailabilityChange &deprecated,
+ const AvailabilityChange &obsoleted,
+ SourceLocation unavailable, const Expr *MessageExpr,
+ ParsedAttr::Syntax syntax, SourceLocation strict,
+ const Expr *ReplacementExpr) {
+ ParsedAttr *attr = pool.create(
+ attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated,
+ obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr);
+ addAtEnd(attr);
+ return attr;
+ }
+
+ /// Add objc_bridge_related attribute.
+ ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Param1, IdentifierLoc *Param2,
+ IdentifierLoc *Param3, ParsedAttr::Syntax syntax) {
+ ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc,
+ Param1, Param2, Param3, syntax);
+ addAtEnd(attr);
+ return attr;
+ }
+
+ /// Add type_tag_for_datatype attribute.
+ ParsedAttr *
+ addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *argumentKind,
+ ParsedType matchingCType, bool layoutCompatible,
+ bool mustBeNull, ParsedAttr::Syntax syntax) {
+ ParsedAttr *attr = pool.createTypeTagForDatatype(
+ attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType,
+ layoutCompatible, mustBeNull, syntax);
+ addAtEnd(attr);
+ return attr;
+ }
+
+ /// Add an attribute with a single type argument.
+ ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg,
+ ParsedAttr::Syntax syntaxUsed) {
+ ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName,
+ scopeLoc, typeArg, syntaxUsed);
+ addAtEnd(attr);
+ return attr;
+ }
+
+ /// Add microsoft __delspec(property) attribute.
+ ParsedAttr *
+ addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ ParsedAttr::Syntax syntaxUsed) {
+ ParsedAttr *attr =
+ pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc,
+ getterId, setterId, syntaxUsed);
+ addAtEnd(attr);
+ return attr;
+ }
+
+private:
+ mutable AttributePool pool;
+};
+
+/// Consumes the attributes from `First` and `Second` and concatenates them into
+/// `Result`. Sets `Result.Range` to the combined range of `First` and `Second`.
+void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &Second,
+ ParsedAttributes &Result);
+
+/// These constants match the enumerated choices of
+/// err_attribute_argument_n_type and err_attribute_argument_type.
+enum AttributeArgumentNType {
+ AANT_ArgumentIntOrBool,
+ AANT_ArgumentIntegerConstant,
+ AANT_ArgumentString,
+ AANT_ArgumentIdentifier,
+ AANT_ArgumentConstantExpr,
+ AANT_ArgumentBuiltinFunction,
+};
+
+/// These constants match the enumerated choices of
+/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
+enum AttributeDeclKind {
+ ExpectedFunction,
+ ExpectedUnion,
+ ExpectedVariableOrFunction,
+ ExpectedFunctionOrMethod,
+ ExpectedFunctionMethodOrBlock,
+ ExpectedFunctionMethodOrParameter,
+ ExpectedVariable,
+ ExpectedVariableOrField,
+ ExpectedVariableFieldOrTag,
+ ExpectedTypeOrNamespace,
+ ExpectedFunctionVariableOrClass,
+ ExpectedKernelFunction,
+ ExpectedFunctionWithProtoType,
+};
+
+inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
+ const ParsedAttr &At) {
+ DB.AddTaggedVal(reinterpret_cast<uint64_t>(At.getAttrName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
+ const ParsedAttr *At) {
+ DB.AddTaggedVal(reinterpret_cast<uint64_t>(At->getAttrName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+/// AttributeCommonInfo has a non-explicit constructor which takes an
+/// SourceRange as its only argument, this constructor has many uses so making
+/// it explicit is hard. This constructor causes ambiguity with
+/// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R).
+/// We use SFINAE to disable any conversion and remove any ambiguity.
+template <
+ typename ACI,
+ std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
+inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
+ const ACI &CI) {
+ DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI.getAttrName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+template <
+ typename ACI,
+ std::enable_if_t<std::is_same<ACI, AttributeCommonInfo>::value, int> = 0>
+inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
+ const ACI *CI) {
+ DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI->getAttrName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_PARSEDATTR_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/ParsedTemplate.h b/contrib/libs/clang16/include/clang/Sema/ParsedTemplate.h
new file mode 100644
index 0000000000..83faf47709
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/ParsedTemplate.h
@@ -0,0 +1,273 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- ParsedTemplate.h - Template Parsing Data Types ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides data structures that store the parsed representation of
+// templates.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+
+#include "clang/Basic/OperatorKinds.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <cstdlib>
+#include <new>
+
+namespace clang {
+ /// Represents the parsed form of a C++ template argument.
+ class ParsedTemplateArgument {
+ public:
+ /// Describes the kind of template argument that was parsed.
+ enum KindType {
+ /// A template type parameter, stored as a type.
+ Type,
+ /// A non-type template parameter, stored as an expression.
+ NonType,
+ /// A template template argument, stored as a template name.
+ Template
+ };
+
+ /// Build an empty template argument.
+ ///
+ /// This template argument is invalid.
+ ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { }
+
+ /// Create a template type argument or non-type template argument.
+ ///
+ /// \param Arg the template type argument or non-type template argument.
+ /// \param Loc the location of the type.
+ ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
+ : Kind(Kind), Arg(Arg), Loc(Loc) { }
+
+ /// Create a template template argument.
+ ///
+ /// \param SS the C++ scope specifier that precedes the template name, if
+ /// any.
+ ///
+ /// \param Template the template to which this template template
+ /// argument refers.
+ ///
+ /// \param TemplateLoc the location of the template name.
+ ParsedTemplateArgument(const CXXScopeSpec &SS,
+ ParsedTemplateTy Template,
+ SourceLocation TemplateLoc)
+ : Kind(ParsedTemplateArgument::Template),
+ Arg(Template.getAsOpaquePtr()), SS(SS), Loc(TemplateLoc) {}
+
+ /// Determine whether the given template argument is invalid.
+ bool isInvalid() const { return Arg == nullptr; }
+
+ /// Determine what kind of template argument we have.
+ KindType getKind() const { return Kind; }
+
+ /// Retrieve the template type argument's type.
+ ParsedType getAsType() const {
+ assert(Kind == Type && "Not a template type argument");
+ return ParsedType::getFromOpaquePtr(Arg);
+ }
+
+ /// Retrieve the non-type template argument's expression.
+ Expr *getAsExpr() const {
+ assert(Kind == NonType && "Not a non-type template argument");
+ return static_cast<Expr*>(Arg);
+ }
+
+ /// Retrieve the template template argument's template name.
+ ParsedTemplateTy getAsTemplate() const {
+ assert(Kind == Template && "Not a template template argument");
+ return ParsedTemplateTy::getFromOpaquePtr(Arg);
+ }
+
+ /// Retrieve the location of the template argument.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// Retrieve the nested-name-specifier that precedes the template
+ /// name in a template template argument.
+ const CXXScopeSpec &getScopeSpec() const {
+ assert(Kind == Template &&
+ "Only template template arguments can have a scope specifier");
+ return SS;
+ }
+
+ /// Retrieve the location of the ellipsis that makes a template
+ /// template argument into a pack expansion.
+ SourceLocation getEllipsisLoc() const {
+ assert(Kind == Template &&
+ "Only template template arguments can have an ellipsis");
+ return EllipsisLoc;
+ }
+
+ /// Retrieve a pack expansion of the given template template
+ /// argument.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ParsedTemplateArgument getTemplatePackExpansion(
+ SourceLocation EllipsisLoc) const;
+
+ private:
+ KindType Kind;
+
+ /// The actual template argument representation, which may be
+ /// an \c Sema::TypeTy* (for a type), an Expr* (for an
+ /// expression), or an Sema::TemplateTy (for a template).
+ void *Arg;
+
+ /// The nested-name-specifier that can accompany a template template
+ /// argument.
+ CXXScopeSpec SS;
+
+ /// the location of the template argument.
+ SourceLocation Loc;
+
+ /// The ellipsis location that can accompany a template template
+ /// argument (turning it into a template template argument expansion).
+ SourceLocation EllipsisLoc;
+ };
+
+ /// Information about a template-id annotation
+ /// token.
+ ///
+ /// A template-id annotation token contains the template name,
+ /// template arguments, and the source locations for important
+ /// tokens. All of the information about template arguments is allocated
+ /// directly after this structure.
+ /// A template-id annotation token can also be generated by a type-constraint
+ /// construct with no explicit template arguments, e.g. "template<C T>" would
+ /// annotate C as a TemplateIdAnnotation with no template arguments (the angle
+ /// locations would be invalid in this case).
+ struct TemplateIdAnnotation final
+ : private llvm::TrailingObjects<TemplateIdAnnotation,
+ ParsedTemplateArgument> {
+ friend TrailingObjects;
+ /// TemplateKWLoc - The location of the template keyword.
+ /// For e.g. typename T::template Y<U>
+ SourceLocation TemplateKWLoc;
+
+ /// TemplateNameLoc - The location of the template name within the
+ /// source.
+ SourceLocation TemplateNameLoc;
+
+ /// FIXME: Temporarily stores the name of a specialization
+ IdentifierInfo *Name;
+
+ /// FIXME: Temporarily stores the overloaded operator kind.
+ OverloadedOperatorKind Operator;
+
+ /// The declaration of the template corresponding to the
+ /// template-name.
+ ParsedTemplateTy Template;
+
+ /// The kind of template that Template refers to. If this is
+ /// TNK_Non_template, an error was encountered and diagnosed
+ /// when parsing or looking up the template name.
+ TemplateNameKind Kind;
+
+ /// The location of the '<' before the template argument
+ /// list.
+ SourceLocation LAngleLoc;
+
+ /// The location of the '>' after the template argument
+ /// list.
+ SourceLocation RAngleLoc;
+
+ /// NumArgs - The number of template arguments.
+ unsigned NumArgs;
+
+ /// Whether an error was encountered in the template arguments.
+ /// If so, NumArgs and the trailing arguments are best-effort.
+ bool ArgsInvalid;
+
+ /// Retrieves a pointer to the template arguments
+ ParsedTemplateArgument *getTemplateArgs() {
+ return getTrailingObjects<ParsedTemplateArgument>();
+ }
+
+ /// Creates a new TemplateIdAnnotation with NumArgs arguments and
+ /// appends it to List.
+ static TemplateIdAnnotation *
+ Create(SourceLocation TemplateKWLoc, SourceLocation TemplateNameLoc,
+ IdentifierInfo *Name, OverloadedOperatorKind OperatorKind,
+ ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
+ SourceLocation LAngleLoc, SourceLocation RAngleLoc,
+ ArrayRef<ParsedTemplateArgument> TemplateArgs, bool ArgsInvalid,
+ SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
+ TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc(
+ totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
+ TemplateIdAnnotation(TemplateKWLoc, TemplateNameLoc, Name,
+ OperatorKind, OpaqueTemplateName, TemplateKind,
+ LAngleLoc, RAngleLoc, TemplateArgs, ArgsInvalid);
+ CleanupList.push_back(TemplateId);
+ return TemplateId;
+ }
+
+ void Destroy() {
+ for (ParsedTemplateArgument &A :
+ llvm::make_range(getTemplateArgs(), getTemplateArgs() + NumArgs))
+ A.~ParsedTemplateArgument();
+ this->~TemplateIdAnnotation();
+ free(this);
+ }
+
+ /// Determine whether this might be a type template.
+ bool mightBeType() const {
+ return Kind == TNK_Non_template ||
+ Kind == TNK_Type_template ||
+ Kind == TNK_Dependent_template_name ||
+ Kind == TNK_Undeclared_template;
+ }
+
+ bool hasInvalidName() const { return Kind == TNK_Non_template; }
+ bool hasInvalidArgs() const { return ArgsInvalid; }
+
+ bool isInvalid() const { return hasInvalidName() || hasInvalidArgs(); }
+
+ private:
+ TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
+
+ TemplateIdAnnotation(SourceLocation TemplateKWLoc,
+ SourceLocation TemplateNameLoc, IdentifierInfo *Name,
+ OverloadedOperatorKind OperatorKind,
+ ParsedTemplateTy OpaqueTemplateName,
+ TemplateNameKind TemplateKind,
+ SourceLocation LAngleLoc, SourceLocation RAngleLoc,
+ ArrayRef<ParsedTemplateArgument> TemplateArgs,
+ bool ArgsInvalid) noexcept
+ : TemplateKWLoc(TemplateKWLoc), TemplateNameLoc(TemplateNameLoc),
+ Name(Name), Operator(OperatorKind), Template(OpaqueTemplateName),
+ Kind(TemplateKind), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
+ NumArgs(TemplateArgs.size()), ArgsInvalid(ArgsInvalid) {
+
+ std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(),
+ getTemplateArgs());
+ }
+ ~TemplateIdAnnotation() = default;
+ };
+
+ /// Retrieves the range of the given template parameter lists.
+ SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
+ unsigned NumParams);
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/RISCVIntrinsicManager.h b/contrib/libs/clang16/include/clang/Sema/RISCVIntrinsicManager.h
new file mode 100644
index 0000000000..a5daf0737a
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/RISCVIntrinsicManager.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- RISCVIntrinsicManager.h - RISC-V Intrinsic Handler -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the RISCVIntrinsicManager, which handles RISC-V vector
+// intrinsic functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H
+#define LLVM_CLANG_SEMA_RISCVINTRINSICMANAGER_H
+
+namespace clang {
+class LookupResult;
+class IdentifierInfo;
+class Preprocessor;
+
+namespace sema {
+class RISCVIntrinsicManager {
+public:
+ virtual ~RISCVIntrinsicManager() = default;
+
+ // Create RISC-V intrinsic and insert into symbol table and return true if
+ // found, otherwise return false.
+ virtual bool CreateIntrinsicIfFound(LookupResult &LR, IdentifierInfo *II,
+ Preprocessor &PP) = 0;
+};
+} // end namespace sema
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Scope.h b/contrib/libs/clang16/include/clang/Sema/Scope.h
new file mode 100644
index 0000000000..7873e593c3
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Scope.h
@@ -0,0 +1,581 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- Scope.h - Scope interface --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Scope interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SCOPE_H
+#define LLVM_CLANG_SEMA_SCOPE_H
+
+#include "clang/AST/Decl.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include <cassert>
+#include <optional>
+
+namespace llvm {
+
+class raw_ostream;
+
+} // namespace llvm
+
+namespace clang {
+
+class Decl;
+class DeclContext;
+class UsingDirectiveDecl;
+class VarDecl;
+
+/// Scope - A scope is a transient data structure that is used while parsing the
+/// program. It assists with resolving identifiers to the appropriate
+/// declaration.
+class Scope {
+public:
+ /// ScopeFlags - These are bitfields that are or'd together when creating a
+ /// scope, which defines the sorts of things the scope contains.
+ enum ScopeFlags {
+ /// This indicates that the scope corresponds to a function, which
+ /// means that labels are set here.
+ FnScope = 0x01,
+
+ /// This is a while, do, switch, for, etc that can have break
+ /// statements embedded into it.
+ BreakScope = 0x02,
+
+ /// This is a while, do, for, which can have continue statements
+ /// embedded into it.
+ ContinueScope = 0x04,
+
+ /// This is a scope that can contain a declaration. Some scopes
+ /// just contain loop constructs but don't contain decls.
+ DeclScope = 0x08,
+
+ /// The controlling scope in a if/switch/while/for statement.
+ ControlScope = 0x10,
+
+ /// The scope of a struct/union/class definition.
+ ClassScope = 0x20,
+
+ /// This is a scope that corresponds to a block/closure object.
+ /// Blocks serve as top-level scopes for some objects like labels, they
+ /// also prevent things like break and continue. BlockScopes always have
+ /// the FnScope and DeclScope flags set as well.
+ BlockScope = 0x40,
+
+ /// This is a scope that corresponds to the
+ /// template parameters of a C++ template. Template parameter
+ /// scope starts at the 'template' keyword and ends when the
+ /// template declaration ends.
+ TemplateParamScope = 0x80,
+
+ /// This is a scope that corresponds to the
+ /// parameters within a function prototype.
+ FunctionPrototypeScope = 0x100,
+
+ /// This is a scope that corresponds to the parameters within
+ /// a function prototype for a function declaration (as opposed to any
+ /// other kind of function declarator). Always has FunctionPrototypeScope
+ /// set as well.
+ FunctionDeclarationScope = 0x200,
+
+ /// This is a scope that corresponds to the Objective-C
+ /// \@catch statement.
+ AtCatchScope = 0x400,
+
+ /// This scope corresponds to an Objective-C method body.
+ /// It always has FnScope and DeclScope set as well.
+ ObjCMethodScope = 0x800,
+
+ /// This is a scope that corresponds to a switch statement.
+ SwitchScope = 0x1000,
+
+ /// This is the scope of a C++ try statement.
+ TryScope = 0x2000,
+
+ /// This is the scope for a function-level C++ try or catch scope.
+ FnTryCatchScope = 0x4000,
+
+ /// This is the scope of OpenMP executable directive.
+ OpenMPDirectiveScope = 0x8000,
+
+ /// This is the scope of some OpenMP loop directive.
+ OpenMPLoopDirectiveScope = 0x10000,
+
+ /// This is the scope of some OpenMP simd directive.
+ /// For example, it is used for 'omp simd', 'omp for simd'.
+ /// This flag is propagated to children scopes.
+ OpenMPSimdDirectiveScope = 0x20000,
+
+ /// This scope corresponds to an enum.
+ EnumScope = 0x40000,
+
+ /// This scope corresponds to an SEH try.
+ SEHTryScope = 0x80000,
+
+ /// This scope corresponds to an SEH except.
+ SEHExceptScope = 0x100000,
+
+ /// We are currently in the filter expression of an SEH except block.
+ SEHFilterScope = 0x200000,
+
+ /// This is a compound statement scope.
+ CompoundStmtScope = 0x400000,
+
+ /// We are between inheritance colon and the real class/struct definition
+ /// scope.
+ ClassInheritanceScope = 0x800000,
+
+ /// This is the scope of a C++ catch statement.
+ CatchScope = 0x1000000,
+
+ /// This is a scope in which a condition variable is currently being
+ /// parsed. If such a scope is a ContinueScope, it's invalid to jump to the
+ /// continue block from here.
+ ConditionVarScope = 0x2000000,
+
+ /// This is a scope of some OpenMP directive with
+ /// order clause which specifies concurrent
+ OpenMPOrderClauseScope = 0x4000000,
+ };
+
+private:
+ /// The parent scope for this scope. This is null for the translation-unit
+ /// scope.
+ Scope *AnyParent;
+
+ /// Flags - This contains a set of ScopeFlags, which indicates how the scope
+ /// interrelates with other control flow statements.
+ unsigned Flags;
+
+ /// Depth - This is the depth of this scope. The translation-unit scope has
+ /// depth 0.
+ unsigned short Depth;
+
+ /// Declarations with static linkage are mangled with the number of
+ /// scopes seen as a component.
+ unsigned short MSLastManglingNumber;
+
+ unsigned short MSCurManglingNumber;
+
+ /// PrototypeDepth - This is the number of function prototype scopes
+ /// enclosing this scope, including this scope.
+ unsigned short PrototypeDepth;
+
+ /// PrototypeIndex - This is the number of parameters currently
+ /// declared in this scope.
+ unsigned short PrototypeIndex;
+
+ /// FnParent - If this scope has a parent scope that is a function body, this
+ /// pointer is non-null and points to it. This is used for label processing.
+ Scope *FnParent;
+ Scope *MSLastManglingParent;
+
+ /// BreakParent/ContinueParent - This is a direct link to the innermost
+ /// BreakScope/ContinueScope which contains the contents of this scope
+ /// for control flow purposes (and might be this scope itself), or null
+ /// if there is no such scope.
+ Scope *BreakParent, *ContinueParent;
+
+ /// BlockParent - This is a direct link to the immediately containing
+ /// BlockScope if this scope is not one, or null if there is none.
+ Scope *BlockParent;
+
+ /// TemplateParamParent - This is a direct link to the
+ /// immediately containing template parameter scope. In the
+ /// case of nested templates, template parameter scopes can have
+ /// other template parameter scopes as parents.
+ Scope *TemplateParamParent;
+
+ /// DeclsInScope - This keeps track of all declarations in this scope. When
+ /// the declaration is added to the scope, it is set as the current
+ /// declaration for the identifier in the IdentifierTable. When the scope is
+ /// popped, these declarations are removed from the IdentifierTable's notion
+ /// of current declaration. It is up to the current Action implementation to
+ /// implement these semantics.
+ using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>;
+ DeclSetTy DeclsInScope;
+
+ /// The DeclContext with which this scope is associated. For
+ /// example, the entity of a class scope is the class itself, the
+ /// entity of a function scope is a function, etc.
+ DeclContext *Entity;
+
+ using UsingDirectivesTy = SmallVector<UsingDirectiveDecl *, 2>;
+ UsingDirectivesTy UsingDirectives;
+
+ /// Used to determine if errors occurred in this scope.
+ DiagnosticErrorTrap ErrorTrap;
+
+ /// A single NRVO candidate variable in this scope.
+ /// There are three possible values:
+ /// 1) pointer to VarDecl that denotes NRVO candidate itself.
+ /// 2) nullptr value means that NRVO is not allowed in this scope
+ /// (e.g. return a function parameter).
+ /// 3) std::nullopt value means that there is no NRVO candidate in this scope
+ /// (i.e. there are no return statements in this scope).
+ std::optional<VarDecl *> NRVO;
+
+ /// Represents return slots for NRVO candidates in the current scope.
+ /// If a variable is present in this set, it means that a return slot is
+ /// available for this variable in the current scope.
+ llvm::SmallPtrSet<VarDecl *, 8> ReturnSlots;
+
+ void setFlags(Scope *Parent, unsigned F);
+
+public:
+ Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag)
+ : ErrorTrap(Diag) {
+ Init(Parent, ScopeFlags);
+ }
+
+ /// getFlags - Return the flags for this scope.
+ unsigned getFlags() const { return Flags; }
+
+ void setFlags(unsigned F) { setFlags(getParent(), F); }
+
+ /// isBlockScope - Return true if this scope correspond to a closure.
+ bool isBlockScope() const { return Flags & BlockScope; }
+
+ /// getParent - Return the scope that this is nested in.
+ const Scope *getParent() const { return AnyParent; }
+ Scope *getParent() { return AnyParent; }
+
+ /// getFnParent - Return the closest scope that is a function body.
+ const Scope *getFnParent() const { return FnParent; }
+ Scope *getFnParent() { return FnParent; }
+
+ const Scope *getMSLastManglingParent() const {
+ return MSLastManglingParent;
+ }
+ Scope *getMSLastManglingParent() { return MSLastManglingParent; }
+
+ /// getContinueParent - Return the closest scope that a continue statement
+ /// would be affected by.
+ Scope *getContinueParent() {
+ return ContinueParent;
+ }
+
+ const Scope *getContinueParent() const {
+ return const_cast<Scope*>(this)->getContinueParent();
+ }
+
+ // Set whether we're in the scope of a condition variable, where 'continue'
+ // is disallowed despite being a continue scope.
+ void setIsConditionVarScope(bool InConditionVarScope) {
+ Flags = (Flags & ~ConditionVarScope) |
+ (InConditionVarScope ? ConditionVarScope : 0);
+ }
+
+ bool isConditionVarScope() const {
+ return Flags & ConditionVarScope;
+ }
+
+ /// getBreakParent - Return the closest scope that a break statement
+ /// would be affected by.
+ Scope *getBreakParent() {
+ return BreakParent;
+ }
+ const Scope *getBreakParent() const {
+ return const_cast<Scope*>(this)->getBreakParent();
+ }
+
+ Scope *getBlockParent() { return BlockParent; }
+ const Scope *getBlockParent() const { return BlockParent; }
+
+ Scope *getTemplateParamParent() { return TemplateParamParent; }
+ const Scope *getTemplateParamParent() const { return TemplateParamParent; }
+
+ /// Returns the depth of this scope. The translation-unit has scope depth 0.
+ unsigned getDepth() const { return Depth; }
+
+ /// Returns the number of function prototype scopes in this scope
+ /// chain.
+ unsigned getFunctionPrototypeDepth() const {
+ return PrototypeDepth;
+ }
+
+ /// Return the number of parameters declared in this function
+ /// prototype, increasing it by one for the next call.
+ unsigned getNextFunctionPrototypeIndex() {
+ assert(isFunctionPrototypeScope());
+ return PrototypeIndex++;
+ }
+
+ using decl_range = llvm::iterator_range<DeclSetTy::iterator>;
+
+ decl_range decls() const {
+ return decl_range(DeclsInScope.begin(), DeclsInScope.end());
+ }
+
+ bool decl_empty() const { return DeclsInScope.empty(); }
+
+ void AddDecl(Decl *D) {
+ if (auto *VD = dyn_cast<VarDecl>(D))
+ if (!isa<ParmVarDecl>(VD))
+ ReturnSlots.insert(VD);
+
+ DeclsInScope.insert(D);
+ }
+
+ void RemoveDecl(Decl *D) { DeclsInScope.erase(D); }
+
+ void incrementMSManglingNumber() {
+ if (Scope *MSLMP = getMSLastManglingParent()) {
+ MSLMP->MSLastManglingNumber += 1;
+ MSCurManglingNumber += 1;
+ }
+ }
+
+ void decrementMSManglingNumber() {
+ if (Scope *MSLMP = getMSLastManglingParent()) {
+ MSLMP->MSLastManglingNumber -= 1;
+ MSCurManglingNumber -= 1;
+ }
+ }
+
+ unsigned getMSLastManglingNumber() const {
+ if (const Scope *MSLMP = getMSLastManglingParent())
+ return MSLMP->MSLastManglingNumber;
+ return 1;
+ }
+
+ unsigned getMSCurManglingNumber() const {
+ return MSCurManglingNumber;
+ }
+
+ /// isDeclScope - Return true if this is the scope that the specified decl is
+ /// declared in.
+ bool isDeclScope(const Decl *D) const { return DeclsInScope.contains(D); }
+
+ /// Get the entity corresponding to this scope.
+ DeclContext *getEntity() const {
+ return isTemplateParamScope() ? nullptr : Entity;
+ }
+
+ /// Get the DeclContext in which to continue unqualified lookup after a
+ /// lookup in this scope.
+ DeclContext *getLookupEntity() const { return Entity; }
+
+ void setEntity(DeclContext *E) {
+ assert(!isTemplateParamScope() &&
+ "entity associated with template param scope");
+ Entity = E;
+ }
+ void setLookupEntity(DeclContext *E) { Entity = E; }
+
+ /// Determine whether any unrecoverable errors have occurred within this
+ /// scope. Note that this may return false even if the scope contains invalid
+ /// declarations or statements, if the errors for those invalid constructs
+ /// were suppressed because some prior invalid construct was referenced.
+ bool hasUnrecoverableErrorOccurred() const {
+ return ErrorTrap.hasUnrecoverableErrorOccurred();
+ }
+
+ /// isFunctionScope() - Return true if this scope is a function scope.
+ bool isFunctionScope() const { return getFlags() & Scope::FnScope; }
+
+ /// isClassScope - Return true if this scope is a class/struct/union scope.
+ bool isClassScope() const { return getFlags() & Scope::ClassScope; }
+
+ /// Determines whether this scope is between inheritance colon and the real
+ /// class/struct definition.
+ bool isClassInheritanceScope() const {
+ return getFlags() & Scope::ClassInheritanceScope;
+ }
+
+ /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline
+ /// method scope or is inside one.
+ bool isInCXXInlineMethodScope() const {
+ if (const Scope *FnS = getFnParent()) {
+ assert(FnS->getParent() && "TUScope not created?");
+ return FnS->getParent()->isClassScope();
+ }
+ return false;
+ }
+
+ /// isInObjcMethodScope - Return true if this scope is, or is contained in, an
+ /// Objective-C method body. Note that this method is not constant time.
+ bool isInObjcMethodScope() const {
+ for (const Scope *S = this; S; S = S->getParent()) {
+ // If this scope is an objc method scope, then we succeed.
+ if (S->getFlags() & ObjCMethodScope)
+ return true;
+ }
+ return false;
+ }
+
+ /// isInObjcMethodOuterScope - Return true if this scope is an
+ /// Objective-C method outer most body.
+ bool isInObjcMethodOuterScope() const {
+ if (const Scope *S = this) {
+ // If this scope is an objc method scope, then we succeed.
+ if (S->getFlags() & ObjCMethodScope)
+ return true;
+ }
+ return false;
+ }
+
+ /// isTemplateParamScope - Return true if this scope is a C++
+ /// template parameter scope.
+ bool isTemplateParamScope() const {
+ return getFlags() & Scope::TemplateParamScope;
+ }
+
+ /// isFunctionPrototypeScope - Return true if this scope is a
+ /// function prototype scope.
+ bool isFunctionPrototypeScope() const {
+ return getFlags() & Scope::FunctionPrototypeScope;
+ }
+
+ /// isFunctionDeclarationScope - Return true if this scope is a
+ /// function prototype scope.
+ bool isFunctionDeclarationScope() const {
+ return getFlags() & Scope::FunctionDeclarationScope;
+ }
+
+ /// isAtCatchScope - Return true if this scope is \@catch.
+ bool isAtCatchScope() const {
+ return getFlags() & Scope::AtCatchScope;
+ }
+
+ /// isCatchScope - Return true if this scope is a C++ catch statement.
+ bool isCatchScope() const { return getFlags() & Scope::CatchScope; }
+
+ /// isSwitchScope - Return true if this scope is a switch scope.
+ bool isSwitchScope() const {
+ for (const Scope *S = this; S; S = S->getParent()) {
+ if (S->getFlags() & Scope::SwitchScope)
+ return true;
+ else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope |
+ Scope::BlockScope | Scope::TemplateParamScope |
+ Scope::FunctionPrototypeScope |
+ Scope::AtCatchScope | Scope::ObjCMethodScope))
+ return false;
+ }
+ return false;
+ }
+
+ /// Determines whether this scope is the OpenMP directive scope
+ bool isOpenMPDirectiveScope() const {
+ return (getFlags() & Scope::OpenMPDirectiveScope);
+ }
+
+ /// Determine whether this scope is some OpenMP loop directive scope
+ /// (for example, 'omp for', 'omp simd').
+ bool isOpenMPLoopDirectiveScope() const {
+ if (getFlags() & Scope::OpenMPLoopDirectiveScope) {
+ assert(isOpenMPDirectiveScope() &&
+ "OpenMP loop directive scope is not a directive scope");
+ return true;
+ }
+ return false;
+ }
+
+ /// Determine whether this scope is (or is nested into) some OpenMP
+ /// loop simd directive scope (for example, 'omp simd', 'omp for simd').
+ bool isOpenMPSimdDirectiveScope() const {
+ return getFlags() & Scope::OpenMPSimdDirectiveScope;
+ }
+
+ /// Determine whether this scope is a loop having OpenMP loop
+ /// directive attached.
+ bool isOpenMPLoopScope() const {
+ const Scope *P = getParent();
+ return P && P->isOpenMPLoopDirectiveScope();
+ }
+
+ /// Determine whether this scope is some OpenMP directive with
+ /// order clause which specifies concurrent scope.
+ bool isOpenMPOrderClauseScope() const {
+ return getFlags() & Scope::OpenMPOrderClauseScope;
+ }
+
+ /// Determine whether this scope is a while/do/for statement, which can have
+ /// continue statements embedded into it.
+ bool isContinueScope() const {
+ return getFlags() & ScopeFlags::ContinueScope;
+ }
+
+ /// Determine whether this scope is a C++ 'try' block.
+ bool isTryScope() const { return getFlags() & Scope::TryScope; }
+
+ /// Determine whether this scope is a function-level C++ try or catch scope.
+ bool isFnTryCatchScope() const {
+ return getFlags() & ScopeFlags::FnTryCatchScope;
+ }
+
+ /// Determine whether this scope is a SEH '__try' block.
+ bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; }
+
+ /// Determine whether this scope is a SEH '__except' block.
+ bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; }
+
+ /// Determine whether this scope is a compound statement scope.
+ bool isCompoundStmtScope() const {
+ return getFlags() & Scope::CompoundStmtScope;
+ }
+
+ /// Determine whether this scope is a controlling scope in a
+ /// if/switch/while/for statement.
+ bool isControlScope() const { return getFlags() & Scope::ControlScope; }
+
+ /// Returns if rhs has a higher scope depth than this.
+ ///
+ /// The caller is responsible for calling this only if one of the two scopes
+ /// is an ancestor of the other.
+ bool Contains(const Scope& rhs) const { return Depth < rhs.Depth; }
+
+ /// containedInPrototypeScope - Return true if this or a parent scope
+ /// is a FunctionPrototypeScope.
+ bool containedInPrototypeScope() const;
+
+ void PushUsingDirective(UsingDirectiveDecl *UDir) {
+ UsingDirectives.push_back(UDir);
+ }
+
+ using using_directives_range =
+ llvm::iterator_range<UsingDirectivesTy::iterator>;
+
+ using_directives_range using_directives() {
+ return using_directives_range(UsingDirectives.begin(),
+ UsingDirectives.end());
+ }
+
+ void updateNRVOCandidate(VarDecl *VD);
+
+ void applyNRVO();
+
+ /// Init - This is used by the parser to implement scope caching.
+ void Init(Scope *parent, unsigned flags);
+
+ /// Sets up the specified scope flags and adjusts the scope state
+ /// variables accordingly.
+ void AddFlags(unsigned Flags);
+
+ void dumpImpl(raw_ostream &OS) const;
+ void dump() const;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SCOPE_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/ScopeInfo.h b/contrib/libs/clang16/include/clang/Sema/ScopeInfo.h
new file mode 100644
index 0000000000..8122f93acb
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/ScopeInfo.h
@@ -0,0 +1,1078 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- ScopeInfo.h - Information about a semantic context -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines FunctionScopeInfo and its subclasses, which contain
+// information about a single function, block, lambda, or method body.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SCOPEINFO_H
+#define LLVM_CLANG_SEMA_SCOPEINFO_H
+
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/CapturedStmt.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/CleanupInfo.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <cassert>
+#include <utility>
+
+namespace clang {
+
+class BlockDecl;
+class CapturedDecl;
+class CXXMethodDecl;
+class CXXRecordDecl;
+class ImplicitParamDecl;
+class NamedDecl;
+class ObjCIvarRefExpr;
+class ObjCMessageExpr;
+class ObjCPropertyDecl;
+class ObjCPropertyRefExpr;
+class ParmVarDecl;
+class RecordDecl;
+class ReturnStmt;
+class Scope;
+class Stmt;
+class SwitchStmt;
+class TemplateParameterList;
+class VarDecl;
+
+namespace sema {
+
+/// Contains information about the compound statement currently being
+/// parsed.
+class CompoundScopeInfo {
+public:
+ /// Whether this compound stamement contains `for' or `while' loops
+ /// with empty bodies.
+ bool HasEmptyLoopBodies = false;
+
+ /// Whether this compound statement corresponds to a GNU statement
+ /// expression.
+ bool IsStmtExpr;
+
+ /// FP options at the beginning of the compound statement, prior to
+ /// any pragma.
+ FPOptions InitialFPFeatures;
+
+ CompoundScopeInfo(bool IsStmtExpr, FPOptions FPO)
+ : IsStmtExpr(IsStmtExpr), InitialFPFeatures(FPO) {}
+
+ void setHasEmptyLoopBodies() {
+ HasEmptyLoopBodies = true;
+ }
+};
+
+class PossiblyUnreachableDiag {
+public:
+ PartialDiagnostic PD;
+ SourceLocation Loc;
+ llvm::TinyPtrVector<const Stmt*> Stmts;
+
+ PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
+ ArrayRef<const Stmt *> Stmts)
+ : PD(PD), Loc(Loc), Stmts(Stmts) {}
+};
+
+/// Retains information about a function, method, or block that is
+/// currently being parsed.
+class FunctionScopeInfo {
+protected:
+ enum ScopeKind {
+ SK_Function,
+ SK_Block,
+ SK_Lambda,
+ SK_CapturedRegion
+ };
+
+public:
+ /// What kind of scope we are describing.
+ ScopeKind Kind : 3;
+
+ /// Whether this function contains a VLA, \@try, try, C++
+ /// initializer, or anything else that can't be jumped past.
+ bool HasBranchProtectedScope : 1;
+
+ /// Whether this function contains any switches or direct gotos.
+ bool HasBranchIntoScope : 1;
+
+ /// Whether this function contains any indirect gotos.
+ bool HasIndirectGoto : 1;
+
+ /// Whether this function contains any statement marked with
+ /// \c [[clang::musttail]].
+ bool HasMustTail : 1;
+
+ /// Whether a statement was dropped because it was invalid.
+ bool HasDroppedStmt : 1;
+
+ /// True if current scope is for OpenMP declare reduction combiner.
+ bool HasOMPDeclareReductionCombiner : 1;
+
+ /// Whether there is a fallthrough statement in this function.
+ bool HasFallthroughStmt : 1;
+
+ /// Whether this function uses constrained floating point intrinsics
+ bool UsesFPIntrin : 1;
+
+ /// Whether we make reference to a declaration that could be
+ /// unavailable.
+ bool HasPotentialAvailabilityViolations : 1;
+
+ /// A flag that is set when parsing a method that must call super's
+ /// implementation, such as \c -dealloc, \c -finalize, or any method marked
+ /// with \c __attribute__((objc_requires_super)).
+ bool ObjCShouldCallSuper : 1;
+
+ /// True when this is a method marked as a designated initializer.
+ bool ObjCIsDesignatedInit : 1;
+
+ /// This starts true for a method marked as designated initializer and will
+ /// be set to false if there is an invocation to a designated initializer of
+ /// the super class.
+ bool ObjCWarnForNoDesignatedInitChain : 1;
+
+ /// True when this is an initializer method not marked as a designated
+ /// initializer within a class that has at least one initializer marked as a
+ /// designated initializer.
+ bool ObjCIsSecondaryInit : 1;
+
+ /// This starts true for a secondary initializer method and will be set to
+ /// false if there is an invocation of an initializer on 'self'.
+ bool ObjCWarnForNoInitDelegation : 1;
+
+ /// True only when this function has not already built, or attempted
+ /// to build, the initial and final coroutine suspend points
+ bool NeedsCoroutineSuspends : 1;
+
+ /// An enumeration represeting the kind of the first coroutine statement
+ /// in the function. One of co_return, co_await, or co_yield.
+ unsigned char FirstCoroutineStmtKind : 2;
+
+ /// First coroutine statement in the current function.
+ /// (ex co_return, co_await, co_yield)
+ SourceLocation FirstCoroutineStmtLoc;
+
+ /// First 'return' statement in the current function.
+ SourceLocation FirstReturnLoc;
+
+ /// First C++ 'try' or ObjC @try statement in the current function.
+ SourceLocation FirstCXXOrObjCTryLoc;
+ enum { TryLocIsCXX, TryLocIsObjC, Unknown } FirstTryType = Unknown;
+
+ /// First SEH '__try' statement in the current function.
+ SourceLocation FirstSEHTryLoc;
+
+private:
+ /// Used to determine if errors occurred in this function or block.
+ DiagnosticErrorTrap ErrorTrap;
+
+public:
+ /// A SwitchStmt, along with a flag indicating if its list of case statements
+ /// is incomplete (because we dropped an invalid one while parsing).
+ using SwitchInfo = llvm::PointerIntPair<SwitchStmt*, 1, bool>;
+
+ /// SwitchStack - This is the current set of active switch statements in the
+ /// block.
+ SmallVector<SwitchInfo, 8> SwitchStack;
+
+ /// The list of return statements that occur within the function or
+ /// block, if there is any chance of applying the named return value
+ /// optimization, or if we need to infer a return type.
+ SmallVector<ReturnStmt*, 4> Returns;
+
+ /// The promise object for this coroutine, if any.
+ VarDecl *CoroutinePromise = nullptr;
+
+ /// A mapping between the coroutine function parameters that were moved
+ /// to the coroutine frame, and their move statements.
+ llvm::SmallMapVector<ParmVarDecl *, Stmt *, 4> CoroutineParameterMoves;
+
+ /// The initial and final coroutine suspend points.
+ std::pair<Stmt *, Stmt *> CoroutineSuspends;
+
+ /// The stack of currently active compound stamement scopes in the
+ /// function.
+ SmallVector<CompoundScopeInfo, 4> CompoundScopes;
+
+ /// The set of blocks that are introduced in this function.
+ llvm::SmallPtrSet<const BlockDecl *, 1> Blocks;
+
+ /// The set of __block variables that are introduced in this function.
+ llvm::TinyPtrVector<VarDecl *> ByrefBlockVars;
+
+ /// A list of PartialDiagnostics created but delayed within the
+ /// current function scope. These diagnostics are vetted for reachability
+ /// prior to being emitted.
+ SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
+
+ /// A list of parameters which have the nonnull attribute and are
+ /// modified in the function.
+ llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams;
+
+ /// The set of GNU address of label extension "&&label".
+ llvm::SmallVector<AddrLabelExpr *, 4> AddrLabels;
+
+public:
+ /// Represents a simple identification of a weak object.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ ///
+ /// This is used to determine if two weak accesses refer to the same object.
+ /// Here are some examples of how various accesses are "profiled":
+ ///
+ /// Access Expression | "Base" Decl | "Property" Decl
+ /// :---------------: | :-----------------: | :------------------------------:
+ /// self.property | self (VarDecl) | property (ObjCPropertyDecl)
+ /// self.implicitProp | self (VarDecl) | -implicitProp (ObjCMethodDecl)
+ /// self->ivar.prop | ivar (ObjCIvarDecl) | prop (ObjCPropertyDecl)
+ /// cxxObj.obj.prop | obj (FieldDecl) | prop (ObjCPropertyDecl)
+ /// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl)
+ /// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl)
+ /// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl)
+ /// MyClass.foo.prop | +foo (ObjCMethodDecl) | -prop (ObjCPropertyDecl)
+ /// weakVar | 0 (known) | weakVar (VarDecl)
+ /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl)
+ ///
+ /// Objects are identified with only two Decls to make it reasonably fast to
+ /// compare them.
+ class WeakObjectProfileTy {
+ /// The base object decl, as described in the class documentation.
+ ///
+ /// The extra flag is "true" if the Base and Property are enough to uniquely
+ /// identify the object in memory.
+ ///
+ /// \sa isExactProfile()
+ using BaseInfoTy = llvm::PointerIntPair<const NamedDecl *, 1, bool>;
+ BaseInfoTy Base;
+
+ /// The "property" decl, as described in the class documentation.
+ ///
+ /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the
+ /// case of "implicit" properties (regular methods accessed via dot syntax).
+ const NamedDecl *Property = nullptr;
+
+ /// Used to find the proper base profile for a given base expression.
+ static BaseInfoTy getBaseInfo(const Expr *BaseE);
+
+ inline WeakObjectProfileTy();
+ static inline WeakObjectProfileTy getSentinel();
+
+ public:
+ WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
+ WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
+ WeakObjectProfileTy(const DeclRefExpr *RE);
+ WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
+
+ const NamedDecl *getBase() const { return Base.getPointer(); }
+ const NamedDecl *getProperty() const { return Property; }
+
+ /// Returns true if the object base specifies a known object in memory,
+ /// rather than, say, an instance variable or property of another object.
+ ///
+ /// Note that this ignores the effects of aliasing; that is, \c foo.bar is
+ /// considered an exact profile if \c foo is a local variable, even if
+ /// another variable \c foo2 refers to the same object as \c foo.
+ ///
+ /// For increased precision, accesses with base variables that are
+ /// properties or ivars of 'self' (e.g. self.prop1.prop2) are considered to
+ /// be exact, though this is not true for arbitrary variables
+ /// (foo.prop1.prop2).
+ bool isExactProfile() const {
+ return Base.getInt();
+ }
+
+ bool operator==(const WeakObjectProfileTy &Other) const {
+ return Base == Other.Base && Property == Other.Property;
+ }
+
+ // For use in DenseMap.
+ // We can't specialize the usual llvm::DenseMapInfo at the end of the file
+ // because by that point the DenseMap in FunctionScopeInfo has already been
+ // instantiated.
+ class DenseMapInfo {
+ public:
+ static inline WeakObjectProfileTy getEmptyKey() {
+ return WeakObjectProfileTy();
+ }
+
+ static inline WeakObjectProfileTy getTombstoneKey() {
+ return WeakObjectProfileTy::getSentinel();
+ }
+
+ static unsigned getHashValue(const WeakObjectProfileTy &Val) {
+ using Pair = std::pair<BaseInfoTy, const NamedDecl *>;
+
+ return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base,
+ Val.Property));
+ }
+
+ static bool isEqual(const WeakObjectProfileTy &LHS,
+ const WeakObjectProfileTy &RHS) {
+ return LHS == RHS;
+ }
+ };
+ };
+
+ /// Represents a single use of a weak object.
+ ///
+ /// Stores both the expression and whether the access is potentially unsafe
+ /// (i.e. it could potentially be warned about).
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ class WeakUseTy {
+ llvm::PointerIntPair<const Expr *, 1, bool> Rep;
+
+ public:
+ WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {}
+
+ const Expr *getUseExpr() const { return Rep.getPointer(); }
+ bool isUnsafe() const { return Rep.getInt(); }
+ void markSafe() { Rep.setInt(false); }
+
+ bool operator==(const WeakUseTy &Other) const {
+ return Rep == Other.Rep;
+ }
+ };
+
+ /// Used to collect uses of a particular weak object in a function body.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ using WeakUseVector = SmallVector<WeakUseTy, 4>;
+
+ /// Used to collect all uses of weak objects in a function body.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ using WeakObjectUseMap =
+ llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8,
+ WeakObjectProfileTy::DenseMapInfo>;
+
+private:
+ /// Used to collect all uses of weak objects in this function body.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ WeakObjectUseMap WeakObjectUses;
+
+protected:
+ FunctionScopeInfo(const FunctionScopeInfo&) = default;
+
+public:
+ FunctionScopeInfo(DiagnosticsEngine &Diag)
+ : Kind(SK_Function), HasBranchProtectedScope(false),
+ HasBranchIntoScope(false), HasIndirectGoto(false), HasMustTail(false),
+ HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false),
+ HasFallthroughStmt(false), UsesFPIntrin(false),
+ HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false),
+ ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false),
+ ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false),
+ NeedsCoroutineSuspends(true), ErrorTrap(Diag) {}
+
+ virtual ~FunctionScopeInfo();
+
+ /// Determine whether an unrecoverable error has occurred within this
+ /// function. Note that this may return false even if the function body is
+ /// invalid, because the errors may be suppressed if they're caused by prior
+ /// invalid declarations.
+ ///
+ /// FIXME: Migrate the caller of this to use containsErrors() instead once
+ /// it's ready.
+ bool hasUnrecoverableErrorOccurred() const {
+ return ErrorTrap.hasUnrecoverableErrorOccurred();
+ }
+
+ /// Record that a weak object was accessed.
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ template <typename ExprT>
+ inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
+
+ void recordUseOfWeak(const ObjCMessageExpr *Msg,
+ const ObjCPropertyDecl *Prop);
+
+ /// Record that a given expression is a "safe" access of a weak object (e.g.
+ /// assigning it to a strong variable.)
+ ///
+ /// Part of the implementation of -Wrepeated-use-of-weak.
+ void markSafeWeakUse(const Expr *E);
+
+ const WeakObjectUseMap &getWeakObjectUses() const {
+ return WeakObjectUses;
+ }
+
+ void setHasBranchIntoScope() {
+ HasBranchIntoScope = true;
+ }
+
+ void setHasBranchProtectedScope() {
+ HasBranchProtectedScope = true;
+ }
+
+ void setHasIndirectGoto() {
+ HasIndirectGoto = true;
+ }
+
+ void setHasMustTail() { HasMustTail = true; }
+
+ void setHasDroppedStmt() {
+ HasDroppedStmt = true;
+ }
+
+ void setHasOMPDeclareReductionCombiner() {
+ HasOMPDeclareReductionCombiner = true;
+ }
+
+ void setHasFallthroughStmt() {
+ HasFallthroughStmt = true;
+ }
+
+ void setUsesFPIntrin() {
+ UsesFPIntrin = true;
+ }
+
+ void setHasCXXTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstCXXOrObjCTryLoc = TryLoc;
+ FirstTryType = TryLocIsCXX;
+ }
+
+ void setHasObjCTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstCXXOrObjCTryLoc = TryLoc;
+ FirstTryType = TryLocIsObjC;
+ }
+
+ void setHasSEHTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstSEHTryLoc = TryLoc;
+ }
+
+ bool NeedsScopeChecking() const {
+ return !HasDroppedStmt && (HasIndirectGoto || HasMustTail ||
+ (HasBranchProtectedScope && HasBranchIntoScope));
+ }
+
+ // Add a block introduced in this function.
+ void addBlock(const BlockDecl *BD) {
+ Blocks.insert(BD);
+ }
+
+ // Add a __block variable introduced in this function.
+ void addByrefBlockVar(VarDecl *VD) {
+ ByrefBlockVars.push_back(VD);
+ }
+
+ bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); }
+
+ void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) {
+ assert(FirstCoroutineStmtLoc.isInvalid() &&
+ "first coroutine statement location already set");
+ FirstCoroutineStmtLoc = Loc;
+ FirstCoroutineStmtKind = llvm::StringSwitch<unsigned char>(Keyword)
+ .Case("co_return", 0)
+ .Case("co_await", 1)
+ .Case("co_yield", 2);
+ }
+
+ StringRef getFirstCoroutineStmtKeyword() const {
+ assert(FirstCoroutineStmtLoc.isValid()
+ && "no coroutine statement available");
+ switch (FirstCoroutineStmtKind) {
+ case 0: return "co_return";
+ case 1: return "co_await";
+ case 2: return "co_yield";
+ default:
+ llvm_unreachable("FirstCoroutineStmtKind has an invalid value");
+ };
+ }
+
+ void setNeedsCoroutineSuspends(bool value = true) {
+ assert((!value || CoroutineSuspends.first == nullptr) &&
+ "we already have valid suspend points");
+ NeedsCoroutineSuspends = value;
+ }
+
+ bool hasInvalidCoroutineSuspends() const {
+ return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr;
+ }
+
+ void setCoroutineSuspends(Stmt *Initial, Stmt *Final) {
+ assert(Initial && Final && "suspend points cannot be null");
+ assert(CoroutineSuspends.first == nullptr && "suspend points already set");
+ NeedsCoroutineSuspends = false;
+ CoroutineSuspends.first = Initial;
+ CoroutineSuspends.second = Final;
+ }
+
+ /// Clear out the information in this function scope, making it
+ /// suitable for reuse.
+ void Clear();
+
+ bool isPlainFunction() const { return Kind == SK_Function; }
+};
+
+class Capture {
+ // There are three categories of capture: capturing 'this', capturing
+ // local variables, and C++1y initialized captures (which can have an
+ // arbitrary initializer, and don't really capture in the traditional
+ // sense at all).
+ //
+ // There are three ways to capture a local variable:
+ // - capture by copy in the C++11 sense,
+ // - capture by reference in the C++11 sense, and
+ // - __block capture.
+ // Lambdas explicitly specify capture by copy or capture by reference.
+ // For blocks, __block capture applies to variables with that annotation,
+ // variables of reference type are captured by reference, and other
+ // variables are captured by copy.
+ enum CaptureKind {
+ Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
+ };
+
+ union {
+ /// If Kind == Cap_VLA, the captured type.
+ const VariableArrayType *CapturedVLA;
+
+ /// Otherwise, the captured variable (if any).
+ ValueDecl *CapturedVar;
+ };
+
+ /// The source location at which the first capture occurred.
+ SourceLocation Loc;
+
+ /// The location of the ellipsis that expands a parameter pack.
+ SourceLocation EllipsisLoc;
+
+ /// The type as it was captured, which is the type of the non-static data
+ /// member that would hold the capture.
+ QualType CaptureType;
+
+ /// The CaptureKind of this capture.
+ unsigned Kind : 2;
+
+ /// Whether this is a nested capture (a capture of an enclosing capturing
+ /// scope's capture).
+ unsigned Nested : 1;
+
+ /// Whether this is a capture of '*this'.
+ unsigned CapturesThis : 1;
+
+ /// Whether an explicit capture has been odr-used in the body of the
+ /// lambda.
+ unsigned ODRUsed : 1;
+
+ /// Whether an explicit capture has been non-odr-used in the body of
+ /// the lambda.
+ unsigned NonODRUsed : 1;
+
+ /// Whether the capture is invalid (a capture was required but the entity is
+ /// non-capturable).
+ unsigned Invalid : 1;
+
+public:
+ Capture(ValueDecl *Var, bool Block, bool ByRef, bool IsNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType,
+ bool Invalid)
+ : CapturedVar(Var), Loc(Loc), EllipsisLoc(EllipsisLoc),
+ CaptureType(CaptureType), Kind(Block ? Cap_Block
+ : ByRef ? Cap_ByRef
+ : Cap_ByCopy),
+ Nested(IsNested), CapturesThis(false), ODRUsed(false),
+ NonODRUsed(false), Invalid(Invalid) {}
+
+ enum IsThisCapture { ThisCapture };
+ Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
+ QualType CaptureType, const bool ByCopy, bool Invalid)
+ : Loc(Loc), CaptureType(CaptureType),
+ Kind(ByCopy ? Cap_ByCopy : Cap_ByRef), Nested(IsNested),
+ CapturesThis(true), ODRUsed(false), NonODRUsed(false),
+ Invalid(Invalid) {}
+
+ enum IsVLACapture { VLACapture };
+ Capture(IsVLACapture, const VariableArrayType *VLA, bool IsNested,
+ SourceLocation Loc, QualType CaptureType)
+ : CapturedVLA(VLA), Loc(Loc), CaptureType(CaptureType), Kind(Cap_VLA),
+ Nested(IsNested), CapturesThis(false), ODRUsed(false),
+ NonODRUsed(false), Invalid(false) {}
+
+ bool isThisCapture() const { return CapturesThis; }
+ bool isVariableCapture() const {
+ return !isThisCapture() && !isVLATypeCapture();
+ }
+
+ bool isCopyCapture() const { return Kind == Cap_ByCopy; }
+ bool isReferenceCapture() const { return Kind == Cap_ByRef; }
+ bool isBlockCapture() const { return Kind == Cap_Block; }
+ bool isVLATypeCapture() const { return Kind == Cap_VLA; }
+
+ bool isNested() const { return Nested; }
+
+ bool isInvalid() const { return Invalid; }
+
+ /// Determine whether this capture is an init-capture.
+ bool isInitCapture() const;
+
+ bool isODRUsed() const { return ODRUsed; }
+ bool isNonODRUsed() const { return NonODRUsed; }
+ void markUsed(bool IsODRUse) {
+ if (IsODRUse)
+ ODRUsed = true;
+ else
+ NonODRUsed = true;
+ }
+
+ ValueDecl *getVariable() const {
+ assert(isVariableCapture());
+ return CapturedVar;
+ }
+
+ const VariableArrayType *getCapturedVLAType() const {
+ assert(isVLATypeCapture());
+ return CapturedVLA;
+ }
+
+ /// Retrieve the location at which this variable was captured.
+ SourceLocation getLocation() const { return Loc; }
+
+ /// Retrieve the source location of the ellipsis, whose presence
+ /// indicates that the capture is a pack expansion.
+ SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+
+ /// Retrieve the capture type for this capture, which is effectively
+ /// the type of the non-static data member in the lambda/block structure
+ /// that would store this capture.
+ QualType getCaptureType() const { return CaptureType; }
+};
+
+class CapturingScopeInfo : public FunctionScopeInfo {
+protected:
+ CapturingScopeInfo(const CapturingScopeInfo&) = default;
+
+public:
+ enum ImplicitCaptureStyle {
+ ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
+ ImpCap_CapturedRegion
+ };
+
+ ImplicitCaptureStyle ImpCaptureStyle;
+
+ CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
+ : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {}
+
+ /// CaptureMap - A map of captured variables to (index+1) into Captures.
+ llvm::DenseMap<ValueDecl *, unsigned> CaptureMap;
+
+ /// CXXThisCaptureIndex - The (index+1) of the capture of 'this';
+ /// zero if 'this' is not captured.
+ unsigned CXXThisCaptureIndex = 0;
+
+ /// Captures - The captures.
+ SmallVector<Capture, 4> Captures;
+
+ /// - Whether the target type of return statements in this context
+ /// is deduced (e.g. a lambda or block with omitted return type).
+ bool HasImplicitReturnType = false;
+
+ /// ReturnType - The target type of return statements in this context,
+ /// or null if unknown.
+ QualType ReturnType;
+
+ void addCapture(ValueDecl *Var, bool isBlock, bool isByref, bool isNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
+ QualType CaptureType, bool Invalid) {
+ Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
+ EllipsisLoc, CaptureType, Invalid));
+ CaptureMap[Var] = Captures.size();
+ }
+
+ void addVLATypeCapture(SourceLocation Loc, const VariableArrayType *VLAType,
+ QualType CaptureType) {
+ Captures.push_back(Capture(Capture::VLACapture, VLAType,
+ /*FIXME: IsNested*/ false, Loc, CaptureType));
+ }
+
+ void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
+ bool ByCopy);
+
+ /// Determine whether the C++ 'this' is captured.
+ bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
+
+ /// Retrieve the capture of C++ 'this', if it has been captured.
+ Capture &getCXXThisCapture() {
+ assert(isCXXThisCaptured() && "this has not been captured");
+ return Captures[CXXThisCaptureIndex - 1];
+ }
+
+ /// Determine whether the given variable has been captured.
+ bool isCaptured(ValueDecl *Var) const { return CaptureMap.count(Var); }
+
+ /// Determine whether the given variable-array type has been captured.
+ bool isVLATypeCaptured(const VariableArrayType *VAT) const;
+
+ /// Retrieve the capture of the given variable, if it has been
+ /// captured already.
+ Capture &getCapture(ValueDecl *Var) {
+ assert(isCaptured(Var) && "Variable has not been captured");
+ return Captures[CaptureMap[Var] - 1];
+ }
+
+ const Capture &getCapture(ValueDecl *Var) const {
+ llvm::DenseMap<ValueDecl *, unsigned>::const_iterator Known =
+ CaptureMap.find(Var);
+ assert(Known != CaptureMap.end() && "Variable has not been captured");
+ return Captures[Known->second - 1];
+ }
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda
+ || FSI->Kind == SK_CapturedRegion;
+ }
+};
+
+/// Retains information about a block that is currently being parsed.
+class BlockScopeInfo final : public CapturingScopeInfo {
+public:
+ BlockDecl *TheDecl;
+
+ /// TheScope - This is the scope for the block itself, which contains
+ /// arguments etc.
+ Scope *TheScope;
+
+ /// BlockType - The function type of the block, if one was given.
+ /// Its return type may be BuiltinType::Dependent.
+ QualType FunctionType;
+
+ BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
+ : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
+ TheScope(BlockScope) {
+ Kind = SK_Block;
+ }
+
+ ~BlockScopeInfo() override;
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_Block;
+ }
+};
+
+/// Retains information about a captured region.
+class CapturedRegionScopeInfo final : public CapturingScopeInfo {
+public:
+ /// The CapturedDecl for this statement.
+ CapturedDecl *TheCapturedDecl;
+
+ /// The captured record type.
+ RecordDecl *TheRecordDecl;
+
+ /// This is the enclosing scope of the captured region.
+ Scope *TheScope;
+
+ /// The implicit parameter for the captured variables.
+ ImplicitParamDecl *ContextParam;
+
+ /// The kind of captured region.
+ unsigned short CapRegionKind;
+
+ unsigned short OpenMPLevel;
+ unsigned short OpenMPCaptureLevel;
+
+ CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
+ RecordDecl *RD, ImplicitParamDecl *Context,
+ CapturedRegionKind K, unsigned OpenMPLevel,
+ unsigned OpenMPCaptureLevel)
+ : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
+ TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
+ ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel),
+ OpenMPCaptureLevel(OpenMPCaptureLevel) {
+ Kind = SK_CapturedRegion;
+ }
+
+ ~CapturedRegionScopeInfo() override;
+
+ /// A descriptive name for the kind of captured region this is.
+ StringRef getRegionName() const {
+ switch (CapRegionKind) {
+ case CR_Default:
+ return "default captured statement";
+ case CR_ObjCAtFinally:
+ return "Objective-C @finally statement";
+ case CR_OpenMP:
+ return "OpenMP region";
+ }
+ llvm_unreachable("Invalid captured region kind!");
+ }
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_CapturedRegion;
+ }
+};
+
+class LambdaScopeInfo final :
+ public CapturingScopeInfo, public InventedTemplateParameterInfo {
+public:
+ /// The class that describes the lambda.
+ CXXRecordDecl *Lambda = nullptr;
+
+ /// The lambda's compiler-generated \c operator().
+ CXXMethodDecl *CallOperator = nullptr;
+
+ /// Source range covering the lambda introducer [...].
+ SourceRange IntroducerRange;
+
+ /// Source location of the '&' or '=' specifying the default capture
+ /// type, if any.
+ SourceLocation CaptureDefaultLoc;
+
+ /// The number of captures in the \c Captures list that are
+ /// explicit captures.
+ unsigned NumExplicitCaptures = 0;
+
+ /// Whether this is a mutable lambda.
+ bool Mutable = false;
+
+ /// Whether the (empty) parameter list is explicit.
+ bool ExplicitParams = false;
+
+ /// Whether any of the capture expressions requires cleanups.
+ CleanupInfo Cleanup;
+
+ /// Whether the lambda contains an unexpanded parameter pack.
+ bool ContainsUnexpandedParameterPack = false;
+
+ /// Packs introduced by this lambda, if any.
+ SmallVector<NamedDecl*, 4> LocalPacks;
+
+ /// Source range covering the explicit template parameter list (if it exists).
+ SourceRange ExplicitTemplateParamsRange;
+
+ /// The requires-clause immediately following the explicit template parameter
+ /// list, if any. (Note that there may be another requires-clause included as
+ /// part of the lambda-declarator.)
+ ExprResult RequiresClause;
+
+ /// If this is a generic lambda, and the template parameter
+ /// list has been created (from the TemplateParams) then store
+ /// a reference to it (cache it to avoid reconstructing it).
+ TemplateParameterList *GLTemplateParameterList = nullptr;
+
+ /// Contains all variable-referring-expressions (i.e. DeclRefExprs
+ /// or MemberExprs) that refer to local variables in a generic lambda
+ /// or a lambda in a potentially-evaluated-if-used context.
+ ///
+ /// Potentially capturable variables of a nested lambda that might need
+ /// to be captured by the lambda are housed here.
+ /// This is specifically useful for generic lambdas or
+ /// lambdas within a potentially evaluated-if-used context.
+ /// If an enclosing variable is named in an expression of a lambda nested
+ /// within a generic lambda, we don't always know whether the variable
+ /// will truly be odr-used (i.e. need to be captured) by that nested lambda,
+ /// until its instantiation. But we still need to capture it in the
+ /// enclosing lambda if all intervening lambdas can capture the variable.
+ llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;
+
+ /// Contains all variable-referring-expressions that refer
+ /// to local variables that are usable as constant expressions and
+ /// do not involve an odr-use (they may still need to be captured
+ /// if the enclosing full-expression is instantiation dependent).
+ llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs;
+
+ /// A map of explicit capture indices to their introducer source ranges.
+ llvm::DenseMap<unsigned, SourceRange> ExplicitCaptureRanges;
+
+ /// Contains all of the variables defined in this lambda that shadow variables
+ /// that were defined in parent contexts. Used to avoid warnings when the
+ /// shadowed variables are uncaptured by this lambda.
+ struct ShadowedOuterDecl {
+ const VarDecl *VD;
+ const VarDecl *ShadowedDecl;
+ };
+ llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls;
+
+ SourceLocation PotentialThisCaptureLocation;
+
+ LambdaScopeInfo(DiagnosticsEngine &Diag)
+ : CapturingScopeInfo(Diag, ImpCap_None) {
+ Kind = SK_Lambda;
+ }
+
+ /// Note when all explicit captures have been added.
+ void finishedExplicitCaptures() {
+ NumExplicitCaptures = Captures.size();
+ }
+
+ static bool classof(const FunctionScopeInfo *FSI) {
+ return FSI->Kind == SK_Lambda;
+ }
+
+ /// Is this scope known to be for a generic lambda? (This will be false until
+ /// we parse a template parameter list or the first 'auto'-typed parameter).
+ bool isGenericLambda() const {
+ return !TemplateParams.empty() || GLTemplateParameterList;
+ }
+
+ /// Add a variable that might potentially be captured by the
+ /// lambda and therefore the enclosing lambdas.
+ ///
+ /// This is also used by enclosing lambda's to speculatively capture
+ /// variables that nested lambda's - depending on their enclosing
+ /// specialization - might need to capture.
+ /// Consider:
+ /// void f(int, int); <-- don't capture
+ /// void f(const int&, double); <-- capture
+ /// void foo() {
+ /// const int x = 10;
+ /// auto L = [=](auto a) { // capture 'x'
+ /// return [=](auto b) {
+ /// f(x, a); // we may or may not need to capture 'x'
+ /// };
+ /// };
+ /// }
+ void addPotentialCapture(Expr *VarExpr) {
+ assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr) ||
+ isa<FunctionParmPackExpr>(VarExpr));
+ PotentiallyCapturingExprs.push_back(VarExpr);
+ }
+
+ void addPotentialThisCapture(SourceLocation Loc) {
+ PotentialThisCaptureLocation = Loc;
+ }
+
+ bool hasPotentialThisCapture() const {
+ return PotentialThisCaptureLocation.isValid();
+ }
+
+ /// Mark a variable's reference in a lambda as non-odr using.
+ ///
+ /// For generic lambdas, if a variable is named in a potentially evaluated
+ /// expression, where the enclosing full expression is dependent then we
+ /// must capture the variable (given a default capture).
+ /// This is accomplished by recording all references to variables
+ /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of
+ /// PotentialCaptures. All such variables have to be captured by that lambda,
+ /// except for as described below.
+ /// If that variable is usable as a constant expression and is named in a
+ /// manner that does not involve its odr-use (e.g. undergoes
+ /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the
+ /// act of analyzing the enclosing full expression (ActOnFinishFullExpr)
+ /// if we can determine that the full expression is not instantiation-
+ /// dependent, then we can entirely avoid its capture.
+ ///
+ /// const int n = 0;
+ /// [&] (auto x) {
+ /// (void)+n + x;
+ /// };
+ /// Interestingly, this strategy would involve a capture of n, even though
+ /// it's obviously not odr-used here, because the full-expression is
+ /// instantiation-dependent. It could be useful to avoid capturing such
+ /// variables, even when they are referred to in an instantiation-dependent
+ /// expression, if we can unambiguously determine that they shall never be
+ /// odr-used. This would involve removal of the variable-referring-expression
+ /// from the array of PotentialCaptures during the lvalue-to-rvalue
+ /// conversions. But per the working draft N3797, (post-chicago 2013) we must
+ /// capture such variables.
+ /// Before anyone is tempted to implement a strategy for not-capturing 'n',
+ /// consider the insightful warning in:
+ /// /cfe-commits/Week-of-Mon-20131104/092596.html
+ /// "The problem is that the set of captures for a lambda is part of the ABI
+ /// (since lambda layout can be made visible through inline functions and the
+ /// like), and there are no guarantees as to which cases we'll manage to build
+ /// an lvalue-to-rvalue conversion in, when parsing a template -- some
+ /// seemingly harmless change elsewhere in Sema could cause us to start or stop
+ /// building such a node. So we need a rule that anyone can implement and get
+ /// exactly the same result".
+ void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {
+ assert(isa<DeclRefExpr>(CapturingVarExpr) ||
+ isa<MemberExpr>(CapturingVarExpr) ||
+ isa<FunctionParmPackExpr>(CapturingVarExpr));
+ NonODRUsedCapturingExprs.insert(CapturingVarExpr);
+ }
+ bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
+ assert(isa<DeclRefExpr>(CapturingVarExpr) ||
+ isa<MemberExpr>(CapturingVarExpr) ||
+ isa<FunctionParmPackExpr>(CapturingVarExpr));
+ return NonODRUsedCapturingExprs.count(CapturingVarExpr);
+ }
+ void removePotentialCapture(Expr *E) {
+ llvm::erase_value(PotentiallyCapturingExprs, E);
+ }
+ void clearPotentialCaptures() {
+ PotentiallyCapturingExprs.clear();
+ PotentialThisCaptureLocation = SourceLocation();
+ }
+ unsigned getNumPotentialVariableCaptures() const {
+ return PotentiallyCapturingExprs.size();
+ }
+
+ bool hasPotentialCaptures() const {
+ return getNumPotentialVariableCaptures() ||
+ PotentialThisCaptureLocation.isValid();
+ }
+
+ void visitPotentialCaptures(
+ llvm::function_ref<void(ValueDecl *, Expr *)> Callback) const;
+};
+
+FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
+ : Base(nullptr, false) {}
+
+FunctionScopeInfo::WeakObjectProfileTy
+FunctionScopeInfo::WeakObjectProfileTy::getSentinel() {
+ FunctionScopeInfo::WeakObjectProfileTy Result;
+ Result.Base.setInt(true);
+ return Result;
+}
+
+template <typename ExprT>
+void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
+ assert(E);
+ WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)];
+ Uses.push_back(WeakUseTy(E, IsRead));
+}
+
+inline void CapturingScopeInfo::addThisCapture(bool isNested,
+ SourceLocation Loc,
+ QualType CaptureType,
+ bool ByCopy) {
+ Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
+ ByCopy, /*Invalid*/ false));
+ CXXThisCaptureIndex = Captures.size();
+}
+
+} // namespace sema
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SCOPEINFO_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Sema.h b/contrib/libs/clang16/include/clang/Sema/Sema.h
new file mode 100644
index 0000000000..75814f5e89
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Sema.h
@@ -0,0 +1,14016 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- Sema.h - Semantic Analysis & AST Building --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Sema class, which performs semantic analysis and
+// builds ASTs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMA_H
+#define LLVM_CLANG_SEMA_SEMA_H
+
+#include "clang/AST/ASTConcept.h"
+#include "clang/AST/ASTFwd.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Availability.h"
+#include "clang/AST/ComparisonCategories.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/LocInfoType.h"
+#include "clang/AST/MangleNumberingContext.h"
+#include "clang/AST/NSAPI.h"
+#include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtOpenMP.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/BitmaskEnum.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/DarwinSDKInfo.h"
+#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/Module.h"
+#include "clang/Basic/OpenCLOptions.h"
+#include "clang/Basic/OpenMPKinds.h"
+#include "clang/Basic/PragmaKinds.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TemplateKinds.h"
+#include "clang/Basic/TypeTraits.h"
+#include "clang/Sema/AnalysisBasedWarnings.h"
+#include "clang/Sema/CleanupInfo.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/ObjCMethodList.h"
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaConcept.h"
+#include "clang/Sema/TypoCorrection.h"
+#include "clang/Sema/Weak.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Frontend/OpenMP/OMPConstants.h"
+#include <deque>
+#include <memory>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <vector>
+
+namespace llvm {
+ class APSInt;
+ template <typename ValueT, typename ValueInfoT> class DenseSet;
+ class SmallBitVector;
+ struct InlineAsmIdentifierInfo;
+}
+
+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;
+
+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;
+}
+
+namespace threadSafety {
+ class BeforeSet;
+ void threadSafetyCleanup(BeforeSet* Cache);
+}
+
+// FIXME: No way to easily map from TemplateTypeParmTypes to
+// TemplateTypeParmDecls, so we have this horrible PointerUnion.
+typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *>,
+ SourceLocation>
+ UnexpandedParameterPack;
+
+/// Describes whether we've seen any nullability information for the given
+/// file.
+struct FileNullability {
+ /// The first pointer declarator (of any pointer kind) in the file that does
+ /// not have a corresponding nullability annotation.
+ SourceLocation PointerLoc;
+
+ /// The end location for the first pointer declarator in the file. Used for
+ /// placing fix-its.
+ SourceLocation PointerEndLoc;
+
+ /// Which kind of pointer declarator we saw.
+ uint8_t PointerKind;
+
+ /// Whether we saw any type nullability annotations in the given file.
+ bool SawTypeNullability = false;
+};
+
+/// A mapping from file IDs to a record of whether we've seen nullability
+/// information in that file.
+class FileNullabilityMap {
+ /// A mapping from file IDs to the nullability information for each file ID.
+ llvm::DenseMap<FileID, FileNullability> Map;
+
+ /// A single-element cache based on the file ID.
+ struct {
+ FileID File;
+ FileNullability Nullability;
+ } Cache;
+
+public:
+ FileNullability &operator[](FileID file) {
+ // Check the single-element cache.
+ if (file == Cache.File)
+ return Cache.Nullability;
+
+ // It's not in the single-element cache; flush the cache if we have one.
+ if (!Cache.File.isInvalid()) {
+ Map[Cache.File] = Cache.Nullability;
+ }
+
+ // Pull this entry into the cache.
+ Cache.File = file;
+ Cache.Nullability = Map[file];
+ return Cache.Nullability;
+ }
+};
+
+/// Tracks expected type during expression parsing, for use in code completion.
+/// The type is tied to a particular token, all functions that update or consume
+/// the type take a start location of the token they are looking at as a
+/// parameter. This avoids updating the type on hot paths in the parser.
+class PreferredTypeBuilder {
+public:
+ PreferredTypeBuilder(bool Enabled) : Enabled(Enabled) {}
+
+ void enterCondition(Sema &S, SourceLocation Tok);
+ void enterReturn(Sema &S, SourceLocation Tok);
+ void enterVariableInit(SourceLocation Tok, Decl *D);
+ /// Handles e.g. BaseType{ .D = Tok...
+ void enterDesignatedInitializer(SourceLocation Tok, QualType BaseType,
+ const Designation &D);
+ /// Computing a type for the function argument may require running
+ /// overloading, so we postpone its computation until it is actually needed.
+ ///
+ /// Clients should be very careful when using this function, as it stores a
+ /// function_ref, clients should make sure all calls to get() with the same
+ /// location happen while function_ref is alive.
+ ///
+ /// The callback should also emit signature help as a side-effect, but only
+ /// if the completion point has been reached.
+ void enterFunctionArgument(SourceLocation Tok,
+ llvm::function_ref<QualType()> ComputeType);
+
+ void enterParenExpr(SourceLocation Tok, SourceLocation LParLoc);
+ void enterUnary(Sema &S, SourceLocation Tok, tok::TokenKind OpKind,
+ SourceLocation OpLoc);
+ void enterBinary(Sema &S, SourceLocation Tok, Expr *LHS, tok::TokenKind Op);
+ void enterMemAccess(Sema &S, SourceLocation Tok, Expr *Base);
+ void enterSubscript(Sema &S, SourceLocation Tok, Expr *LHS);
+ /// Handles all type casts, including C-style cast, C++ casts, etc.
+ void enterTypeCast(SourceLocation Tok, QualType CastType);
+
+ /// Get the expected type associated with this location, if any.
+ ///
+ /// If the location is a function argument, determining the expected type
+ /// involves considering all function overloads and the arguments so far.
+ /// In this case, signature help for these function overloads will be reported
+ /// as a side-effect (only if the completion point has been reached).
+ QualType get(SourceLocation Tok) const {
+ if (!Enabled || Tok != ExpectedLoc)
+ return QualType();
+ if (!Type.isNull())
+ return Type;
+ if (ComputeType)
+ return ComputeType();
+ return QualType();
+ }
+
+private:
+ bool Enabled;
+ /// Start position of a token for which we store expected type.
+ SourceLocation ExpectedLoc;
+ /// Expected type for a token starting at ExpectedLoc.
+ QualType Type;
+ /// A function to compute expected type at ExpectedLoc. It is only considered
+ /// if Type is null.
+ llvm::function_ref<QualType()> ComputeType;
+};
+
+/// 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);
+
+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;
+
+ /// Flag indicating whether or not to collect detailed statistics.
+ bool CollectStats;
+
+ /// Code-completion consumer.
+ CodeCompleteConsumer *CodeCompleter;
+
+ /// CurContext - This is the current declaration context of parsing.
+ DeclContext *CurContext;
+
+ /// Generally null except when we temporarily switch decl contexts,
+ /// like in \see ActOnObjCTemporaryExitContainerContext.
+ DeclContext *OriginalLexicalContext;
+
+ /// 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;
+
+ bool MSStructPragmaOn; // True when \#pragma ms_struct on
+
+ /// Controls member pointer representation format under the MS ABI.
+ LangOptions::PragmaMSPointersToMembersKind
+ MSPointerToMemberRepresentationMethod;
+
+ /// Stack of active SEH __finally scopes. Can be empty.
+ SmallVector<Scope*, 2> CurrentSEHFinally;
+
+ /// Source location for newly created implicit MSInheritanceAttrs
+ SourceLocation ImplicitMSInheritanceAttrLoc;
+
+ /// 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;
+
+ /// 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
+ };
+
+ struct PragmaClangSection {
+ std::string SectionName;
+ bool Valid = false;
+ SourceLocation PragmaLocation;
+ };
+
+ 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)
+ };
+
+ // #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 };
+
+ // #pragma pack info constructor
+ AlignPackInfo(AlignPackInfo::Mode M, unsigned Num, bool IsXL)
+ : PackAttr(true), AlignMode(M), PackNumber(Num), XLStack(IsXL) {
+ assert(Num == PackNumber && "The pack number has been truncated.");
+ }
+
+ // #pragma align info constructor
+ AlignPackInfo(AlignPackInfo::Mode M, bool IsXL)
+ : PackAttr(false), AlignMode(M),
+ PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {}
+
+ explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {}
+
+ AlignPackInfo() : AlignPackInfo(Native, false) {}
+
+ // 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;
+
+ Encoding |= static_cast<uint32_t>(Info.getPackNumber()) << 4;
+
+ return Encoding;
+ }
+
+ 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;
+
+ if (Encoding & PackAttrMask)
+ return AlignPackInfo(M, PackNumber, IsXL);
+
+ return AlignPackInfo(M, IsXL);
+ }
+
+ bool IsPackAttr() const { return PackAttr; }
+
+ bool IsAlignAttr() const { return !PackAttr; }
+
+ Mode getAlignMode() const { return AlignMode; }
+
+ unsigned getPackNumber() const { return PackNumber; }
+
+ 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;
+ }
+
+ bool IsXLStack() const { return XLStack; }
+
+ bool operator==(const AlignPackInfo &Info) const {
+ return std::tie(AlignMode, PackNumber, PackAttr, XLStack) ==
+ std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
+ Info.XLStack);
+ }
+
+ bool operator!=(const AlignPackInfo &Info) const {
+ return !(*this == Info);
+ }
+
+ private:
+ /// \brief True if this is a pragma pack attribute,
+ /// not a pragma align attribute.
+ bool PackAttr;
+
+ /// \brief The alignment mode that is in effect.
+ Mode AlignMode;
+
+ /// \brief The pack number of the stack.
+ unsigned char PackNumber;
+
+ /// \brief True if it is a XL #pragma align/pack stack.
+ bool XLStack;
+
+ /// \brief Uninitialized pack value.
+ static constexpr unsigned char UninitPackVal = -1;
+
+ // 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};
+ };
+
+ 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) {}
+ };
+
+ 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;
+ }
+ }
+
+ // 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);
+ }
+
+ // Constructors.
+ explicit PragmaStack(const ValueType &Default)
+ : DefaultValue(Default), CurrentValue(Default) {}
+
+ bool hasValue() const { return CurrentValue != DefaultValue; }
+
+ 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).
+
+ /// 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;
+
+ // #pragma strict_gs_check.
+ PragmaStack<bool> StrictGuardStackCheckStack;
+
+ // 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;
+ }
+
+ // 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();
+
+ private:
+ Sema &S;
+ StringRef SlotLabel;
+ bool ShouldAct;
+ };
+
+ /// A mapping that describes the nullability we've seen in each header file.
+ FileNullabilityMap NullabilityMap;
+
+ /// Last section used with #pragma init_seg.
+ StringLiteral *CurInitSeg;
+ SourceLocation CurInitSegLoc;
+
+ /// Sections used with #pragma alloc_text.
+ llvm::StringMap<std::tuple<StringRef, SourceLocation>> FunctionToSectionMap;
+
+ /// VisContext - Manages the stack for \#pragma GCC visibility.
+ void *VisContext; // Really a "PragmaVisStack*"
+
+ /// This an attribute introduced by \#pragma clang attribute.
+ struct PragmaAttributeEntry {
+ SourceLocation Loc;
+ ParsedAttr *Attribute;
+ SmallVector<attr::SubjectMatchRule, 4> MatchRules;
+ bool IsUsed;
+ };
+
+ /// 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;
+ };
+
+ SmallVector<PragmaAttributeGroup, 2> PragmaAttributeStack;
+
+ /// The declaration that is currently receiving an attribute from the
+ /// #pragma attribute stack.
+ const Decl *PragmaAttributeCurrentTargetDecl;
+
+ /// 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;
+
+ /// 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;
+
+ /// Set of no-builtin functions listed by \#pragma function.
+ llvm::SmallSetVector<StringRef, 4> MSFunctionNoBuiltins;
+
+ /// 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;
+
+ /// Used to control the generation of ExprWithCleanups.
+ CleanupInfo Cleanup;
+
+ /// ExprCleanupObjects - This is the stack of objects requiring
+ /// cleanup that are created by the current full expression.
+ SmallVector<ExprWithCleanups::CleanupObject, 8> ExprCleanupObjects;
+
+ /// 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::SetVector<Expr *, SmallVector<Expr *, 4>,
+ llvm::SmallPtrSet<Expr *, 4>>;
+ MaybeODRUseExprSet MaybeODRUseExprs;
+
+ std::unique_ptr<sema::FunctionScopeInfo> CachedFunctionScope;
+
+ /// 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;
+
+ ArrayRef<sema::FunctionScopeInfo*> getFunctionScopes() const {
+ return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
+ FunctionScopes.end());
+ }
+
+ /// 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;
+
+ /// The index of the first InventedParameterInfo that refers to the current
+ /// context.
+ unsigned InventedParameterInfosStart = 0;
+
+ ArrayRef<InventedTemplateParameterInfo> getInventedParameterInfos() const {
+ return llvm::ArrayRef(InventedParameterInfos.begin() +
+ InventedParameterInfosStart,
+ InventedParameterInfos.end());
+ }
+
+ typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadExtVectorDecls, 2, 2>
+ 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.
+ /// This is only necessary for issuing pretty diagnostics.
+ ExtVectorDeclsType ExtVectorDecls;
+
+ /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+ std::unique_ptr<CXXFieldCollector> FieldCollector;
+
+ typedef llvm::SmallSetVector<NamedDecl *, 16> NamedDeclSetType;
+
+ /// Set containing all declared private fields that are not used.
+ NamedDeclSetType UnusedPrivateFields;
+
+ /// Set containing all typedefs that are likely unused.
+ llvm::SmallSetVector<const TypedefNameDecl *, 4>
+ UnusedLocalTypedefNameCandidates;
+
+ /// Delete-expressions to be analyzed at the end of translation unit
+ ///
+ /// 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;
+
+ 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
+ /// same list more than once.
+ std::unique_ptr<RecordDeclSetTy> PureVirtualClassDiagSet;
+
+ /// ParsingInitForAutoVars - a set of declarations with auto types for which
+ /// we are currently parsing the initializer.
+ llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars;
+
+ /// Look for a locally scoped extern "C" declaration by the given name.
+ NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
+
+ 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;
+
+ 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<CXXConstructorDecl *, ExternalSemaSource,
+ &ExternalSemaSource::ReadDelegatingConstructors, 2, 2>
+ DelegatingCtorDeclsType;
+
+ /// All the delegating constructors seen so far in the file, used for
+ /// cycle detection at the end of the TU.
+ DelegatingCtorDeclsType DelegatingCtorDecls;
+
+ /// 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;
+
+ /// 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;
+
+ typedef llvm::MapVector<const FunctionDecl *,
+ std::unique_ptr<LateParsedTemplate>>
+ LateParsedTemplateMapT;
+ LateParsedTemplateMapT LateParsedTemplateMap;
+
+ /// Callback to the parser to parse templated functions when needed.
+ typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT);
+ typedef void LateTemplateParserCleanupCB(void *P);
+ LateTemplateParserCB *LateTemplateParser;
+ LateTemplateParserCleanupCB *LateTemplateParserCleanup;
+ void *OpaqueParser;
+
+ void SetLateTemplateParser(LateTemplateParserCB *LTP,
+ LateTemplateParserCleanupCB *LTPCleanup,
+ void *P) {
+ LateTemplateParser = LTP;
+ LateTemplateParserCleanup = LTPCleanup;
+ OpaqueParser = P;
+ }
+
+ class DelayedDiagnostics;
+
+ class DelayedDiagnosticsState {
+ sema::DelayedDiagnosticPool *SavedPool;
+ friend class Sema::DelayedDiagnostics;
+ };
+ typedef DelayedDiagnosticsState ParsingDeclState;
+ typedef DelayedDiagnosticsState ProcessingContextState;
+
+ /// A class which encapsulates the logic for delaying diagnostics
+ /// during parsing and other processing.
+ class DelayedDiagnostics {
+ /// The current pool of diagnostics into which delayed
+ /// diagnostics should go.
+ sema::DelayedDiagnosticPool *CurPool;
+
+ public:
+ DelayedDiagnostics() : CurPool(nullptr) {}
+
+ /// Adds a delayed diagnostic.
+ void add(const sema::DelayedDiagnostic &diag); // in DelayedDiagnostic.h
+
+ /// Determines whether diagnostics should be delayed.
+ bool shouldDelayDiagnostics() { return CurPool != nullptr; }
+
+ /// Returns the current delayed-diagnostics pool.
+ sema::DelayedDiagnosticPool *getCurrentPool() const {
+ return CurPool;
+ }
+
+ /// Enter a new scope. Access and deprecation diagnostics will be
+ /// collected in this pool.
+ DelayedDiagnosticsState push(sema::DelayedDiagnosticPool &pool) {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = &pool;
+ return state;
+ }
+
+ /// Leave a delayed-diagnostic state that was previously pushed.
+ /// Do not emit any of the diagnostics. This is performed as part
+ /// of the bookkeeping of popping a pool "properly".
+ void popWithoutEmitting(DelayedDiagnosticsState state) {
+ CurPool = state.SavedPool;
+ }
+
+ /// Enter a new scope where access and deprecation diagnostics are
+ /// not delayed.
+ DelayedDiagnosticsState pushUndelayed() {
+ DelayedDiagnosticsState state;
+ state.SavedPool = CurPool;
+ CurPool = nullptr;
+ return state;
+ }
+
+ /// Undo a previous pushUndelayed().
+ void popUndelayed(DelayedDiagnosticsState state) {
+ assert(CurPool == nullptr);
+ CurPool = state.SavedPool;
+ }
+ } DelayedDiagnostics;
+
+ /// 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();
+ }
+ };
+
+ /// 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;
+
+ /// Used to change context to isConstantEvaluated without pushing a heavy
+ /// ExpressionEvaluationContextRecord object.
+ bool isConstantEvaluatedOverride;
+
+ bool isConstantEvaluated() {
+ return ExprEvalContexts.back().isConstantEvaluated() ||
+ isConstantEvaluatedOverride;
+ }
+
+ /// 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) {
+ S.PushFunctionScope();
+ S.PushExpressionEvaluationContext(
+ Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+ if (auto *FD = dyn_cast<FunctionDecl>(DC))
+ FD->setWillHaveBody(true);
+ 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;
+ }
+
+ ~SynthesizedFunctionScope() {
+ if (PushedCodeSynthesisContext)
+ S.popCodeSynthesisContext();
+ if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext))
+ FD->setWillHaveBody(false);
+ S.PopExpressionEvaluationContext();
+ S.PopFunctionScopeInfo();
+ }
+ };
+
+ /// 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;
+
+
+ /// Load weak undeclared identifiers from the external source.
+ void LoadExternalWeakUndeclaredIdentifiers();
+
+ /// WeakTopLevelDecl - Translation-unit scoped declarations generated by
+ /// \#pragma weak during processing of other Decls.
+ /// I couldn't figure out a clean way to generate these in-line, so
+ /// we store them here and handle separately -- which is a hack.
+ /// It would be best to refactor this.
+ SmallVector<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;
+
+ /// The C++ "std" namespace, where the standard library resides.
+ LazyDeclPtr StdNamespace;
+
+ /// The C++ "std::bad_alloc" class, which is defined by the C++
+ /// standard library.
+ LazyDeclPtr StdBadAlloc;
+
+ /// The C++ "std::align_val_t" enum class, which is defined by the C++
+ /// standard library.
+ LazyDeclPtr StdAlignValT;
+
+ /// The C++ "std::experimental" namespace, where the experimental parts
+ /// of the standard library resides.
+ NamespaceDecl *StdExperimentalNamespaceCache;
+
+ /// The C++ "std::initializer_list" template, which is defined in
+ /// \<initializer_list>.
+ ClassTemplateDecl *StdInitializerList;
+
+ /// The C++ "std::coroutine_traits" template, which is defined in
+ /// \<coroutine_traits>
+ ClassTemplateDecl *StdCoroutineTraitsCache;
+ /// The namespace where coroutine components are defined. In standard,
+ /// they are defined in std namespace. And in the previous implementation,
+ /// they are defined in std::experimental namespace.
+ NamespaceDecl *CoroTraitsNamespaceCache;
+
+ /// The C++ "type_info" declaration, which is defined in \<typeinfo>.
+ RecordDecl *CXXTypeInfoDecl;
+
+ /// The MSVC "_GUID" struct, which is defined in MSVC header files.
+ RecordDecl *MSVCGuidDecl;
+
+ /// The C++ "std::source_location::__impl" struct, defined in
+ /// \<source_location>.
+ RecordDecl *StdSourceLocationImplDecl;
+
+ /// Caches identifiers/selectors for NSFoundation APIs.
+ std::unique_ptr<NSAPI> NSAPIObj;
+
+ /// The declaration of the Objective-C NSNumber class.
+ ObjCInterfaceDecl *NSNumberDecl;
+
+ /// The declaration of the Objective-C NSValue class.
+ ObjCInterfaceDecl *NSValueDecl;
+
+ /// Pointer to NSNumber type (NSNumber *).
+ QualType NSNumberPointer;
+
+ /// Pointer to NSValue type (NSValue *).
+ QualType NSValuePointer;
+
+ /// The Objective-C NSNumber methods used to create NSNumber literals.
+ ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
+
+ /// The declaration of the Objective-C NSString class.
+ ObjCInterfaceDecl *NSStringDecl;
+
+ /// Pointer to NSString type (NSString *).
+ QualType NSStringPointer;
+
+ /// The declaration of the stringWithUTF8String: method.
+ ObjCMethodDecl *StringWithUTF8StringMethod;
+
+ /// The declaration of the valueWithBytes:objCType: method.
+ ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
+
+ /// The declaration of the Objective-C NSArray class.
+ ObjCInterfaceDecl *NSArrayDecl;
+
+ /// The declaration of the arrayWithObjects:count: method.
+ ObjCMethodDecl *ArrayWithObjectsMethod;
+
+ /// The declaration of the Objective-C NSDictionary class.
+ ObjCInterfaceDecl *NSDictionaryDecl;
+
+ /// The declaration of the dictionaryWithObjects:forKeys:count: method.
+ ObjCMethodDecl *DictionaryWithObjectsMethod;
+
+ /// id<NSCopying> type.
+ QualType QIDNSCopying;
+
+ /// will hold 'respondsToSelector:'
+ Selector RespondsToSelectorSel;
+
+ /// A flag to remember whether the implicit forms of operator new and delete
+ /// have been declared.
+ bool GlobalNewDeleteDeclared;
+
+ /// 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,
+
+ /// The current expression occurs within a braced-init-list within
+ /// an unevaluated operand. This is mostly like a regular unevaluated
+ /// context, except that we still instantiate constexpr functions that are
+ /// referenced here so that we can perform narrowing checks correctly.
+ UnevaluatedList,
+
+ /// The current expression occurs within a discarded statement.
+ /// This behaves largely similarly to an unevaluated operand in preventing
+ /// definitions from being required, but not in other ways.
+ DiscardedStatement,
+
+ /// 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,
+
+ /// 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,
+
+ /// In addition of being constant evaluated, the current expression
+ /// occurs in an immediate function context - either a consteval function
+ /// or a consteval if function.
+ ImmediateFunctionContext,
+
+ /// 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,
+
+ /// 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
+ };
+
+ using ImmediateInvocationCandidate = llvm::PointerIntPair<ConstantExpr *, 1>;
+
+ /// Data structure used to record current or nested
+ /// expression evaluation contexts.
+ struct ExpressionEvaluationContextRecord {
+ /// The expression evaluation context.
+ ExpressionEvaluationContext Context;
+
+ /// Whether the enclosing context needed a cleanup.
+ CleanupInfo ParentCleanup;
+
+ /// The number of active cleanup objects when we entered
+ /// this expression evaluation context.
+ unsigned NumCleanupObjects;
+
+ /// The number of typos encountered during this expression evaluation
+ /// context (i.e. the number of TypoExprs created).
+ unsigned NumTypos;
+
+ MaybeODRUseExprSet SavedMaybeODRUseExprs;
+
+ /// The lambdas that are present within this context, if it
+ /// is indeed an unevaluated context.
+ SmallVector<LambdaExpr *, 2> Lambdas;
+
+ /// 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;
+
+ /// 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;
+
+ /// 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;
+
+ llvm::SmallPtrSet<const Expr *, 8> PossibleDerefs;
+
+ /// 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;
+
+ /// Set of candidates for starting an immediate invocation.
+ llvm::SmallVector<ImmediateInvocationCandidate, 4> ImmediateInvocationCandidates;
+
+ /// Set of DeclRefExprs referencing a consteval function when used in a
+ /// context not already known to be immediately invoked.
+ llvm::SmallPtrSet<DeclRefExpr *, 4> ReferenceToConsteval;
+
+ /// \brief Describes whether we are in an expression constext which we have
+ /// to handle differently.
+ enum ExpressionKind {
+ EK_Decltype, EK_TemplateArgument, EK_Other
+ } ExprContext;
+
+ // 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 IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
+
+ // 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");
+ }
+
+ SourceLocation Loc;
+ ValueDecl *Decl = nullptr;
+ DeclContext *Context = nullptr;
+ };
+ std::optional<InitializationContext> DelayedDefaultInitializationContext;
+
+ 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) {}
+
+ bool isUnevaluated() const {
+ return Context == ExpressionEvaluationContext::Unevaluated ||
+ Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
+ Context == ExpressionEvaluationContext::UnevaluatedList;
+ }
+
+ bool isConstantEvaluated() const {
+ return Context == ExpressionEvaluationContext::ConstantEvaluated ||
+ Context == ExpressionEvaluationContext::ImmediateFunctionContext;
+ }
+
+ bool isImmediateFunctionContext() const {
+ return Context == ExpressionEvaluationContext::ImmediateFunctionContext ||
+ (Context == ExpressionEvaluationContext::DiscardedStatement &&
+ InImmediateFunctionContext) ||
+ // C++2b [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);
+ }
+ };
+
+ /// A stack of expression evaluation contexts.
+ SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+
+ /// Emit a warning for all pending noderef expressions that we recorded.
+ void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
+
+ /// 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);
+
+
+ /// 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;
+
+ public:
+ SpecialMemberOverloadResult() {}
+ SpecialMemberOverloadResult(CXXMethodDecl *MD)
+ : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {}
+
+ CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
+ void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
+
+ Kind getKind() const { return static_cast<Kind>(Pair.getInt()); }
+ void setKind(Kind K) { Pair.setInt(K); }
+ };
+
+ class SpecialMemberOverloadResultEntry
+ : public llvm::FastFoldingSetNode,
+ public SpecialMemberOverloadResult {
+ public:
+ SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
+ : FastFoldingSetNode(ID)
+ {}
+ };
+
+ /// A cache of special member function overload resolution results
+ /// for C++ records.
+ llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache;
+
+ /// A cache of the flags available in enumerations with the flag_bits
+ /// attribute.
+ mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache;
+
+ /// 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;
+
+ /// The number of SFINAE diagnostics that have been trapped.
+ unsigned NumSFINAEErrors;
+
+ typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>>
+ UnparsedDefaultArgInstantiationsMap;
+
+ /// 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;
+
+ // Contains the locations of the beginning of unparsed default
+ // argument locations.
+ llvm::DenseMap<ParmVarDecl *, SourceLocation> UnparsedDefaultArgLocs;
+
+ /// UndefinedInternals - all the used, undefined objects which require a
+ /// definition in this translation unit.
+ llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed;
+
+ /// Determine if VD, which must be a variable or function, is an external
+ /// symbol that nonetheless can't be referenced from outside this translation
+ /// unit because its type has no linkage and it's not extern "C".
+ bool isExternalWithNoLinkageType(ValueDecl *VD);
+
+ /// Obtain a sorted list of functions that are undefined but ODR-used.
+ void getUndefinedButUsed(
+ SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);
+
+ /// Retrieves list of suspicious delete-expressions that will be checked at
+ /// the end of translation unit.
+ const llvm::MapVector<FieldDecl *, DeleteLocs> &
+ getMismatchingDeleteExpressions() const;
+
+ 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(); }
+
+ private:
+ llvm::DenseMap<Selector, Lists> Methods;
+ };
+
+ /// 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;
+
+ /// Method selectors used in a \@selector expression. Used for implementation
+ /// of -Wselector.
+ llvm::MapVector<Selector, SourceLocation> ReferencedSelectors;
+
+ /// List of SourceLocations where 'self' is implicitly retained inside a
+ /// block.
+ llvm::SmallVector<std::pair<SourceLocation, const BlockDecl *>, 1>
+ ImplicitlyRetainedSelfLocs;
+
+ /// Kinds of C++ special members.
+ enum CXXSpecialMember {
+ CXXDefaultConstructor,
+ CXXCopyConstructor,
+ CXXMoveConstructor,
+ CXXCopyAssignment,
+ CXXMoveAssignment,
+ CXXDestructor,
+ CXXInvalid
+ };
+
+ typedef llvm::PointerIntPair<CXXRecordDecl *, 3, CXXSpecialMember>
+ SpecialMemberDecl;
+
+ /// 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;
+
+ /// 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,
+ };
+
+ /// 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;
+
+ /// Stack of types that correspond to the parameter entities that are
+ /// currently being copy-initialized. Can be empty.
+ llvm::SmallVector<QualType, 4> CurrentParameterCopyTypes;
+
+ void ReadMethodPool(Selector Sel);
+ void updateOutOfDateSelector(Selector Sel);
+
+ /// Private Helper predicate to check for 'self'.
+ bool isSelfExpr(Expr *RExpr);
+ bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method);
+
+ /// 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);
+
+ /// 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;
+ };
+
+ void addImplicitTypedef(StringRef Name, QualType T);
+
+ bool WarnedStackExhausted = false;
+
+ /// 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;
+
+ /// Indicate RISC-V vector builtin functions enabled or not.
+ bool DeclareRISCVVBuiltins = false;
+
+private:
+ std::unique_ptr<sema::RISCVIntrinsicManager> RVIntrinsicManager;
+
+ std::optional<std::unique_ptr<DarwinSDKInfo>> CachedDarwinSDKInfo;
+
+ bool WarnedDarwinSDKInfoMissing = false;
+
+public:
+ Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+ TranslationUnitKind TUKind = TU_Complete,
+ CodeCompleteConsumer *CompletionConsumer = nullptr);
+ ~Sema();
+
+ /// Perform initialization that occurs after the parser has been
+ /// initialized but before it parses anything.
+ void Initialize();
+
+ /// 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();
+
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
+ FPOptions &getCurFPFeatures() { return CurFPFeatures; }
+
+ 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(); }
+
+ DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
+ StringRef Platform);
+ DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking();
+
+ ///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);
+
+ void PrintStats() const;
+
+ /// Warn that the stack is nearly exhausted.
+ void warnStackExhausted(SourceLocation Loc);
+
+ /// Run some code with "sufficient" stack space. (Currently, at least 256K is
+ /// guaranteed). Produces a warning if we're low on stack space and allocates
+ /// more in that case. Use this in code that may recurse deeply (for example,
+ /// in template instantiation) to avoid stack overflow.
+ void runWithSufficientStackSpace(SourceLocation Loc,
+ llvm::function_ref<void()> Fn);
+
+ /// Helper class that creates diagnostics with optional
+ /// template instantiation stacks.
+ ///
+ /// This class provides a wrapper around the basic DiagnosticBuilder
+ /// class that emits diagnostics. ImmediateDiagBuilder is
+ /// responsible for emitting the diagnostic (as DiagnosticBuilder
+ /// does) and, if the diagnostic comes from inside a template
+ /// instantiation, printing the template instantiation stack as
+ /// well.
+ class ImmediateDiagBuilder : public DiagnosticBuilder {
+ Sema &SemaRef;
+ unsigned DiagID;
+
+ public:
+ 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) {}
+
+ // 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;
+
+ ~ImmediateDiagBuilder() {
+ // If we aren't active, there is nothing to do.
+ 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.
+ //
+ // This seems wasteful, in that as written the DiagnosticBuilder dtor will
+ // do its own needless checks to see if the diagnostic needs to be
+ // emitted. However, because we take care to ensure that the builder
+ // objects never escape, a sufficiently smart compiler will be able to
+ // eliminate that code.
+ Clear();
+
+ // Dispatch to Sema to emit the diagnostic.
+ SemaRef.EmitCurrentDiagnostic(DiagID);
+ }
+
+ /// Teach operator<< to produce an object of the correct type.
+ template <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
+ };
+
+ SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
+ FunctionDecl *Fn, Sema &S);
+ SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
+ SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;
+ ~SemaDiagnosticBuilder();
+
+ bool isImmediate() const { return ImmediateDiag.has_value(); }
+
+ /// 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;
+ }
+
+ void AddFixItHint(const FixItHint &Hint) const {
+ if (ImmediateDiag)
+ ImmediateDiag->AddFixItHint(Hint);
+ else if (PartialDiagId)
+ S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint);
+ }
+
+ friend ExprResult ExprError(const SemaDiagnosticBuilder &) {
+ return ExprError();
+ }
+ friend StmtResult StmtError(const SemaDiagnosticBuilder &) {
+ return StmtError();
+ }
+ operator ExprResult() const { return ExprError(); }
+ operator StmtResult() const { return StmtError(); }
+ operator TypeResult() const { return TypeError(); }
+ operator DeclResult() const { return DeclResult(true); }
+ operator MemInitResult() const { return MemInitResult(true); }
+
+ private:
+ Sema &S;
+ SourceLocation Loc;
+ unsigned DiagID;
+ FunctionDecl *Fn;
+ bool ShowCallStack;
+
+ // 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;
+ };
+
+ /// Is the last error level diagnostic immediate. This is used to determined
+ /// whether the next info diagnostic should be immediate.
+ bool IsLastErrorImmediate = true;
+
+ /// Emit a diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
+ bool DeferHint = false);
+
+ /// Emit a partial diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
+ bool DeferHint = false);
+
+ /// Build a partial diagnostic.
+ PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+
+ /// Whether deferrable diagnostics should be deferred.
+ bool DeferDiags = false;
+
+ /// RAII class to control scope of DeferDiags.
+ class DeferDiagsRAII {
+ Sema &S;
+ bool SavedDeferDiags = false;
+
+ 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);
+
+ /// 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;
+
+ /// Calls \c Lexer::getLocForEndOfToken()
+ SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
+
+ /// Retrieve the module loader associated with the preprocessor.
+ ModuleLoader &getModuleLoader() const;
+
+ /// Invent a new identifier for parameters of abbreviated templates.
+ IdentifierInfo *
+ InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
+ unsigned Index);
+
+ void emitAndClearUnusedLocalTypedefWarnings();
+
+ private:
+ /// Function or variable declarations to be checked for whether the deferred
+ /// diagnostics should be emitted.
+ llvm::SmallSetVector<Decl *, 4> DeclsToCheckForDeferredDiags;
+
+ public:
+ // 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
+ };
+
+ void ActOnStartOfTranslationUnit();
+ void ActOnEndOfTranslationUnit();
+ void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind);
+
+ void CheckDelegatingCtorCycles();
+
+ Scope *getScopeForContext(DeclContext *Ctx);
+
+ void PushFunctionScope();
+ void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+ sema::LambdaScopeInfo *PushLambdaScope();
+
+ /// 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 PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
+ RecordDecl *RD, CapturedRegionKind K,
+ unsigned OpenMPCaptureLevel = 0);
+
+ /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
+ /// time after they've been popped.
+ class PoppedFunctionScopeDeleter {
+ Sema *Self;
+
+ public:
+ explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {}
+ void operator()(sema::FunctionScopeInfo *Scope) const;
+ };
+
+ 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();
+ }
+
+ sema::FunctionScopeInfo *getEnclosingFunction() const;
+
+ void setFunctionHasBranchIntoScope();
+ void setFunctionHasBranchProtectedScope();
+ void setFunctionHasIndirectGoto();
+ void setFunctionHasMustTail();
+
+ void PushCompoundScope(bool IsStmtExpr);
+ void PopCompoundScope();
+
+ sema::CompoundScopeInfo &getCurCompoundScope() const;
+
+ bool hasAnyUnrecoverableErrorsInThisFunction() const;
+
+ /// Retrieve the current block, if any.
+ sema::BlockScopeInfo *getCurBlock();
+
+ /// 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;
+
+ /// 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);
+
+ /// Retrieve the current generic lambda info, if any.
+ sema::LambdaScopeInfo *getCurGenericLambda();
+
+ /// Retrieve the current captured region, if any.
+ sema::CapturedRegionScopeInfo *getCurCapturedRegion();
+
+ /// Retrieve the current function, if any, that should be analyzed for
+ /// potential availability violations.
+ sema::FunctionScopeInfo *getCurFunctionAvailabilityContext();
+
+ /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
+ SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+
+ /// Called before parsing a function declarator belonging to a function
+ /// declaration.
+ void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
+ unsigned TemplateParameterDepth);
+
+ /// Called after parsing a function declarator belonging to a function
+ /// declaration.
+ void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
+
+ void ActOnComment(SourceRange Comment);
+
+ //===--------------------------------------------------------------------===//
+ // Type Analysis / Processing: SemaType.cpp.
+ //
+
+ 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, ArrayType::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);
+
+ QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
+ SourceLocation AttrLoc);
+
+ /// Same as above, but constructs the AddressSpace index if not provided.
+ QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
+ SourceLocation AttrLoc);
+
+ bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
+
+ bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
+
+ /// Build a function type.
+ ///
+ /// This routine checks the function type according to C++ rules and
+ /// under the assumption that the result type and parameter types have
+ /// just been instantiated from a template. It therefore duplicates
+ /// some of the behavior of GetTypeForDeclarator, but in a much
+ /// simpler form that is only suitable for this narrow use case.
+ ///
+ /// \param T The return type of the function.
+ ///
+ /// \param ParamTypes The parameter types of the function. This array
+ /// will be modified to account for adjustments to the types of the
+ /// function parameters.
+ ///
+ /// \param Loc The location of the entity whose type involves this
+ /// function type or, if there is no such entity, the location of the
+ /// type that will have function type.
+ ///
+ /// \param Entity The name of the entity that involves the function
+ /// type, if known.
+ ///
+ /// \param EPI Extra information about the function type. Usually this will
+ /// be taken from an existing function with the same prototype.
+ ///
+ /// \returns A suitable function type, if there are no errors. The
+ /// unqualified type will always be a FunctionProtoType.
+ /// Otherwise, returns a NULL type.
+ QualType BuildFunctionType(QualType T,
+ MutableArrayRef<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);
+ 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, Scope *S);
+ TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
+
+ /// 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,
+ SourceLocation SuperLoc,
+ const FunctionProtoType *Subset,
+ SourceLocation SubLoc);
+ bool CheckParamExceptionSpec(const PartialDiagnostic &NestedDiagID,
+ const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Target,
+ SourceLocation TargetLoc,
+ const FunctionProtoType *Source,
+ SourceLocation SourceLoc);
+
+ TypeResult ActOnTypeName(Scope *S, 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);
+
+ /// Abstract class used to diagnose incomplete types.
+ struct TypeDiagnoser {
+ TypeDiagnoser() {}
+
+ virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
+ virtual ~TypeDiagnoser() {}
+ };
+
+ 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();}
+
+ 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;
+ }
+
+ public:
+ 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;
+ }
+ };
+
+ /// Do a check to make sure \p Name looks like a legal argument for the
+ /// swift_name attribute applied to decl \p D. Raise a diagnostic if the name
+ /// is invalid for the given declaration.
+ ///
+ /// \p AL is used to provide caret diagnostics in case of a malformed name.
+ ///
+ /// \returns true if the name is a valid swift name for \p D, false otherwise.
+ bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
+ const ParsedAttr &AL, bool IsAsync);
+
+ /// A 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 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;
+ }
+ };
+
+ 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
+ };
+
+ enum class AcceptableKind { Visible, Reachable };
+
+private:
+ /// Methods for marking which expressions involve dereferencing a pointer
+ /// marked with the 'noderef' attribute. Expressions are checked bottom up as
+ /// they are parsed, meaning that a noderef pointer may not be accessed. For
+ /// example, in `&*p` where `p` is a noderef pointer, we will first parse the
+ /// `*p`, but need to check that `address of` is called on it. This requires
+ /// keeping a container of all pending expressions and checking if the address
+ /// of them are eventually taken.
+ void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E);
+ void CheckAddressOfNoDeref(const Expr *E);
+ void CheckMemberAccessOfNoDeref(const MemberExpr *E);
+
+ bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
+ CompleteTypeKind Kind, TypeDiagnoser *Diagnoser);
+
+ struct ModuleScope {
+ SourceLocation BeginLoc;
+ clang::Module *Module = nullptr;
+ bool ModuleInterface = false;
+ bool IsPartition = false;
+ bool ImplicitGlobalModuleFragment = false;
+ VisibleModuleSet OuterVisibleModules;
+ };
+ /// The modules we're currently parsing.
+ llvm::SmallVector<ModuleScope, 16> ModuleScopes;
+ /// The global module fragment of the current translation unit.
+ clang::Module *GlobalModuleFragment = nullptr;
+
+ /// The modules we imported directly.
+ llvm::SmallPtrSet<clang::Module *, 8> DirectModuleImports;
+
+ /// 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 {
+ return getCurrentModule() ? getCurrentModule()->isModulePurview() : false;
+ }
+
+ /// Enter the scope of the global module.
+ Module *PushGlobalModuleFragment(SourceLocation BeginLoc, bool IsImplicit);
+ /// Leave the scope of the global module.
+ void PopGlobalModuleFragment();
+
+ VisibleModuleSet VisibleModules;
+
+ /// Cache for module units which is usable for current module.
+ llvm::DenseSet<const Module *> UsableModuleUnitsCache;
+
+ bool isUsableModule(const Module *M);
+
+ bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
+
+public:
+ /// Get the module unit whose scope we are currently within.
+ Module *getCurrentModule() const {
+ return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
+ }
+
+ /// Is the module scope we are an interface?
+ bool currentModuleIsInterface() const {
+ return ModuleScopes.empty() ? false : ModuleScopes.back().ModuleInterface;
+ }
+
+ /// 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();
+ }
+
+ bool isModuleDirectlyImported(const Module *M) {
+ return DirectModuleImports.contains(M);
+ }
+
+ // Determine whether the module M belongs to the current TU.
+ bool isModuleUnitOfCurrentTU(const Module *M) const;
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ 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 hasVisibleMergedDefinition(NamedDecl *Def);
+ bool hasMergedDefinitionInCurrentModule(NamedDecl *Def);
+
+ /// 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);
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
+ AcceptableKind Kind,
+ bool OnlyNeedComplete = false);
+ bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) {
+ NamedDecl *Hidden;
+ return hasAcceptableDefinition(D, &Hidden, Kind);
+ }
+
+ /// Determine if the template parameter \p D has a visible default argument.
+ bool
+ hasVisibleDefaultArgument(const NamedDecl *D,
+ llvm::SmallVectorImpl<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);
+
+ /// 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);
+ }
+
+ /// 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);
+
+ void completeExprArrayBound(Expr *E);
+ bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind,
+ TypeDiagnoser &Diagnoser);
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID);
+
+ template <typename... Ts>
+ bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) {
+ BoundTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser);
+ }
+
+ template <typename... Ts>
+ bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
+ const Ts &... Args) {
+ SizelessTypeDiagnoser<Ts...> Diagnoser(DiagID, Args...);
+ return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
+ }
+
+ 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);
+ }
+
+ QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
+ const CXXScopeSpec &SS, QualType T,
+ TagDecl *OwnedTagDecl = nullptr);
+
+ // Returns the underlying type of a decltype with the given expression.
+ QualType getDecltypeForExpr(Expr *E);
+
+ 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);
+
+ 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()
+ : ShouldSkip(false), CheckSameAsPrevious(false), Previous(nullptr),
+ New(nullptr) {}
+ bool ShouldSkip;
+ bool CheckSameAsPrevious;
+ NamedDecl *Previous;
+ NamedDecl *New;
+ };
+
+ DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
+
+ void DiagnoseUseOfUnimplementedSelectors();
+
+ bool isSimpleTypeSpecifier(tok::TokenKind Kind) const;
+
+ ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec *SS = nullptr,
+ bool isClassName = false, bool HasTrailingDot = false,
+ ParsedType ObjectType = nullptr,
+ bool IsCtorOrDtorName = false,
+ bool WantNontrivialTypeSourceInfo = false,
+ bool IsClassTemplateDeductionContext = true,
+ ImplicitTypenameContext AllowImplicitTypename =
+ ImplicitTypenameContext::No,
+ 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,
+ ParsedType &SuggestedType,
+ bool IsTemplateName = false);
+
+ /// Attempt to behave like MSVC in situations where lookup of an unqualified
+ /// type name has failed in a dependent context. In these situations, we
+ /// automatically form a DependentTypeName that will retry lookup in a related
+ /// scope during instantiation.
+ ParsedType ActOnMSVCUnknownTypeName(const IdentifierInfo &II,
+ SourceLocation NameLoc,
+ bool IsTemplateTypeArg);
+
+ /// Describes the result of the name lookup and resolution performed
+ /// by \c ClassifyName().
+ enum NameClassificationKind {
+ /// This name is not a type or template in this context, but might be
+ /// something else.
+ NC_Unknown,
+ /// Classification failed; an error has been produced.
+ NC_Error,
+ /// The name has been typo-corrected to a keyword.
+ NC_Keyword,
+ /// The name was classified as a type.
+ NC_Type,
+ /// The name was classified as a specific non-type, non-template
+ /// declaration. ActOnNameClassifiedAsNonType should be called to
+ /// convert the declaration to an expression.
+ NC_NonType,
+ /// The name was classified as an ADL-only function name.
+ /// ActOnNameClassifiedAsUndeclaredNonType should be called to convert the
+ /// result to an expression.
+ NC_UndeclaredNonType,
+ /// The name denotes a member of a dependent type that could not be
+ /// resolved. ActOnNameClassifiedAsDependentNonType should be called to
+ /// convert the result to an expression.
+ NC_DependentNonType,
+ /// The name was classified as an overload set, and an expression
+ /// representing that overload set has been formed.
+ /// ActOnNameClassifiedAsOverloadSet should be called to form a suitable
+ /// expression referencing the overload set.
+ NC_OverloadSet,
+ /// The name was classified as a template whose specializations are types.
+ NC_TypeTemplate,
+ /// The name was classified as a variable template name.
+ NC_VarTemplate,
+ /// The name was classified as a function template name.
+ NC_FunctionTemplate,
+ /// The name was classified as an ADL-only function template name.
+ NC_UndeclaredTemplate,
+ /// The name was classified as a concept name.
+ NC_Concept,
+ };
+
+ class NameClassification {
+ NameClassificationKind Kind;
+ union {
+ ExprResult Expr;
+ NamedDecl *NonTypeDecl;
+ TemplateName Template;
+ ParsedType Type;
+ };
+
+ explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {}
+
+ public:
+ NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {}
+
+ NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {}
+
+ static NameClassification Error() {
+ return NameClassification(NC_Error);
+ }
+
+ static NameClassification Unknown() {
+ return NameClassification(NC_Unknown);
+ }
+
+ static NameClassification OverloadSet(ExprResult E) {
+ NameClassification Result(NC_OverloadSet);
+ Result.Expr = E;
+ return Result;
+ }
+
+ static NameClassification NonType(NamedDecl *D) {
+ NameClassification Result(NC_NonType);
+ Result.NonTypeDecl = D;
+ return Result;
+ }
+
+ static NameClassification UndeclaredNonType() {
+ return NameClassification(NC_UndeclaredNonType);
+ }
+
+ static NameClassification DependentNonType() {
+ return NameClassification(NC_DependentNonType);
+ }
+
+ static NameClassification TypeTemplate(TemplateName Name) {
+ NameClassification Result(NC_TypeTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
+ static NameClassification VarTemplate(TemplateName Name) {
+ NameClassification Result(NC_VarTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
+ static NameClassification FunctionTemplate(TemplateName Name) {
+ NameClassification Result(NC_FunctionTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
+ static NameClassification Concept(TemplateName Name) {
+ NameClassification Result(NC_Concept);
+ Result.Template = Name;
+ return Result;
+ }
+
+ static NameClassification UndeclaredTemplate(TemplateName Name) {
+ NameClassification Result(NC_UndeclaredTemplate);
+ Result.Template = Name;
+ return Result;
+ }
+
+ NameClassificationKind getKind() const { return Kind; }
+
+ ExprResult getExpression() const {
+ assert(Kind == NC_OverloadSet);
+ return Expr;
+ }
+
+ ParsedType getType() const {
+ assert(Kind == NC_Type);
+ return Type;
+ }
+
+ NamedDecl *getNonTypeDecl() const {
+ assert(Kind == NC_NonType);
+ return NonTypeDecl;
+ }
+
+ TemplateName getTemplateName() const {
+ assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate ||
+ Kind == NC_VarTemplate || Kind == NC_Concept ||
+ Kind == NC_UndeclaredTemplate);
+ return Template;
+ }
+
+ TemplateNameKind getTemplateNameKind() const {
+ switch (Kind) {
+ case NC_TypeTemplate:
+ return TNK_Type_template;
+ case NC_FunctionTemplate:
+ return TNK_Function_template;
+ case NC_VarTemplate:
+ return TNK_Var_template;
+ case NC_Concept:
+ return TNK_Concept_template;
+ case NC_UndeclaredTemplate:
+ return TNK_Undeclared_template;
+ default:
+ llvm_unreachable("unsupported name classification.");
+ }
+ }
+ };
+
+ /// Perform name lookup on the given name, classifying it based on
+ /// the results of name lookup and the following token.
+ ///
+ /// This routine is used by the parser to resolve identifiers and help direct
+ /// parsing. When the identifier cannot be found, this routine will attempt
+ /// to correct the typo and classify based on the resulting name.
+ ///
+ /// \param S The scope in which we're performing name lookup.
+ ///
+ /// \param SS The nested-name-specifier that precedes the name.
+ ///
+ /// \param Name The identifier. If typo correction finds an alternative name,
+ /// this pointer parameter will be updated accordingly.
+ ///
+ /// \param NameLoc The location of the identifier.
+ ///
+ /// \param NextToken The token following the identifier. Used to help
+ /// disambiguate the name.
+ ///
+ /// \param CCC The correction callback, if typo correction is desired.
+ NameClassification ClassifyName(Scope *S, CXXScopeSpec &SS,
+ IdentifierInfo *&Name, SourceLocation NameLoc,
+ const Token &NextToken,
+ CorrectionCandidateCallback *CCC = nullptr);
+
+ /// Act on the result of classifying a name as an undeclared (ADL-only)
+ /// non-type declaration.
+ ExprResult ActOnNameClassifiedAsUndeclaredNonType(IdentifierInfo *Name,
+ SourceLocation NameLoc);
+ /// Act on the result of classifying a name as an undeclared member of a
+ /// dependent base class.
+ ExprResult ActOnNameClassifiedAsDependentNonType(const CXXScopeSpec &SS,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsAddressOfOperand);
+ /// Act on the result of classifying a name as a specific non-type
+ /// declaration.
+ ExprResult ActOnNameClassifiedAsNonType(Scope *S, const CXXScopeSpec &SS,
+ NamedDecl *Found,
+ SourceLocation NameLoc,
+ const Token &NextToken);
+ /// Act on the result of classifying a name as an overload set.
+ ExprResult ActOnNameClassifiedAsOverloadSet(Scope *S, Expr *OverloadSet);
+
+ /// Describes the detailed kind of a template name. Used in diagnostics.
+ enum class TemplateNameKindForDiagnostics {
+ ClassTemplate,
+ FunctionTemplate,
+ VarTemplate,
+ AliasTemplate,
+ TemplateTemplateParam,
+ Concept,
+ DependentTemplate
+ };
+ TemplateNameKindForDiagnostics
+ getTemplateNameKindForDiagnostics(TemplateName Name);
+
+ /// Determine whether it's plausible that E was intended to be a
+ /// template-name.
+ bool mightBeIntendedToBeTemplateName(ExprResult E, bool &Dependent) {
+ if (!getLangOpts().CPlusPlus || E.isInvalid())
+ return false;
+ Dependent = false;
+ if (auto *DRE = dyn_cast<DeclRefExpr>(E.get()))
+ return !DRE->hasExplicitTemplateArgs();
+ if (auto *ME = dyn_cast<MemberExpr>(E.get()))
+ return !ME->hasExplicitTemplateArgs();
+ Dependent = true;
+ if (auto *DSDRE = dyn_cast<DependentScopeDeclRefExpr>(E.get()))
+ return !DSDRE->hasExplicitTemplateArgs();
+ if (auto *DSME = dyn_cast<CXXDependentScopeMemberExpr>(E.get()))
+ return !DSME->hasExplicitTemplateArgs();
+ // Any additional cases recognized here should also be handled by
+ // diagnoseExprIntendedAsTemplateName.
+ return false;
+ }
+ void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
+ SourceLocation Less,
+ SourceLocation Greater);
+
+ void warnOnReservedIdentifier(const NamedDecl *D);
+
+ Decl *ActOnDeclarator(Scope *S, Declarator &D);
+
+ NamedDecl *HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists);
+ bool tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo,
+ QualType &T, SourceLocation Loc,
+ unsigned FailedFoldDiagID);
+ void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S);
+ bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
+ bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
+ DeclarationName Name, SourceLocation Loc,
+ bool IsTemplateId);
+ 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);
+ NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R);
+ NamedDecl *getShadowedDeclaration(const BindingDecl *D,
+ const LookupResult &R);
+ void CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
+ const LookupResult &R);
+ void CheckShadow(Scope *S, VarDecl *D);
+
+ /// Warn if 'E', which is an expression that is about to be modified, refers
+ /// to a shadowing declaration.
+ void CheckShadowingDeclModification(Expr *E, SourceLocation Loc);
+
+ 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);
+ void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D);
+ NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+ TypeSourceInfo *TInfo,
+ LookupResult &Previous);
+ NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D,
+ LookupResult &Previous, bool &Redeclaration);
+ NamedDecl *ActOnVariableDeclarator(
+ Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
+ LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
+ bool &AddToScope, ArrayRef<BindingDecl *> Bindings = std::nullopt);
+ NamedDecl *
+ ActOnDecompositionDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists);
+ // 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,
+ LookupResult &Previous,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool &AddToScope);
+ bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
+
+ enum class CheckConstexprKind {
+ /// Diagnose issues that are non-constant or that are extensions.
+ Diagnose,
+ /// Identify whether this function satisfies the formal rules for constexpr
+ /// functions in the current lanugage mode (with no extensions).
+ CheckValid
+ };
+
+ bool CheckConstexprFunctionDefinition(const FunctionDecl *FD,
+ CheckConstexprKind Kind);
+
+ void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
+ void FindHiddenVirtualMethods(CXXMethodDecl *MD,
+ SmallVectorImpl<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,
+ bool IsMemberSpecialization, bool DeclIsDefn);
+ bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl);
+ bool canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD,
+ QualType NewT, QualType OldT);
+ void CheckMain(FunctionDecl *FD, const DeclSpec &D);
+ void CheckMSVCRTEntryPoint(FunctionDecl *FD);
+ void CheckHLSLEntryPoint(FunctionDecl *FD);
+ Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD,
+ bool IsDefinition);
+ void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D);
+ Decl *ActOnParamDeclarator(Scope *S, Declarator &D);
+ ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T);
+ ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc,
+ 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);
+ 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.
+ enum NonTrivialCUnionContext {
+ // Function parameter.
+ NTCUC_FunctionParam,
+ // Function return.
+ NTCUC_FunctionReturn,
+ // Default-initialized object.
+ NTCUC_DefaultInitializedObject,
+ // Variable with automatic storage duration.
+ NTCUC_AutoVar,
+ // Initializer expression that might copy from another object.
+ NTCUC_CopyInit,
+ // Assignment.
+ NTCUC_Assignment,
+ // Compound literal.
+ NTCUC_CompoundLiteral,
+ // Block capture.
+ NTCUC_BlockCapture,
+ // lvalue-to-rvalue conversion of volatile type.
+ NTCUC_LValueToRValueVolatile,
+ };
+
+ /// Emit diagnostics if the initializer or any of its explicit or
+ /// implicitly-generated subexpressions require copying or
+ /// default-initializing a type that is or contains a C union type that is
+ /// non-trivial to copy or default-initialize.
+ void checkNonTrivialCUnionInInitializer(const Expr *Init, SourceLocation Loc);
+
+ // These flags are passed to checkNonTrivialCUnion.
+ enum NonTrivialCUnionKind {
+ NTCUK_Init = 0x1,
+ NTCUK_Destruct = 0x2,
+ NTCUK_Copy = 0x4,
+ };
+
+ /// Emit diagnostics if a non-trivial C union type or a struct that contains
+ /// a non-trivial C union is used in an invalid context.
+ void checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
+ NonTrivialCUnionContext UseContext,
+ unsigned NonTrivialKind);
+
+ void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
+ 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);
+ DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
+ ArrayRef<Decl *> Group);
+ DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group);
+
+ /// Should be called on all declarations that might have attached
+ /// documentation comments.
+ void ActOnDocumentableDecl(Decl *D);
+ void ActOnDocumentableDecls(ArrayRef<Decl *> Group);
+
+ enum class FnBodyKind {
+ /// C++ [dcl.fct.def.general]p1
+ /// function-body:
+ /// ctor-initializer[opt] compound-statement
+ /// function-try-block
+ Other,
+ /// = default ;
+ Default,
+ /// = delete ;
+ Delete
+ };
+
+ void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
+ SourceLocation LocAfterDecls);
+ void CheckForFunctionRedefinition(
+ FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = nullptr,
+ SkipBodyInfo *SkipBody = nullptr);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists,
+ SkipBodyInfo *SkipBody = nullptr,
+ FnBodyKind BodyKind = FnBodyKind::Other);
+ 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
+ /// code for that function.
+ ///
+ /// This will be \c false if we may need the body of the function in the
+ /// middle of parsing an expression (where it's impractical to switch to
+ /// parsing a different function), for instance, if it's constexpr in C++11
+ /// or has an 'auto' return type in C++14. These cases are essentially bugs.
+ bool canDelayFunctionBody(const Declarator &D);
+
+ /// Determine whether we can skip parsing the body of a function
+ /// definition, assuming we don't care about analyzing its body or emitting
+ /// code for that function.
+ ///
+ /// This will be \c false only if we may need the body of the function in
+ /// order to parse the rest of the program (for instance, if it is
+ /// \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);
+ Decl *ActOnSkippedFunctionBody(Decl *Decl);
+ void ActOnFinishInlineFunctionDef(FunctionDecl *D);
+
+ /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an
+ /// attribute for which parsing is delayed.
+ void ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs);
+
+ /// Diagnose any unused parameters in the given sequence of
+ /// ParmVarDecl pointers.
+ void DiagnoseUnusedParameters(ArrayRef<ParmVarDecl *> Parameters);
+
+ /// Diagnose whether the size of parameters or return value of a
+ /// function or obj-c method definition is pass-by-value and larger than a
+ /// specified threshold.
+ void
+ 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);
+
+ enum class ModuleDeclKind {
+ Interface, ///< 'export module X;'
+ Implementation, ///< 'module X;'
+ PartitionInterface, ///< 'export module X:Y;'
+ PartitionImplementation, ///< 'module X:Y;'
+ };
+
+ /// 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.
+ };
+
+private:
+ /// The parser has begun a translation unit to be compiled as a C++20
+ /// Header Unit, helper for ActOnStartOfTranslationUnit() only.
+ void HandleStartOfHeaderUnit();
+
+public:
+ /// The parser has processed a module-declaration that begins the definition
+ /// of a module interface or implementation.
+ DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc,
+ SourceLocation ModuleLoc, ModuleDeclKind MDK,
+ ModuleIdPath Path, ModuleIdPath Partition,
+ ModuleImportState &ImportState);
+
+ /// The parser has processed a global-module-fragment declaration that begins
+ /// the definition of the global module fragment of the current module unit.
+ /// \param ModuleLoc The location of the 'module' keyword.
+ DeclGroupPtrTy ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc);
+
+ /// The parser has processed a private-module-fragment declaration that begins
+ /// the definition of the private module fragment of the current module unit.
+ /// \param ModuleLoc The location of the 'module' keyword.
+ /// \param PrivateLoc The location of the 'private' keyword.
+ DeclGroupPtrTy ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
+ SourceLocation PrivateLoc);
+
+ /// The parser has processed a module import declaration.
+ ///
+ /// \param StartLoc The location of the first token in the declaration. This
+ /// could be the location of an '@', 'export', or 'import'.
+ /// \param ExportLoc The location of the 'export' keyword, if any.
+ /// \param ImportLoc The location of the 'import' keyword.
+ /// \param Path The module toplevel name as an access path.
+ /// \param IsPartition If the name is for a partition.
+ DeclResult ActOnModuleImport(SourceLocation StartLoc,
+ SourceLocation ExportLoc,
+ SourceLocation ImportLoc, ModuleIdPath Path,
+ bool IsPartition = false);
+ DeclResult ActOnModuleImport(SourceLocation StartLoc,
+ SourceLocation ExportLoc,
+ SourceLocation ImportLoc, Module *M,
+ ModuleIdPath Path = {});
+
+ /// The parser has processed a module import translated from a
+ /// #include or similar preprocessing directive.
+ void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
+ void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
+
+ /// The parsed has entered a submodule.
+ void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
+ /// The parser has left a submodule.
+ void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
+
+ /// Create an implicit import of the given module at the given
+ /// source location, for error recovery, if possible.
+ ///
+ /// This routine is typically used when an entity found by name lookup
+ /// is actually hidden within a module that we know about but the user
+ /// has forgotten to import.
+ void createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
+ Module *Mod);
+
+ /// Kinds of missing import. Note, the values of these enumerators correspond
+ /// to %select values in diagnostics.
+ enum class MissingImportKind {
+ Declaration,
+ Definition,
+ DefaultArgument,
+ ExplicitSpecialization,
+ PartialSpecialization
+ };
+
+ /// Diagnose that the specified declaration needs to be visible but
+ /// isn't, and suggest a module import that would resolve the problem.
+ void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl,
+ MissingImportKind MIK, bool Recover = true);
+ void diagnoseMissingImport(SourceLocation Loc, 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);
+
+ 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.
+ enum NonTagKind {
+ NTK_NonStruct,
+ NTK_NonClass,
+ NTK_NonUnion,
+ NTK_NonEnum,
+ NTK_Typedef,
+ NTK_TypeAlias,
+ NTK_Template,
+ NTK_TypeAliasTemplate,
+ NTK_TemplateTemplateArgument,
+ };
+
+ /// Given a non-tag type declaration, returns an enum useful for indicating
+ /// 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,
+ const IdentifierInfo *Name);
+
+ enum TagUseKind {
+ TUK_Reference, // Reference to a tag: 'struct foo *X;'
+ TUK_Declaration, // Fwd decl of a tag: 'struct foo;'
+ TUK_Definition, // Definition of a tag: 'struct foo { int X; } Y;'
+ TUK_Friend // Friend declaration: 'friend struct foo;'
+ };
+
+ enum OffsetOfKind {
+ // Not parsing a type within __builtin_offsetof.
+ OOK_Outside,
+ // Parsing a type within __builtin_offsetof.
+ OOK_Builtin,
+ // Parsing a type within macro "offsetof", defined in __buitin_offsetof
+ // To improve our diagnostic message.
+ OOK_Macro,
+ };
+
+ DeclResult ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+ SourceLocation KWLoc, CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ const ParsedAttributesView &Attr, AccessSpecifier AS,
+ SourceLocation ModulePrivateLoc,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool &OwnedDecl, bool &IsDependent,
+ SourceLocation ScopedEnumKWLoc,
+ bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
+ 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);
+
+ FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
+ AccessSpecifier AS);
+ MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
+ SourceLocation DeclStart, Declarator &D,
+ Expr *BitfieldWidth,
+ InClassInitStyle InitStyle,
+ AccessSpecifier AS,
+ const ParsedAttr &MSPropertyAttr);
+
+ 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);
+
+ 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 {
+ CXXSpecialMember SpecialMember : 8;
+ DefaultedComparisonKind Comparison : 8;
+
+ public:
+ DefaultedFunctionKind()
+ : SpecialMember(CXXInvalid), Comparison(DefaultedComparisonKind::None) {
+ }
+ DefaultedFunctionKind(CXXSpecialMember CSM)
+ : SpecialMember(CSM), Comparison(DefaultedComparisonKind::None) {}
+ DefaultedFunctionKind(DefaultedComparisonKind Comp)
+ : SpecialMember(CXXInvalid), Comparison(Comp) {}
+
+ bool isSpecialMember() const { return SpecialMember != CXXInvalid; }
+ bool isComparison() const {
+ return Comparison != DefaultedComparisonKind::None;
+ }
+
+ explicit operator bool() const {
+ return isSpecialMember() || isComparison();
+ }
+
+ CXXSpecialMember asSpecialMember() const { return SpecialMember; }
+ DefaultedComparisonKind asComparison() const { return 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 + (unsigned)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);
+ Decl *ActOnIvar(Scope *S, SourceLocation DeclStart,
+ Declarator &D, Expr *BitfieldWidth,
+ tok::ObjCKeywordKind visibility);
+
+ // This is used for both record definitions and ObjC interface declarations.
+ void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl,
+ ArrayRef<Decl *> Fields, SourceLocation LBrac,
+ SourceLocation RBrac, const ParsedAttributesView &AttrList);
+
+ /// ActOnTagStartDefinition - Invoked when we have entered the
+ /// scope of a tag's definition (e.g., for an enumeration, class,
+ /// struct, or union).
+ void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
+
+ /// Perform ODR-like check for C/ObjC when merging tag types from modules.
+ /// Differently from C++, actually parse the body and reject / error out
+ /// 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.
+ SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD);
+
+ void ActOnObjCContainerStartDefinition(ObjCContainerDecl *IDecl);
+
+ /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
+ /// C++ record definition's base-specifiers clause and are starting its
+ /// member declarations.
+ void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl,
+ SourceLocation FinalLoc,
+ bool IsFinalSpelledSealed,
+ bool IsAbstract,
+ SourceLocation LBraceLoc);
+
+ /// ActOnTagFinishDefinition - Invoked once we have finished parsing
+ /// the definition of a tag (enumeration, class, struct, or union).
+ void ActOnTagFinishDefinition(Scope *S, Decl *TagDecl,
+ SourceRange BraceRange);
+
+ void ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context);
+
+ void ActOnObjCContainerFinishDefinition();
+
+ /// Invoked when we must temporarily exit the objective-c container
+ /// scope for parsing/looking-up C constructs.
+ ///
+ /// Must be followed by a call to \see ActOnObjCReenterContainerContext
+ void ActOnObjCTemporaryExitContainerContext(ObjCContainerDecl *ObjCCtx);
+ void ActOnObjCReenterContainerContext(ObjCContainerDecl *ObjCCtx);
+
+ /// ActOnTagDefinitionError - Invoked when there was an unrecoverable
+ /// error parsing the definition of a tag.
+ void ActOnTagDefinitionError(Scope *S, Decl *TagDecl);
+
+ EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
+ EnumConstantDecl *LastEnumConst,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id,
+ Expr *val);
+ bool CheckEnumUnderlyingType(TypeSourceInfo *TI);
+ bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
+ QualType EnumUnderlyingTy, bool IsFixed,
+ const EnumDecl *Prev);
+
+ /// Determine whether the body of an anonymous enumeration should be skipped.
+ /// \param II The name of the first enumerator.
+ SkipBodyInfo shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
+ SourceLocation IILoc);
+
+ Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ const ParsedAttributesView &Attrs,
+ SourceLocation EqualLoc, Expr *Val);
+ void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
+ Decl *EnumDecl, ArrayRef<Decl *> Elements, Scope *S,
+ const ParsedAttributesView &Attr);
+
+ /// Set the current declaration context until it gets popped.
+ void PushDeclContext(Scope *S, DeclContext *DC);
+ void PopDeclContext();
+
+ /// EnterDeclaratorContext - Used when we must lookup names in the context
+ /// of a declarator's nested name specifier.
+ 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.
+ 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 ActOnExitFunctionContext();
+
+ /// If \p AllowLambda is true, treat lambda as function.
+ DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false);
+
+ /// 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);
+
+ /// 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();
+
+ /// Add this decl to the scope shadowed decl chains.
+ void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
+
+ /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
+ /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
+ /// true if 'D' belongs to the given declaration context.
+ ///
+ /// \param AllowInlineNamespace If \c true, allow the declaration to be in the
+ /// enclosing namespace set of the context, rather than contained
+ /// directly within it.
+ bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S = nullptr,
+ bool AllowInlineNamespace = false);
+
+ /// Finds the scope corresponding to the given decl context, if it
+ /// happens to be an enclosing scope. Otherwise return NULL.
+ static Scope *getScopeForDeclContext(Scope *S, DeclContext *DC);
+
+ /// Subroutines of ActOnDeclarator().
+ TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
+ TypeSourceInfo *TInfo);
+ bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New);
+
+ /// Describes the kind of merge to perform for availability
+ /// attributes (including "deprecated", "unavailable", and "availability").
+ enum AvailabilityMergeKind {
+ /// Don't merge availability attributes at all.
+ AMK_None,
+ /// Merge availability attributes for a redeclaration, which requires
+ /// an exact match.
+ AMK_Redeclaration,
+ /// Merge availability attributes for an override, which requires
+ /// an exact match or a weakening of constraints.
+ AMK_Override,
+ /// Merge availability attributes for an implementation of
+ /// a protocol requirement.
+ AMK_ProtocolImplementation,
+ /// Merge availability attributes for an implementation of
+ /// an optional protocol requirement.
+ 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,
+
+ /// The availability attribute was applied using '#pragma clang attribute'.
+ AP_PragmaClangAttribute = 1,
+
+ /// The availability attribute for a specific platform was inferred from
+ /// an availability attribute for another platform.
+ AP_InferredFromOtherPlatform = 2
+ };
+
+ /// 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);
+
+ 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);
+
+ // 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
+ };
+
+ /// C++ Overloading.
+ enum OverloadKind {
+ /// This is a legitimate overload: the existing declarations are
+ /// functions or function templates with different signatures.
+ Ovl_Overload,
+
+ /// This is not an overload because the signature exactly matches
+ /// an existing declaration.
+ Ovl_Match,
+
+ /// 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,
+ bool ConsiderRequiresClauses = true);
+
+ // 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);
+
+ // Calculates whether the friend function depends on an enclosing template for
+ // the purposes of [temp.friend] p9.
+ bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
+
+ // 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 NamedDecl *New,
+ const Expr *NewConstr);
+
+ 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
+ };
+
+ ImplicitConversionSequence
+ TryImplicitConversion(Expr *From, QualType ToType,
+ bool SuppressUserConversions,
+ AllowedExplicit AllowExplicit,
+ bool InOverloadResolution,
+ bool CStyle,
+ bool AllowObjCWritebackConversion);
+
+ 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 FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+ const FunctionProtoType *NewType,
+ unsigned *ArgPos = nullptr,
+ bool Reversed = false);
+ void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
+ QualType FromType, QualType ToType);
+
+ 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);
+
+ bool CanPerformAggregateInitializationForOverloadResolution(
+ const InitializedEntity &Entity, InitListExpr *From);
+
+ bool IsStringInit(Expr *Init, const ArrayType *AT);
+
+ bool CanPerformCopyInitialization(const InitializedEntity &Entity,
+ ExprResult Init);
+ ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+ SourceLocation EqualLoc,
+ ExprResult Init,
+ bool TopLevelOfInitList = false,
+ bool AllowExplicit = false);
+ ExprResult PerformObjectArgumentInitialization(Expr *From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
+
+ /// 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);
+
+ ExprResult PerformContextuallyConvertToBool(Expr *From);
+ ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
+
+ /// 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.
+ };
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ llvm::APSInt &Value, CCEKind CCE);
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ APValue &Value, CCEKind CCE,
+ NamedDecl *Dest = nullptr);
+
+ /// 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;
+
+ ContextualImplicitConverter(bool Suppress = false,
+ bool SuppressConversion = false)
+ : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
+
+ /// Determine whether the specified type is a valid destination type
+ /// for this conversion.
+ virtual bool match(QualType T) = 0;
+
+ /// Emits a diagnostic complaining that the expression does not have
+ /// integral or enumeration type.
+ virtual SemaDiagnosticBuilder
+ diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
+
+ /// Emits a diagnostic when the expression has incomplete class type.
+ virtual SemaDiagnosticBuilder
+ diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
+
+ /// Emits a diagnostic when the only matching conversion function
+ /// is explicit.
+ virtual SemaDiagnosticBuilder diagnoseExplicitConv(
+ Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
+
+ /// Emits a note for the explicit conversion function.
+ virtual SemaDiagnosticBuilder
+ noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
+
+ /// Emits a diagnostic when there are multiple possible conversion
+ /// functions.
+ virtual SemaDiagnosticBuilder
+ diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
+
+ /// Emits a note for one of the candidate conversions.
+ virtual SemaDiagnosticBuilder
+ noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
+
+ /// 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;
+
+ public:
+ 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 {
+ 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;
+ };
+
+ /// Perform a contextual implicit conversion.
+ ExprResult PerformContextualImplicitConversion(
+ SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
+
+
+ enum ObjCSubscriptKind {
+ OS_Array,
+ OS_Dictionary,
+ OS_Error
+ };
+ ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
+
+ // Note that LK_String is intentionally after the other literals, as
+ // this is used for diagnostics logic.
+ enum ObjCLiteralKind {
+ LK_Array,
+ LK_Dictionary,
+ LK_Numeric,
+ LK_Boxed,
+ LK_String,
+ LK_Block,
+ LK_None
+ };
+ ObjCLiteralKind CheckLiteralKind(Expr *FromE);
+
+ ExprResult PerformObjectMemberConversion(Expr *From,
+ NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
+ NamedDecl *Member);
+
+ // 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;
+
+ using ADLCallKind = CallExpr::ADLCallKind;
+
+ 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 = {});
+ 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 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);
+
+ // Emit as a 'note' the specific overload candidate
+ void NoteOverloadCandidate(
+ NamedDecl *Found, FunctionDecl *Fn,
+ OverloadCandidateRewriteKind RewriteKind = OverloadCandidateRewriteKind(),
+ QualType DestType = QualType(), bool TakingAddress = false);
+
+ // Emit as a series of 'note's all template and non-templates identified by
+ // the expression Expr
+ void NoteAllOverloadCandidates(Expr *E, QualType DestType = QualType(),
+ bool TakingAddress = false);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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());
+
+ // [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);
+
+ FunctionDecl *
+ ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
+ QualType TargetType,
+ bool Complain,
+ DeclAccessPair &Found,
+ bool *pHadMultipleCandidates = nullptr);
+
+ FunctionDecl *
+ resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult);
+
+ bool resolveAndFixAddressOfSingleOverloadCandidate(
+ ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
+
+ FunctionDecl *
+ ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
+ bool Complain = false,
+ DeclAccessPair *Found = nullptr);
+
+ bool ResolveAndFixSingleFunctionTemplateSpecialization(
+ ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
+ bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(),
+ QualType DestTypeForComplaining = QualType(),
+ unsigned DiagIDForComplaining = 0);
+
+ Expr *FixOverloadedFunctionReference(Expr *E,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+ ExprResult FixOverloadedFunctionReference(ExprResult,
+ DeclAccessPair FoundDecl,
+ FunctionDecl *Fn);
+
+ 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
+ };
+
+ ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
+ SourceLocation RangeLoc,
+ const DeclarationNameInfo &NameInfo,
+ LookupResult &MemberLookup,
+ 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);
+
+ bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+ MultiExprArg Args, SourceLocation RParenLoc,
+ OverloadCandidateSet *CandidateSet,
+ ExprResult *Result);
+
+ ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
+ NestedNameSpecifierLoc NNSLoc,
+ DeclarationNameInfo DNI,
+ const UnresolvedSetImpl &Fns,
+ bool PerformADL = true);
+
+ ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ 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,
+ bool AllowRewrittenCandidates = true,
+ FunctionDecl *DefaultedFn = nullptr);
+ ExprResult BuildSynthesizedThreeWayComparison(SourceLocation OpLoc,
+ const UnresolvedSetImpl &Fns,
+ Expr *LHS, Expr *RHS,
+ FunctionDecl *DefaultedFn);
+
+ ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ 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 BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+ SourceLocation OpLoc,
+ bool *NoArrowOperatorFound = nullptr);
+
+ /// 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);
+
+ /// 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);
+
+ /// \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.
+ //@{
+
+ /// 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
+ };
+
+ /// 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
+ };
+
+ RedeclarationKind forRedeclarationInCurContext() {
+ // 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;
+ }
+
+ /// 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,
+ };
+
+ 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)>
+ TypoRecoveryCallback;
+
+private:
+ bool CppLookupName(LookupResult &R, Scope *S);
+
+ struct TypoExprState {
+ std::unique_ptr<TypoCorrectionConsumer> Consumer;
+ TypoDiagnosticGenerator DiagHandler;
+ TypoRecoveryCallback RecoveryHandler;
+ TypoExprState();
+ TypoExprState(TypoExprState &&other) noexcept;
+ TypoExprState &operator=(TypoExprState &&other) noexcept;
+ };
+
+ /// The set of unhandled TypoExprs and their associated state.
+ llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos;
+
+ /// Creates a new TypoExpr AST node.
+ TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC,
+ TypoDiagnosticGenerator TDG,
+ TypoRecoveryCallback TRC, SourceLocation TypoLoc);
+
+ // 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;
+
+ /// Whether we have already loaded known namespaces from an extenal
+ /// source.
+ bool LoadedExternalKnownNamespaces;
+
+ /// 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);
+
+public:
+ const TypoExprState &getTypoExprState(TypoExpr *TE) const;
+
+ /// 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);
+
+ LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
+ SourceLocation GnuLabelLoc = SourceLocation());
+
+ DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
+ CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);
+ CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class,
+ unsigned Quals);
+ CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals,
+ bool RValueThis, unsigned ThisQuals);
+ CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class,
+ unsigned Quals);
+ CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals,
+ bool RValueThis, unsigned ThisQuals);
+ CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
+
+ bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
+ bool IsUDSuffix);
+ LiteralOperatorLookupResult
+ LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys,
+ bool AllowRaw, bool AllowTemplate,
+ bool AllowStringTemplate, bool DiagnoseMissing,
+ StringLiteral *StringLit = nullptr);
+ bool isKnownName(StringRef name);
+
+ /// 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(FunctionDecl *Decl,
+ bool Final = false);
+
+ // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
+ bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
+
+ void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+ ArrayRef<Expr *> Args, ADLResult &Functions);
+
+ 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);
+
+ enum CorrectTypoKind {
+ CTK_NonError, // CorrectTypo used in a non error recovery situation.
+ CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
+ };
+
+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+ Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ CorrectionCandidateCallback &CCC,
+ CorrectTypoKind Mode,
+ DeclContext *MemberContext = nullptr,
+ bool EnteringContext = false,
+ const ObjCObjectPointerType *OPT = nullptr,
+ bool RecordFailure = true);
+
+ 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);
+
+ /// 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; });
+
+ 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);
+ }
+
+ 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);
+
+ void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F);
+
+ void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
+ ArrayRef<Expr *> Args,
+ AssociatedNamespaceSet &AssociatedNamespaces,
+ AssociatedClassSet &AssociatedClasses);
+
+ void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
+ bool ConsiderLinkage, bool AllowInlineNamespace);
+
+ 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 DiagnoseAmbiguousLookup(LookupResult &Result);
+ //@}
+
+ /// Attempts to produce a RecoveryExpr after some AST node cannot be created.
+ ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
+ ArrayRef<Expr *> SubExprs,
+ QualType T = QualType());
+
+ 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);
+
+ // More parsing and symbol table subroutines.
+
+ 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);
+
+ // Options for ProcessDeclAttributeList().
+ struct ProcessDeclAttributeOptions {
+ ProcessDeclAttributeOptions()
+ : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {}
+
+ ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) {
+ ProcessDeclAttributeOptions Result = *this;
+ Result.IncludeCXX11Attributes = Val;
+ return Result;
+ }
+
+ ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) {
+ ProcessDeclAttributeOptions Result = *this;
+ Result.IgnoreTypeAttributes = Val;
+ return Result;
+ }
+
+ // Should C++11 attributes be processed?
+ bool IncludeCXX11Attributes;
+
+ // Should any type attributes encountered be ignored?
+ // If this option is false, a diagnostic will be emitted for any type
+ // attributes of a kind that does not "slide" from the declaration to
+ // the decl-specifier-seq.
+ bool IgnoreTypeAttributes;
+ };
+
+ void ProcessDeclAttributeList(Scope *S, Decl *D,
+ const ParsedAttributesView &AttrList,
+ const ProcessDeclAttributeOptions &Options =
+ ProcessDeclAttributeOptions());
+ bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
+ const ParsedAttributesView &AttrList);
+
+ void checkUnusedDeclAttributes(Declarator &D);
+
+ /// 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);
+
+ /// 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 CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
+ bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC,
+ const FunctionDecl *FD = nullptr);
+ 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, StringRef &Str,
+ bool &isDefault);
+ bool
+ checkTargetClonesAttrString(SourceLocation LiteralLoc, StringRef Str,
+ const StringLiteral *Literal, bool &HasDefault,
+ bool &HasCommas, bool &HasNotDefault,
+ SmallVectorImpl<SmallString<64>> &StringsBuffer);
+ bool checkMSInheritanceAttrOnDefinition(
+ CXXRecordDecl *RD, SourceRange Range, bool BestCase,
+ MSInheritanceModel SemanticSpelling);
+
+ void CheckAlignasUnderalignment(Decl *D);
+
+ /// 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 IsStatic, 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);
+
+ /// 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;
+
+ /// 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);
+
+ void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
+
+ void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
+ ObjCMethodDecl *Overridden,
+ bool IsProtocolMethodDecl);
+
+ /// WarnExactTypedMethods - This routine issues a warning if method
+ /// implementation declaration matches exactly that of its declaration.
+ void WarnExactTypedMethods(ObjCMethodDecl *Method,
+ ObjCMethodDecl *MethodDecl,
+ bool IsProtocolMethodDecl);
+
+ typedef llvm::SmallPtrSet<Selector, 8> SelectorSet;
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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;
+
+ /// 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);
+
+ /// 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 DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+
+ void DiagnoseMissingDesignatedInitOverrides(
+ const ObjCImplementationDecl *ImplD,
+ const ObjCInterfaceDecl *IFD);
+
+ void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
+
+ enum MethodMatchStrategy {
+ MMS_loose,
+ MMS_strict
+ };
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// Add the given method to the list of globally-known methods.
+ void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
+
+ /// Returns default addr space for method qualifiers.
+ LangAS getDefaultCXXMethodAddrSpace() const;
+
+private:
+ /// AddMethodToGlobalPool - Add an instance or factory method to the global
+ /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
+ void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+
+ /// 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);
+
+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);
+
+ bool
+ AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+ SourceRange R, bool receiverIdOrClass,
+ SmallVectorImpl<ObjCMethodDecl*>& Methods);
+
+ void
+ DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods,
+ Selector Sel, SourceRange R,
+ bool receiverIdOrClass);
+
+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);
+
+
+ /// 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();
+ }
+
+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);
+ }
+
+ /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+ void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
+ AddMethodToGlobalPool(Method, impl, /*instance*/false);
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
+ QualType ObjectType=QualType());
+ /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+ /// implementation.
+ ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
+
+ /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+ /// initialization.
+ void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+ SmallVectorImpl<ObjCIvarDecl*> &Ivars);
+
+ //===--------------------------------------------------------------------===//
+ // Statement Parsing Callbacks: SemaStmt.cpp.
+public:
+ class FullExprArg {
+ public:
+ FullExprArg() : E(nullptr) { }
+ FullExprArg(Sema &actions) : E(nullptr) { }
+
+ ExprResult release() {
+ return E;
+ }
+
+ Expr *get() const { return E; }
+
+ 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;
+ };
+
+ 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());
+ }
+
+ StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
+ StmtResult ActOnExprStmtError();
+
+ StmtResult ActOnNullStmt(SourceLocation SemiLoc,
+ bool HasLeadingEmptyMacro = false);
+
+ void ActOnStartOfCompoundStmt(bool IsStmtExpr);
+ void ActOnAfterCompoundStatementLeadingPragmas();
+ void ActOnFinishOfCompoundStmt();
+ StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+ ArrayRef<Stmt *> Elts, bool isStmtExpr);
+
+ /// A RAII object to enter scope of a compound statement.
+ class CompoundScopeRAII {
+ public:
+ CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) {
+ S.ActOnStartOfCompoundStmt(IsStmtExpr);
+ }
+
+ ~CompoundScopeRAII() {
+ S.ActOnFinishOfCompoundStmt();
+ }
+
+ private:
+ Sema &S;
+ };
+
+ /// An RAII helper that pops function a function scope on exit.
+ struct FunctionScopeRAII {
+ Sema &S;
+ bool Active;
+ FunctionScopeRAII(Sema &S) : S(S), Active(true) {}
+ ~FunctionScopeRAII() {
+ if (Active)
+ S.PopFunctionScopeInfo();
+ }
+ void disable() { Active = false; }
+ };
+
+ 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);
+
+ StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+ SourceLocation ColonLoc,
+ Stmt *SubStmt, Scope *CurScope);
+ StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+ SourceLocation ColonLoc, Stmt *SubStmt);
+
+ StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
+ ArrayRef<const Attr *> Attrs, Stmt *SubStmt);
+ StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList,
+ Stmt *SubStmt);
+
+ class ConditionResult;
+
+ 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);
+
+ 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);
+
+ 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
+ };
+
+ StmtResult ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
+ SourceLocation CoawaitLoc,
+ Stmt *InitStmt,
+ Stmt *LoopVar,
+ SourceLocation ColonLoc, Expr *Collection,
+ SourceLocation RParenLoc,
+ BuildForRangeKind Kind);
+ 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);
+ 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);
+
+ 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);
+
+ struct NamedReturnInfo {
+ const VarDecl *Candidate;
+
+ enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
+ Status S;
+
+ 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);
+
+ ExprResult
+ PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+ const NamedReturnInfo &NRInfo, Expr *Value,
+ bool SupressSimplerImplicitMoves = false);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ bool Invalid = false);
+
+ Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
+
+ StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
+ Decl *Parm, Stmt *Body);
+
+ StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
+
+ StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+ MultiStmtArg Catch, Stmt *Finally);
+
+ 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);
+
+ StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
+
+ VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
+ SourceLocation StartLoc,
+ SourceLocation IdLoc,
+ IdentifierInfo *Id);
+
+ Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+
+ 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,
+ Stmt *Block);
+ void ActOnStartSEHFinallyBlock();
+ void ActOnAbortSEHFinallyBlock();
+ StmtResult ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block);
+ StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope);
+
+ void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+
+ bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+
+ /// If it's a file scoped decl that must warn if not used, keep track
+ /// of it.
+ void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
+
+ typedef llvm::function_ref<void(SourceLocation Loc, PartialDiagnostic PD)>
+ DiagReceiverTy;
+
+ /// 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);
+
+ /// If VD is set but not otherwise used, diagnose, for a parameter or a
+ /// variable.
+ void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver);
+
+ /// 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);
+
+ /// 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);
+
+ /// Warn if a value is moved to itself.
+ void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+ SourceLocation OpLoc);
+
+ /// 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);
+
+ /// 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);
+ }
+ void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
+
+ typedef ProcessingContextState ParsingClassState;
+ ParsingClassState PushParsingClass() {
+ ParsingClassDepth++;
+ return DelayedDiagnostics.pushUndelayed();
+ }
+ void PopParsingClass(ParsingClassState state) {
+ ParsingClassDepth--;
+ DelayedDiagnostics.popUndelayed(state);
+ }
+
+ void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
+
+ void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ bool ObjCPropertyAccess,
+ bool AvoidPartialAvailabilityChecks = false,
+ ObjCInterfaceDecl *ClassReceiver = nullptr);
+
+ bool makeUnavailableInSystemHeader(SourceLocation loc,
+ UnavailableAttr::ImplicitReason reason);
+
+ /// Issue any -Wunguarded-availability warnings in \c FD
+ void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
+
+ void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+
+ //===--------------------------------------------------------------------===//
+ // Expression Parsing Callbacks: SemaExpr.cpp.
+
+ 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 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(NamedDecl *D, SourceLocation Loc,
+ ArrayRef<Expr *> Args);
+
+ 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();
+
+ void DiscardCleanupsInEvaluationContext();
+
+ ExprResult TransformToPotentiallyEvaluated(Expr *E);
+ TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
+ ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
+
+ ExprResult CheckUnevaluatedOperand(Expr *E);
+ void CheckUnusedVolatileAssignment(Expr *E);
+
+ ExprResult ActOnConstantExpression(ExprResult Res);
+
+ // 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);
+
+ ExprResult CheckLValueToRValueConversionOperand(Expr *E);
+ void CleanupVarDeclMarking();
+
+ enum TryCaptureKind {
+ TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
+ };
+
+ /// 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);
+
+ /// Try to capture the given variable.
+ bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
+ TryCaptureKind Kind = TryCapture_Implicit,
+ SourceLocation EllipsisLoc = SourceLocation());
+
+ /// Checks if the variable must be captured.
+ bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
+
+ /// Given a variable, determine the type that a reference to that
+ /// variable will have in the given scope.
+ QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
+
+ /// 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);
+
+ /// 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);
+
+ /// Figure out if an expression could be turned into a call.
+ bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
+ UnresolvedSetImpl &NonTemplateOverloads);
+
+ /// Try to convert an expression \p E to type \p Ty. Returns the result of the
+ /// conversion.
+ ExprResult tryConvertExprToType(Expr *E, QualType Ty);
+
+ /// 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);
+
+ /// 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);
+
+ // 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);
+
+ void DecomposeUnqualifiedId(const UnqualifiedId &Id,
+ TemplateArgumentListInfo &Buffer,
+ DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *&TemplateArgs);
+
+ bool DiagnoseDependentMemberLookup(LookupResult &R);
+
+ bool
+ DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ CorrectionCandidateCallback &CCC,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+ ArrayRef<Expr *> Args = std::nullopt,
+ TypoExpr **Out = nullptr);
+
+ DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
+ IdentifierInfo *II);
+ ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
+
+ ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
+ IdentifierInfo *II,
+ bool AllowBuiltinCreation=false);
+
+ ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ bool isAddressOfOperand,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ /// 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);
+
+ 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);
+
+ ExprResult
+ BuildAnonymousStructUnionMemberReference(
+ const CXXScopeSpec &SS,
+ SourceLocation nameLoc,
+ IndirectFieldDecl *indirectField,
+ DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
+ Expr *baseObjectExpr = nullptr,
+ SourceLocation opLoc = SourceLocation());
+
+ 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);
+
+ ExprResult
+ BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ bool IsAddressOfOperand, const Scope *S,
+ TypeSourceInfo **RecoveryTSI = nullptr);
+
+ ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
+ LookupResult &R,
+ bool NeedsADL,
+ bool AcceptInvalidDecl = false);
+ ExprResult BuildDeclarationNameExpr(
+ const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+ NamedDecl *FoundD = nullptr,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr,
+ bool AcceptInvalidDecl = false);
+
+ ExprResult BuildLiteralOperatorCall(LookupResult &R,
+ DeclarationNameInfo &SuffixInfo,
+ ArrayRef<Expr *> Args,
+ SourceLocation LitEndLoc,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+
+ ExprResult BuildPredefinedExpr(SourceLocation Loc,
+ PredefinedExpr::IdentKind 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);
+
+ bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
+
+ 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);
+
+ /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+ /// fragments (e.g. "foo" "bar" L"baz").
+ ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks,
+ Scope *UDLScope = nullptr);
+
+ ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ ArrayRef<ParsedType> ArgTypes,
+ ArrayRef<Expr *> ArgExprs);
+ ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ 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);
+ QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+
+ bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+
+ 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);
+
+ bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
+ bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc,
+ SourceRange ExprRange,
+ UnaryExprOrTypeTrait ExprKind);
+ ExprResult ActOnSizeofParameterPackExpr(Scope *S,
+ SourceLocation OpLoc,
+ IdentifierInfo &Name,
+ SourceLocation NameLoc,
+ SourceLocation RParenLoc);
+ ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Kind, Expr *Input);
+
+ ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+ MultiExprArg ArgExprs,
+ SourceLocation RLoc);
+ ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+
+ ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
+ Expr *ColumnIdx,
+ SourceLocation RBLoc);
+
+ 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);
+
+ /// Data structure for iterator expression.
+ struct OMPIteratorData {
+ IdentifierInfo *DeclIdent = nullptr;
+ SourceLocation DeclIdentLoc;
+ ParsedType Type;
+ OMPIteratorExpr::IteratorRange Range;
+ SourceLocation AssignLoc;
+ SourceLocation ColonLoc;
+ SourceLocation SecColonLoc;
+ };
+
+ ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
+ SourceLocation LLoc, SourceLocation RLoc,
+ ArrayRef<OMPIteratorData> Data);
+
+ // This struct is for use by ActOnMemberAccess to allow
+ // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
+ // changing the access operator from a '.' to a '->' (to see if that is the
+ // change needed to fix an error about an unknown member, e.g. when the class
+ // defines a custom operator->).
+ struct ActOnMemberAccessExtraArgs {
+ Scope *S;
+ UnqualifiedId &Id;
+ Decl *ObjCImpDecl;
+ };
+
+ ExprResult BuildMemberReferenceExpr(
+ Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
+ CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
+ ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
+
+ ExprResult
+ BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
+ bool IsArrow, const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ NamedDecl *FirstQualifierInScope, LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs,
+ const Scope *S,
+ bool SuppressQualifierCheck = false,
+ ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
+
+ ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
+ SourceLocation OpLoc,
+ const CXXScopeSpec &SS, FieldDecl *Field,
+ DeclAccessPair FoundDecl,
+ const DeclarationNameInfo &MemberNameInfo);
+
+ ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
+
+ bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+ const CXXScopeSpec &SS,
+ const LookupResult &R);
+
+ 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,
+ SourceLocation TemplateKWLoc,
+ UnqualifiedId &Member,
+ Decl *ObjCImpDecl);
+
+ MemberExpr *
+ BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
+ const CXXScopeSpec *SS, SourceLocation TemplateKWLoc,
+ ValueDecl *Member, DeclAccessPair FoundDecl,
+ bool HadMultipleCandidates,
+ const DeclarationNameInfo &MemberNameInfo, QualType Ty,
+ ExprValueKind VK, ExprObjectKind OK,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr);
+ MemberExpr *
+ BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
+ NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
+ ValueDecl *Member, DeclAccessPair FoundDecl,
+ bool HadMultipleCandidates,
+ const DeclarationNameInfo &MemberNameInfo, QualType Ty,
+ ExprValueKind VK, ExprObjectKind OK,
+ const TemplateArgumentListInfo *TemplateArgs = nullptr);
+
+ 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);
+
+ /// 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);
+
+ ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+ MultiExprArg ExecConfig,
+ SourceLocation GGGLoc);
+
+ 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);
+
+ /// Build an altivec or OpenCL literal.
+ ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
+ SourceLocation RParenLoc, Expr *E,
+ TypeSourceInfo *TInfo);
+
+ ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+
+ 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,
+ SourceLocation RBraceLoc);
+
+ ExprResult BuildInitList(SourceLocation LBraceLoc,
+ MultiExprArg InitArgList,
+ SourceLocation RBraceLoc);
+
+ ExprResult ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation EqualOrColonLoc,
+ bool GNUSyntax,
+ ExprResult Init);
+
+private:
+ static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
+
+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);
+
+ void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc);
+
+ /// 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);
+
+ /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+ ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+ LabelDecl *TheDecl);
+
+ 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();
+
+ // __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;
+ };
+
+ /// __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);
+
+ // __builtin_choose_expr(constExpr, expr1, expr2)
+ 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,
+ SourceLocation RPLoc);
+ ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
+ TypeSourceInfo *TInfo, SourceLocation RPLoc);
+
+ // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FILE(),
+ // __builtin_COLUMN(), __builtin_source_location()
+ ExprResult ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ SourceLocation BuiltinLoc,
+ SourceLocation RPLoc);
+
+ // Build a potentially resolved SourceLocExpr.
+ ExprResult BuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
+ QualType ResultTy, SourceLocation BuiltinLoc,
+ SourceLocation RPLoc,
+ DeclContext *ParentContext);
+
+ // __null
+ ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+
+ bool CheckCaseExpression(Expr *E);
+
+ /// Describes the result of an "if-exists" condition check.
+ enum IfExistsResult {
+ /// The symbol exists.
+ IER_Exists,
+
+ /// The symbol does not exist.
+ IER_DoesNotExist,
+
+ /// The name is a dependent name, so the results will differ
+ /// from one instantiation to the next.
+ IER_Dependent,
+
+ /// An error occurred.
+ IER_Error
+ };
+
+ IfExistsResult
+ CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
+ const DeclarationNameInfo &TargetNameInfo);
+
+ IfExistsResult
+ CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
+ bool IsIfExists, CXXScopeSpec &SS,
+ UnqualifiedId &Name);
+
+ StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
+ bool IsIfExists,
+ NestedNameSpecifierLoc QualifierLoc,
+ DeclarationNameInfo NameInfo,
+ Stmt *Nested);
+ StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
+ bool IsIfExists,
+ CXXScopeSpec &SS, UnqualifiedId &Name,
+ Stmt *Nested);
+
+ //===------------------------- "Block" Extension ------------------------===//
+
+ /// ActOnBlockStart - This callback is invoked when a block literal is
+ /// started.
+ void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ //===---------------------------- Clang Extensions ----------------------===//
+
+ /// __builtin_convertvector(...)
+ ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+
+ //===---------------------------- OpenCL Features -----------------------===//
+
+ /// __builtin_astype(...)
+ ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+ ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+
+ //===---------------------------- HLSL Features -------------------------===//
+ Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
+ SourceLocation KwLoc, IdentifierInfo *Ident,
+ SourceLocation IdentLoc, SourceLocation LBrace);
+ void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
+
+ //===---------------------------- C++ Features --------------------------===//
+
+ // 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);
+
+ NamespaceDecl *getStdNamespace() const;
+ NamespaceDecl *getOrCreateStdNamespace();
+
+ NamespaceDecl *lookupStdExperimentalNamespace();
+ NamespaceDecl *getCachedCoroNamespace() { return CoroTraitsNamespaceCache; }
+
+ CXXRecordDecl *getStdBadAlloc() const;
+ EnumDecl *getStdAlignValT() const;
+
+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;
+
+ ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+ CXXScopeSpec &SS,
+ ParsedType TemplateTypeTy,
+ IdentifierInfo *MemberOrBase);
+
+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,
+ };
+
+ /// 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);
+
+ /// Tests whether Ty is an instance of std::initializer_list and, if
+ /// it is and Element is not NULL, assigns the element type to Element.
+ bool isStdInitializerList(QualType Ty, QualType *Element);
+
+ /// Looks for the std::initializer_list template and instantiates it
+ /// with Element, or emits an error if it's not found.
+ ///
+ /// \returns The instantiated template, or null on error.
+ QualType BuildStdInitializerList(QualType Element, SourceLocation Loc);
+
+ /// Determine whether Ctor is an initializer-list constructor, as
+ /// defined in [dcl.init.list]p2.
+ bool isInitListConstructor(const FunctionDecl *Ctor);
+
+ Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
+ SourceLocation NamespcLoc, CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *NamespcName,
+ const ParsedAttributesView &AttrList);
+
+ void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
+
+ Decl *ActOnNamespaceAliasDef(Scope *CurScope,
+ SourceLocation NamespaceLoc,
+ SourceLocation AliasLoc,
+ IdentifierInfo *Alias,
+ CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *Ident);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
+
+ /// 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);
+
+ 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);
+
+ /// 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, unsigned ConstructKind,
+ SourceRange ParenRange);
+
+ /// 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, unsigned ConstructKind,
+ SourceRange ParenRange);
+
+ // 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,
+ unsigned ConstructKind, SourceRange ParenRange);
+
+ ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr,
+ SourceLocation InitLoc);
+
+ 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,
+ ParmVarDecl *Param, Expr *Init = nullptr,
+ bool SkipImmediateInvocations = true);
+
+ /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+ /// the default expr if needed.
+ ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
+ ParmVarDecl *Param, Expr *Init = nullptr);
+
+ /// FinalizeVarWithDestructor - Prepare for calling destructor on the
+ /// constructed variable.
+ void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+
+ /// Helper class that collects exception specifications for
+ /// implicitly-declared special member functions.
+ class ImplicitExceptionSpecification {
+ // Pointer to allow copying
+ Sema *Self;
+ // We order exception specifications thus:
+ // noexcept is the most restrictive, but is only used in C++11.
+ // throw() comes next.
+ // Then a throw(collected exceptions)
+ // Finally no specification, which is expressed as noexcept(false).
+ // throw(...) is used instead if any called function uses it.
+ ExceptionSpecificationType ComputedEST;
+ llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
+ SmallVector<QualType, 4> Exceptions;
+
+ void ClearExceptions() {
+ ExceptionsSeen.clear();
+ Exceptions.clear();
+ }
+
+ public:
+ explicit ImplicitExceptionSpecification(Sema &Self)
+ : Self(&Self), ComputedEST(EST_BasicNoexcept) {
+ if (!Self.getLangOpts().CPlusPlus11)
+ ComputedEST = EST_DynamicNone;
+ }
+
+ /// Get the computed exception specification type.
+ ExceptionSpecificationType getExceptionSpecType() const {
+ assert(!isComputedNoexcept(ComputedEST) &&
+ "noexcept(expr) should not be a possible result");
+ return ComputedEST;
+ }
+
+ /// The number of exceptions in the exception specification.
+ unsigned size() const { return Exceptions.size(); }
+
+ /// The set of exceptions in the exception specification.
+ const QualType *data() const { return Exceptions.data(); }
+
+ /// Integrate another called method into the collected data.
+ void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
+
+ /// Integrate an invoked expression into the collected data.
+ void CalledExpr(Expr *E) { CalledStmt(E); }
+
+ /// Integrate an invoked statement into the collected data.
+ void CalledStmt(Stmt *S);
+
+ /// 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;
+ }
+ };
+
+ /// Evaluate the implicit exception specification for a defaulted
+ /// special member function.
+ void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD);
+
+ /// Check the given noexcept-specifier, convert its expression, and compute
+ /// the appropriate ExceptionSpecificationType.
+ ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr,
+ ExceptionSpecificationType &EST);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ 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 ClassDecl The class declaration into which the implicit
+ /// default constructor will be added.
+ ///
+ /// \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 ClassDecl The class declaration into which the implicit
+ /// destructor will be added.
+ ///
+ /// \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.
+ ///
+ /// 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);
+
+ /// DefineImplicitCopyConstructor - Checks for feasibility of
+ /// defining this constructor as the copy constructor.
+ void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
+
+ /// 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);
+
+ /// DefineImplicitMoveConstructor - Checks for feasibility of
+ /// defining this constructor as the move constructor.
+ void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor);
+
+ /// 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);
+
+ /// Defines an implicitly-declared copy assignment operator.
+ void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
+
+ /// 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);
+
+ /// Defines an implicitly-declared move assignment operator.
+ void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
+
+ /// Force the declaration of any implicitly-declared members of this
+ /// class.
+ void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+
+ /// Check a completed declaration of an implicit special member.
+ void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
+
+ /// Determine whether the given function is an implicitly-deleted
+ /// special member function.
+ bool isImplicitlyDeleted(FunctionDecl *FD);
+
+ /// 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);
+
+ /// Whether this' shows up in the exception specification of a static
+ /// member function.
+ bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
+
+ /// Check whether 'this' shows up in the attributes of the given
+ /// static member function.
+ ///
+ /// \returns true if an error occurred.
+ bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
+
+ /// 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);
+
+ /// Wrap the expression in a ConstantExpr if it is a potential immediate
+ /// invocation.
+ ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl);
+
+ bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+ QualType DeclInitType, MultiExprArg ArgsPtr,
+ SourceLocation Loc,
+ SmallVectorImpl<Expr *> &ConvertedArgs,
+ bool AllowExplicit = false,
+ bool IsListInitialization = false);
+
+ ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
+ SourceLocation NameLoc,
+ IdentifierInfo &Name);
+
+ ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext);
+ ParsedType getDestructorName(SourceLocation TildeLoc,
+ IdentifierInfo &II, SourceLocation NameLoc,
+ Scope *S, CXXScopeSpec &SS,
+ ParsedType ObjectType,
+ bool EnteringContext);
+
+ ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
+ ParsedType ObjectType);
+
+ // Checks that reinterpret casts don't have undefined behavior.
+ void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
+ bool IsDereference, SourceRange Range);
+
+ // 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);
+
+ /// 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);
+
+ ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
+ tok::TokenKind Kind,
+ TypeSourceInfo *Ty,
+ Expr *E,
+ SourceRange AngleBrackets,
+ SourceRange Parens);
+
+ ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
+ ExprResult Operand,
+ SourceLocation RParenLoc);
+
+ ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI,
+ 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,
+ 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,
+ SourceLocation RParenLoc);
+
+ /// 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);
+
+ //// ActOnCXXThis - Parse 'this' pointer.
+ ExprResult ActOnCXXThis(SourceLocation loc);
+
+ /// Build a CXXThisExpr and mark it referenced in the current context.
+ Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
+ void MarkThisReferenced(CXXThisExpr *This);
+
+ /// Try to retrieve the type of the 'this' pointer.
+ ///
+ /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
+ QualType getCurrentThisType();
+
+ /// 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;
+
+ /// 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;
+
+ public:
+ /// Introduce a new scope where 'this' may be allowed (when enabled),
+ /// using the given declaration (which is either a class template or a
+ /// class) along with the given qualifiers.
+ /// along with the qualifiers placed on '*this'.
+ CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals,
+ bool Enabled = true);
+
+ ~CXXThisScopeRAII();
+ };
+
+ /// 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);
+
+ /// 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);
+
+ ExprResult
+ ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef<AvailabilitySpec> AvailSpecs,
+ SourceLocation AtLoc, SourceLocation RParen);
+
+ /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+ ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+
+ //// ActOnCXXThrow - Parse throw expressions.
+ ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr);
+ ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
+ bool IsThrownVarInScope);
+ bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E);
+
+ /// 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);
+
+ ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
+ SourceLocation LParenLoc,
+ MultiExprArg Exprs,
+ SourceLocation RParenLoc,
+ bool ListInitialization);
+
+ /// 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);
+
+ /// Determine whether \p FD is an aligned allocation or deallocation
+ /// function that is unavailable.
+ bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
+
+ /// Produce diagnostics if \p FD is an aligned allocation or deallocation
+ /// function that is unavailable.
+ void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
+ SourceLocation Loc);
+
+ bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+ SourceRange R);
+
+ /// 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);
+
+ bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+ DeclarationName Name, FunctionDecl *&Operator,
+ bool Diagnose = true, bool WantSize = false,
+ bool WantAligned = false);
+ FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
+ bool CanProvideSize,
+ bool Overaligned,
+ DeclarationName Name);
+ FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
+ CXXRecordDecl *RD);
+
+ /// ActOnCXXDelete - Parsed a C++ 'delete' expression
+ ExprResult ActOnCXXDelete(SourceLocation StartLoc,
+ bool UseGlobal, bool ArrayForm,
+ Expr *Operand);
+ void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
+ bool IsDelete, bool CallCanBeVirtual,
+ bool WarnOnNonAbstractTypes,
+ SourceLocation DtorLoc);
+
+ ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
+ Expr *Operand, SourceLocation RParen);
+ ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+ SourceLocation RParen);
+
+ /// 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);
+
+ /// ActOnArrayTypeTrait - Parsed one of the binary type trait support
+ /// pseudo-functions.
+ ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
+ SourceLocation KWLoc,
+ ParsedType LhsTy,
+ Expr *DimExpr,
+ SourceLocation RParen);
+
+ 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 BuildExpressionTrait(ExpressionTrait OET,
+ SourceLocation KWLoc,
+ Expr *Queried,
+ SourceLocation RParen);
+
+ 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 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);
+
+ /// 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);
+
+ MaterializeTemporaryExpr *
+ CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
+ bool BoundToLvalueReference);
+
+ 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);
+
+ // 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);
+
+ DeclContext *computeDeclContext(QualType T);
+ DeclContext *computeDeclContext(const CXXScopeSpec &SS,
+ bool EnteringContext = false);
+ bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
+ CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+
+ /// 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);
+
+ bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
+ bool *CanCorrect = nullptr);
+ NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+
+ /// 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;
+
+ /// The identifier preceding the '::'.
+ IdentifierInfo *Identifier;
+
+ /// The location of the identifier.
+ SourceLocation IdentifierLoc;
+
+ /// The location of the '::'.
+ SourceLocation CCLoc;
+
+ /// 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) {
+ }
+
+ NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
+ SourceLocation ColonColonLoc, QualType ObjectType)
+ : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
+ IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {
+ }
+ };
+
+ bool isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS,
+ NestedNameSpecInfo &IdInfo);
+
+ bool BuildCXXNestedNameSpecifier(Scope *S,
+ NestedNameSpecInfo &IdInfo,
+ bool EnteringContext,
+ CXXScopeSpec &SS,
+ NamedDecl *ScopeLookupResult,
+ bool ErrorRecoveryLookup,
+ bool *IsCorrectedToColon = nullptr,
+ bool OnlyNamespace = false);
+
+ /// 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);
+
+ ExprResult ActOnDecltypeExpression(Expr *E);
+
+ bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
+ const DeclSpec &DS,
+ SourceLocation ColonColonLoc);
+
+ bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+ NestedNameSpecInfo &IdInfo,
+ bool EnteringContext);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// Start the definition of a lambda expression.
+ CXXMethodDecl *
+ startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange,
+ TypeSourceInfo *MethodType, SourceLocation EndLoc,
+ ArrayRef<ParmVarDecl *> Params,
+ ConstexprSpecKind ConstexprKind, StorageClass SC,
+ Expr *TrailingRequiresClause);
+
+ /// Number lambda for linkage purposes if necessary.
+ void handleLambdaNumbering(
+ CXXRecordDecl *Class, CXXMethodDecl *Method,
+ std::optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling =
+ 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 ExplicitResultType,
+ bool Mutable);
+
+ /// 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);
+
+ /// 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);
+
+ /// Add an init-capture to a lambda scope.
+ void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var,
+ bool isReferenceType);
+
+ /// Note that we have finished the explicit captures for the
+ /// given lambda.
+ void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
+
+ /// \brief This is called after parsing the explicit template parameter list
+ /// on a lambda (if it exists) in C++2a.
+ void ActOnLambdaExplicitTemplateParameterList(SourceLocation LAngleLoc,
+ ArrayRef<NamedDecl *> TParams,
+ SourceLocation RAngleLoc,
+ ExprResult RequiresClause);
+
+ /// Introduce the lambda parameters into scope.
+ void addLambdaParameters(
+ ArrayRef<LambdaIntroducer::LambdaCapture> Captures,
+ CXXMethodDecl *CallOperator, Scope *CurScope);
+
+ /// Deduce a block or lambda's return type based on the return
+ /// statements present in the body.
+ void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+
+ /// 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, Scope *CurScope);
+
+ /// 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);
+
+ /// ActOnLambdaExpr - This is called when the body of a lambda expression
+ /// was successfully completed.
+ ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
+ Scope *CurScope);
+
+ /// Does copying/destroying the captured variable have side effects?
+ bool CaptureHasSideEffects(const sema::Capture &From);
+
+ /// Diagnose if an explicit lambda capture is unused. Returns true if a
+ /// diagnostic is emitted.
+ bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+ const sema::Capture &From);
+
+ /// Build a FieldDecl suitable to hold the given capture.
+ FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture);
+
+ /// Initialize the given capture with a suitable expression.
+ ExprResult BuildCaptureInit(const sema::Capture &Capture,
+ SourceLocation ImplicitCaptureLoc,
+ bool IsOpenMPMapping = false);
+
+ /// Complete a lambda-expression having processed and attached the
+ /// lambda body.
+ ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+ sema::LambdaScopeInfo *LSI);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
+ SourceLocation ConvLocation,
+ CXXConversionDecl *Conv,
+ Expr *Src);
+
+ /// 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);
+
+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;
+
+ /// 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);
+
+ /// 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);
+
+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;
+
+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();
+ }
+
+ // 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);
+ }
+
+ 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);
+
+ /// \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);
+
+ /// \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);
+
+ /// \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);
+
+ // ParseObjCStringLiteral - Parse Objective-C string literals.
+ ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ ArrayRef<Expr *> Strings);
+
+ ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
+
+ /// 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);
+
+ /// 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);
+
+ ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
+ Expr *IndexExpr,
+ ObjCMethodDecl *getterMethod,
+ ObjCMethodDecl *setterMethod);
+
+ ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
+ MutableArrayRef<ObjCDictionaryElement> Elements);
+
+ ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
+ TypeSourceInfo *EncodedTypeInfo,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+ CXXConversionDecl *Method,
+ bool HadMultipleCandidates);
+
+ ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+ SourceLocation EncodeLoc,
+ SourceLocation LParenLoc,
+ ParsedType Ty,
+ SourceLocation RParenLoc);
+
+ /// ParseObjCSelectorExpression - Build selector expression for \@selector
+ ExprResult ParseObjCSelectorExpression(Selector Sel,
+ SourceLocation AtLoc,
+ SourceLocation SelLoc,
+ SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ bool WarnMultipleSelectors);
+
+ /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
+ ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
+ SourceLocation AtLoc,
+ SourceLocation ProtoLoc,
+ SourceLocation LParenLoc,
+ SourceLocation ProtoIdLoc,
+ SourceLocation RParenLoc);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Declarations
+ //
+ Decl *ActOnStartLinkageSpecification(Scope *S,
+ SourceLocation ExternLoc,
+ Expr *LangStr,
+ SourceLocation LBraceLoc);
+ Decl *ActOnFinishLinkageSpecification(Scope *S,
+ Decl *LinkageSpec,
+ SourceLocation RBraceLoc);
+
+
+ //===--------------------------------------------------------------------===//
+ // 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);
+
+ 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);
+
+ 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,
+ Expr *InitList,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildMemInitializer(Decl *ConstructorD,
+ Scope *S,
+ CXXScopeSpec &SS,
+ IdentifierInfo *MemberOrBase,
+ ParsedType TemplateTypeTy,
+ const DeclSpec &DS,
+ SourceLocation IdLoc,
+ Expr *Init,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildMemberInitializer(ValueDecl *Member,
+ Expr *Init,
+ SourceLocation IdLoc);
+
+ MemInitResult BuildBaseInitializer(QualType BaseType,
+ TypeSourceInfo *BaseTInfo,
+ Expr *Init,
+ CXXRecordDecl *ClassDecl,
+ SourceLocation EllipsisLoc);
+
+ MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
+ Expr *Init,
+ CXXRecordDecl *ClassDecl);
+
+ bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+ CXXCtorInitializer *Initializer);
+
+ bool SetCtorInitializers(
+ CXXConstructorDecl *Constructor, bool AnyErrors,
+ ArrayRef<CXXCtorInitializer *> Initializers = std::nullopt);
+
+ void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
+
+
+ /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
+ /// mark all the non-trivial destructors of its members and bases as
+ /// referenced.
+ void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
+ CXXRecordDecl *Record);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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;
+
+ /// Load any externally-stored vtable uses.
+ void LoadExternalVTableUses();
+
+ /// Note that the vtable for the given class was used at the
+ /// given location.
+ void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+ bool DefinitionRequired = false);
+
+ /// 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();
+
+ void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+
+ void ActOnMemInitializers(Decl *ConstructorDecl,
+ SourceLocation ColonLoc,
+ ArrayRef<CXXCtorInitializer*> MemInits,
+ bool AnyErrors);
+
+ /// 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 referenceDLLExportedClassMethods();
+
+ void propagateDLLAttrToBaseClassTemplate(
+ CXXRecordDecl *Class, Attr *ClassAttr,
+ ClassTemplateSpecializationDecl *BaseTemplateSpec,
+ SourceLocation BaseLoc);
+
+ /// 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);
+
+ /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
+ void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
+
+ /// Add [[gsl::Pointer]] attributes for std:: types.
+ void inferGslPointerAttribute(TypedefNameDecl *TD);
+
+ void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
+
+ /// 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();
+
+ 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();
+
+ Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+ Expr *AssertExpr,
+ Expr *AssertMessageExpr,
+ SourceLocation RParenLoc);
+ Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+ Expr *AssertExpr,
+ StringLiteral *AssertMessageExpr,
+ SourceLocation RParenLoc,
+ bool Failed);
+ void DiagnoseStaticAssertDetails(const Expr *E);
+
+ FriendDecl *CheckFriendTypeDecl(SourceLocation LocStart,
+ SourceLocation FriendLoc,
+ TypeSourceInfo *TSInfo);
+ Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+ MultiTemplateParamsArg TemplateParams);
+ NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParams);
+
+ 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);
+ void CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
+ StorageClass &SC);
+ void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
+
+ void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
+
+ bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
+ CXXSpecialMember CSM,
+ SourceLocation DefaultLoc);
+ void CheckDelayedMemberExceptionSpecs();
+
+ bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
+ DefaultedComparisonKind DCK);
+ void DeclareImplicitEqualityComparison(CXXRecordDecl *RD,
+ FunctionDecl *Spaceship);
+ void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
+ DefaultedComparisonKind DCK);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Derived Classes
+ //
+
+ /// ActOnBaseSpecifier - Parsed a base specifier
+ CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
+ SourceRange SpecifierRange,
+ bool Virtual, AccessSpecifier Access,
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc);
+
+ BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+ const ParsedAttributesView &Attrs, bool Virtual,
+ AccessSpecifier Access, ParsedType basetype,
+ SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc);
+
+ bool AttachBaseSpecifiers(CXXRecordDecl *Class,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
+ void ActOnBaseSpecifiers(Decl *ClassDecl,
+ MutableArrayRef<CXXBaseSpecifier *> Bases);
+
+ bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
+ bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+ CXXBasePaths &Paths);
+
+ // FIXME: I don't like this name.
+ void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
+
+ 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);
+
+ bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ /// CheckOverridingFunctionReturnType - Checks whether the return types are
+ /// covariant, according to C++ [class.virtual]p5.
+ bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
+ /// spec is a subset of base spec.
+ bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+ const CXXMethodDecl *Old);
+
+ bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+
+ /// CheckOverrideControl - Check C++11 override control semantics.
+ void CheckOverrideControl(NamedDecl *D);
+
+ /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
+ /// not used in the declaration of an overriding method.
+ void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent);
+
+ /// 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);
+
+
+ //===--------------------------------------------------------------------===//
+ // C++ Access Control
+ //
+
+ enum AccessResult {
+ AR_accessible,
+ AR_inaccessible,
+ AR_dependent,
+ AR_delayed
+ };
+
+ bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+ NamedDecl *PrevMemberDecl,
+ AccessSpecifier LexicalAS);
+
+ 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());
+ }
+
+ void HandleDependentAccessCheck(const DependentDiagnostic &DD,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+ void PerformDependentDiagnostics(const DeclContext *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+
+ /// When true, access checking violations are treated as SFINAE
+ /// failures rather than hard errors.
+ bool AccessCheckingSFINAE;
+
+ enum AbstractDiagSelID {
+ AbstractNone = -1,
+ AbstractReturnType,
+ AbstractParamType,
+ AbstractVariableType,
+ AbstractFieldType,
+ AbstractIvarType,
+ AbstractSynthesizedIvarType,
+ AbstractArrayType
+ };
+
+ 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 DiagnoseAbstractType(const CXXRecordDecl *RD);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Overloaded Operators [C++ 13.5]
+ //
+
+ bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+
+ bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
+
+ //===--------------------------------------------------------------------===//
+ // 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) {}
+
+ 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:
+ std::optional<SourceLocation> TemplateKW;
+ };
+
+ enum class AssumedTemplateKind {
+ /// This is not assumed to be a template name.
+ None,
+ /// This is assumed to be a template name because lookup found nothing.
+ FoundNothing,
+ /// This is assumed to be a template name because lookup found one or more
+ /// functions (but no function templates).
+ FoundFunctions,
+ };
+ bool LookupTemplateName(
+ LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,
+ bool EnteringContext, bool &MemberOfUnknownSpecialization,
+ RequiredTemplateKind RequiredTemplate = SourceLocation(),
+ AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
+
+ TemplateNameKind isTemplateName(Scope *S,
+ CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
+ const UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template,
+ bool &MemberOfUnknownSpecialization,
+ bool Disambiguation = false);
+
+ /// 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);
+
+ bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
+ SourceLocation NameLoc,
+ bool Diagnose = true);
+
+ /// 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,
+ ParsedTemplateTy *Template = nullptr);
+
+ bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind);
+
+ bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+ NamedDecl *Instantiation,
+ bool InstantiatedFromMember,
+ const NamedDecl *Pattern,
+ const NamedDecl *PatternDef,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
+ void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
+ TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+
+ NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
+ SourceLocation EllipsisLoc,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position,
+ SourceLocation EqualLoc,
+ ParsedType DefaultArg, bool HasTypeConstraint);
+
+ 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);
+
+ bool AttachTypeConstraint(AutoTypeLoc TL,
+ NonTypeTemplateParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc);
+
+ bool RequireStructuralType(QualType T, SourceLocation Loc);
+
+ QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+ SourceLocation Loc);
+ 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);
+
+ /// 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);
+
+ 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);
+
+ TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
+ QualType NTTPType,
+ SourceLocation Loc);
+
+ /// 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);
+
+ void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+ TemplateArgumentListInfo &Out);
+
+ ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
+
+ void NoteAllFoundTemplates(TemplateName Name);
+
+ QualType CheckTemplateIdType(TemplateName Template,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs);
+
+ 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);
+
+ /// 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);
+
+ DeclResult ActOnVarTemplateSpecialization(
+ Scope *S, Declarator &D, TypeSourceInfo *DI,
+ SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+ StorageClass SC, bool IsPartialSpecialization);
+
+ /// Get the specialization of the given variable template corresponding to
+ /// the specified argument list, or a null-but-valid result if the arguments
+ /// are dependent.
+ DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation TemplateNameLoc,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ /// Form a reference to the specialization of the given variable template
+ /// corresponding to the specified argument list, or a null-but-valid result
+ /// if the arguments are dependent.
+ ExprResult CheckVarTemplateId(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ ExprResult
+ CheckConceptTemplateId(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &ConceptNameInfo,
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
+
+ ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ LookupResult &R,
+ bool RequiresADL,
+ const TemplateArgumentListInfo *TemplateArgs);
+
+ 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);
+
+ DeclResult ActOnClassTemplateSpecialization(
+ Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+ SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
+ TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
+ MultiTemplateParamsArg TemplateParameterLists,
+ SkipBodyInfo *SkipBody = nullptr);
+
+ bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
+ TemplateDecl *PrimaryTemplate,
+ unsigned NumExplicitArgs,
+ ArrayRef<TemplateArgument> Args);
+ void CheckTemplatePartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *Partial);
+ void CheckTemplatePartialSpecialization(
+ VarTemplatePartialSpecializationDecl *Partial);
+
+ Decl *ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
+
+ bool
+ CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPtOfInstantiation,
+ bool &SuppressNew);
+
+ bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
+ const TemplateArgumentListInfo &ExplicitTemplateArgs,
+ LookupResult &Previous);
+
+ 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);
+
+ /// 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.
+ ///
+ /// \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);
+
+ 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);
+
+ ExprResult
+ BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
+ QualType ParamType,
+ SourceLocation Loc);
+ ExprResult
+ BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
+ SourceLocation Loc);
+
+ /// 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,
+
+ /// 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,
+
+ /// 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
+ };
+
+ bool TemplateParameterListsAreEqual(
+ const NamedDecl *NewInstFrom, TemplateParameterList *New,
+ const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
+ TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc = SourceLocation(),
+ bool PartialOrdering = false);
+
+ bool TemplateParameterListsAreEqual(
+ TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
+ TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc = SourceLocation(),
+ bool PartialOrdering = false) {
+ return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
+ Kind, TemplateArgLoc,
+ PartialOrdering);
+ }
+
+ bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
+
+ /// 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);
+
+ /// 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);
+
+ QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ SourceLocation KeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo &II,
+ SourceLocation IILoc,
+ TypeSourceInfo **TSI,
+ bool DeducedTSTContext);
+
+ QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ SourceLocation KeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ 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);
+
+ std::string
+ getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgumentList &Args);
+
+ std::string
+ getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+ const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Concepts
+ //===--------------------------------------------------------------------===//
+ Decl *ActOnConceptDefinition(
+ Scope *S, MultiTemplateParamsArg TemplateParameterLists,
+ IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr);
+
+ void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
+ bool &AddToScope);
+
+ 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,
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation ClosingBraceLoc);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Variadic Templates (C++0x [temp.variadic])
+ //===--------------------------------------------------------------------===//
+
+ /// 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,
+
+ /// 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);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Argument Deduction (C++ [temp.deduct])
+ //===--------------------------------------------------------------------===//
+
+ /// 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);
+
+ /// Describes the result of template argument deduction.
+ ///
+ /// The TemplateDeductionResult enumeration describes the result of
+ /// template argument deduction, as returned from
+ /// DeduceTemplateArguments(). The separate TemplateDeductionInfo
+ /// structure provides additional information about the results of
+ /// template argument deduction, e.g., the deduced template argument
+ /// list (if successful) or the specific template parameters or
+ /// deduced arguments that were involved in the failure.
+ enum TemplateDeductionResult {
+ /// Template argument deduction was successful.
+ TDK_Success = 0,
+ /// The declaration was invalid; do nothing.
+ TDK_Invalid,
+ /// Template argument deduction exceeded the maximum template
+ /// instantiation depth (which has already been diagnosed).
+ TDK_InstantiationDepth,
+ /// Template argument deduction did not deduce a value
+ /// for every template parameter.
+ TDK_Incomplete,
+ /// Template argument deduction did not deduce a value for every
+ /// expansion of an expanded template parameter pack.
+ TDK_IncompletePack,
+ /// Template argument deduction produced inconsistent
+ /// deduced values for the given template parameter.
+ TDK_Inconsistent,
+ /// Template argument deduction failed due to inconsistent
+ /// cv-qualifiers on a template parameter type that would
+ /// otherwise be deduced, e.g., we tried to deduce T in "const T"
+ /// but were given a non-const "X".
+ TDK_Underqualified,
+ /// Substitution of the deduced template argument values
+ /// resulted in an error.
+ TDK_SubstitutionFailure,
+ /// After substituting deduced template arguments, a dependent
+ /// parameter type did not match the corresponding argument.
+ TDK_DeducedMismatch,
+ /// After substituting deduced template arguments, an element of
+ /// a dependent parameter type did not match the corresponding element
+ /// of the corresponding argument (when deducing from an initializer list).
+ TDK_DeducedMismatchNested,
+ /// A non-depnedent component of the parameter did not match the
+ /// corresponding component of the argument.
+ TDK_NonDeducedMismatch,
+ /// When performing template argument deduction for a function
+ /// template, there were too many call arguments.
+ TDK_TooManyArguments,
+ /// When performing template argument deduction for a function
+ /// template, there were too few call arguments.
+ TDK_TooFewArguments,
+ /// The explicitly-specified template arguments were not valid
+ /// template arguments for the given template.
+ TDK_InvalidExplicitArguments,
+ /// Checking non-dependent argument conversions failed.
+ TDK_NonDependentConversionFailure,
+ /// The deduced arguments did not satisfy the constraints associated
+ /// with the template.
+ TDK_ConstraintsNotSatisfied,
+ /// Deduction failed; that's all we know.
+ TDK_MiscellaneousDeductionFailure,
+ /// CUDA Target attributes do not match.
+ TDK_CUDATargetMismatch,
+ /// Some error which was already diagnosed.
+ TDK_AlreadyDiagnosed
+ };
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+ const TemplateArgumentList &TemplateArgs,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult SubstituteExplicitTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo &ExplicitTemplateArgs,
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+ SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType,
+ sema::TemplateDeductionInfo &Info);
+
+ /// 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) {}
+
+ QualType OriginalParamType;
+ bool DecomposedParam;
+ unsigned ArgIdx;
+ QualType OriginalArgType;
+ };
+
+ 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; });
+
+ TemplateDeductionResult DeduceTemplateArguments(
+ FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
+ bool PartialOverloading,
+ 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,
+ QualType ToType,
+ CXXConversionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info);
+
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ TemplateArgumentListInfo *ExplicitTemplateArgs,
+ FunctionDecl *&Specialization,
+ sema::TemplateDeductionInfo &Info,
+ bool IsAddressOfFunction = false);
+
+ /// Substitute Replacement for \p auto in \p TypeWithAuto
+ QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
+ /// Substitute Replacement for auto in TypeWithAuto
+ TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ QualType Replacement);
+
+ // Substitute auto in TypeWithAuto for a Dependent auto type
+ QualType SubstAutoTypeDependent(QualType TypeWithAuto);
+
+ // Substitute auto in TypeWithAuto for a Dependent auto type
+ TypeSourceInfo *
+ SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
+
+ /// Completely replace the \c auto in \p TypeWithAuto by
+ /// \p Replacement. This does not retain any \c auto type sugar.
+ QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
+ TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+ QualType Replacement);
+
+ TemplateDeductionResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer,
+ QualType &Result,
+ sema::TemplateDeductionInfo &Info,
+ bool DependentDeduction = false,
+ bool IgnoreConstraints = false);
+ void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
+ bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
+ bool Diagnose = true);
+
+ /// Declare implicit deduction guides for a class template if we've
+ /// not already done so.
+ void DeclareImplicitDeductionGuides(TemplateDecl *Template,
+ SourceLocation Loc);
+
+ QualType DeduceTemplateSpecializationFromInitializer(
+ TypeSourceInfo *TInfo, const InitializedEntity &Entity,
+ const InitializationKind &Kind, MultiExprArg Init);
+
+ QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
+ QualType Type, TypeSourceInfo *TSI,
+ SourceRange Range, bool DirectInit,
+ Expr *Init);
+
+ TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
+
+ bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
+ SourceLocation ReturnLoc, Expr *RetExpr,
+ const AutoType *AT);
+
+ FunctionTemplateDecl *getMoreSpecializedTemplate(
+ FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
+ TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
+ unsigned NumCallArguments2, bool Reversed = false);
+ UnresolvedSetIterator
+ getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
+ TemplateSpecCandidateSet &FailedCandidates,
+ SourceLocation Loc,
+ const PartialDiagnostic &NoneDiag,
+ const PartialDiagnostic &AmbigDiag,
+ const PartialDiagnostic &CandidateDiag,
+ bool Complain = true, QualType TargetType = QualType());
+
+ ClassTemplatePartialSpecializationDecl *
+ getMoreSpecializedPartialSpecialization(
+ ClassTemplatePartialSpecializationDecl *PS1,
+ ClassTemplatePartialSpecializationDecl *PS2,
+ SourceLocation Loc);
+
+ bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
+ sema::TemplateDeductionInfo &Info);
+
+ VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
+ VarTemplatePartialSpecializationDecl *PS1,
+ VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+
+ bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
+ sema::TemplateDeductionInfo &Info);
+
+ bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
+ TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc);
+
+ void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
+ unsigned Depth, llvm::SmallBitVector &Used);
+
+ 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);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Template Instantiation
+ //
+
+ MultiLevelTemplateArgumentList
+ getTemplateInstantiationArgs(const NamedDecl *D, bool Final = false,
+ const TemplateArgumentList *Innermost = nullptr,
+ bool RelativeToPrimary = false,
+ const FunctionDecl *Pattern = nullptr,
+ bool ForConstraintInstantiation = false,
+ bool SkipForSpecialization = false);
+
+ /// 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,
+
+ /// 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,
+
+ /// We are instantiating a default argument for a function.
+ /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
+ /// provides the template arguments as specified.
+ DefaultFunctionArgumentInstantiation,
+
+ /// We are substituting explicit template arguments provided for
+ /// a function template. The entity is a FunctionTemplateDecl.
+ ExplicitTemplateArgumentSubstitution,
+
+ /// 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,
+
+ /// We are substituting prior template arguments into a new
+ /// template parameter. The template parameter itself is either a
+ /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+ PriorTemplateArgumentSubstitution,
+
+ /// We are checking the validity of a default template argument that
+ /// has been used when naming a template-id.
+ DefaultTemplateArgumentChecking,
+
+ /// We are computing the exception specification for a defaulted special
+ /// member function.
+ ExceptionSpecEvaluation,
+
+ /// We are instantiating the exception specification for a function
+ /// template which was deferred until it was needed.
+ ExceptionSpecInstantiation,
+
+ /// We are instantiating a requirement of a requires expression.
+ RequirementInstantiation,
+
+ /// We are checking the satisfaction of a nested requirement of a requires
+ /// expression.
+ NestedRequirementConstraintsCheck,
+
+ /// We are declaring an implicit special member function.
+ DeclaringSpecialMember,
+
+ /// We are declaring an implicit 'operator==' for a defaulted
+ /// 'operator<=>'.
+ DeclaringImplicitEqualityComparison,
+
+ /// We are defining a synthesized function (such as a defaulted special
+ /// member).
+ DefiningSynthesizedFunction,
+
+ // 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,
+
+ // We are substituting template arguments into a constraint expression.
+ ConstraintSubstitution,
+
+ // We are normalizing a constraint expression.
+ ConstraintNormalization,
+
+ // Instantiating a Requires Expression parameter clause.
+ RequirementParameterInstantiation,
+
+ // We are substituting into the parameter mapping of an atomic constraint
+ // during normalization.
+ ParameterMappingSubstitution,
+
+ /// We are rewriting a comparison operator in terms of an operator<=>.
+ RewritingOperatorAsSpaceship,
+
+ /// We are initializing a structured binding.
+ InitializingStructuredBinding,
+
+ /// We are marking a class as __dllexport.
+ MarkingClassDllexported,
+
+ /// We are building an implied call from __builtin_dump_struct. The
+ /// arguments are in CallArgs.
+ BuildingBuiltinDumpStructCall,
+
+ /// 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
+ } Kind;
+
+ /// Was the enclosing context a non-instantiation SFINAE context?
+ bool SavedInNonInstantiationSFINAEContext;
+
+ /// The point of instantiation or synthesis within the source code.
+ SourceLocation PointOfInstantiation;
+
+ /// The entity that is being synthesized.
+ Decl *Entity;
+
+ /// The template (or partial specialization) in which we are
+ /// performing the instantiation, for substitutions of prior template
+ /// arguments.
+ NamedDecl *Template;
+
+ union {
+ /// The list of template arguments we are substituting, if they
+ /// are not part of the entity.
+ const TemplateArgument *TemplateArgs;
+
+ /// The list of argument expressions in a synthesized call.
+ const Expr *const *CallArgs;
+ };
+
+ // 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;
+
+ /// The number of expressions in CallArgs.
+ unsigned NumCallArgs;
+
+ /// The special member being declared or defined.
+ CXXSpecialMember SpecialMember;
+ };
+
+ ArrayRef<TemplateArgument> template_arguments() const {
+ assert(Kind != DeclaringSpecialMember);
+ return {TemplateArgs, NumTemplateArgs};
+ }
+
+ /// The template deduction info object associated with the
+ /// substitution or checking of explicit or deduced template arguments.
+ sema::TemplateDeductionInfo *DeductionInfo;
+
+ /// The source range that covers the construct that cause
+ /// the instantiation, e.g., the template-id that causes a class
+ /// template instantiation.
+ SourceRange InstantiationRange;
+
+ CodeSynthesisContext()
+ : Kind(TemplateInstantiation),
+ SavedInNonInstantiationSFINAEContext(false), Entity(nullptr),
+ Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0),
+ DeductionInfo(nullptr) {}
+
+ /// Determines whether this template is an actual instantiation
+ /// that should be counted toward the maximum instantiation depth.
+ bool isInstantiationRecord() const;
+ };
+
+ /// List of active code synthesis contexts.
+ ///
+ /// This vector is treated as a stack. As synthesis of one entity requires
+ /// synthesis of another, additional contexts are pushed onto the stack.
+ SmallVector<CodeSynthesisContext, 16> CodeSynthesisContexts;
+
+ /// Specializations whose definitions are currently being instantiated.
+ llvm::DenseSet<std::pair<Decl *, unsigned>> InstantiatingSpecializations;
+
+ /// Non-dependent types used in templates that have already been instantiated
+ /// by some template instantiation.
+ llvm::DenseSet<QualType> InstantiatedNonDependentTypes;
+
+ /// Extra modules inspected when performing a lookup during a template
+ /// instantiation. Computed lazily.
+ 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;
+
+ /// 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();
+
+ /// Map from the most recent declaration of a namespace to the most
+ /// recent visible declaration of that namespace.
+ llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache;
+
+ /// Whether we are in a SFINAE context that is not associated with
+ /// template instantiation.
+ ///
+ /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside
+ /// of a template instantiation or template argument deduction.
+ bool InNonInstantiationSFINAEContext;
+
+ /// 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;
+
+ /// 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;
+
+ /// 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;
+
+ /// The current index into pack expansion arguments that will be
+ /// used for substitution of parameter packs.
+ ///
+ /// The pack expansion index will be -1 to indicate that parameter packs
+ /// should be instantiated as themselves. Otherwise, the index specifies
+ /// which argument within the parameter pack will be used for substitution.
+ int ArgumentPackSubstitutionIndex;
+
+ /// RAII object used to change the argument pack substitution index
+ /// within a \c Sema object.
+ ///
+ /// See \c ArgumentPackSubstitutionIndex for more information.
+ class ArgumentPackSubstitutionIndexRAII {
+ Sema &Self;
+ int OldSubstitutionIndex;
+
+ public:
+ ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
+ : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+ Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
+ }
+
+ ~ArgumentPackSubstitutionIndexRAII() {
+ Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
+ }
+ };
+
+ friend class ArgumentPackSubstitutionRAII;
+
+ /// 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());
+
+ /// 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());
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ 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);
+
+ 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);
+
+ struct ConstraintNormalization {};
+ /// \brief Note that we are normalizing a constraint expression.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ConstraintNormalization, NamedDecl *Template,
+ SourceRange InstantiationRange);
+
+ 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);
+
+ /// \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());
+
+ /// \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());
+
+ /// \brief Note that we are checking a requires clause.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ const RequiresExpr *E,
+ sema::TemplateDeductionInfo &DeductionInfo,
+ SourceRange InstantiationRange);
+ /// Note that we have finished instantiating this template.
+ void Clear();
+
+ ~InstantiatingTemplate() { Clear(); }
+
+ /// Determines whether we have exceeded the maximum
+ /// recursive template instantiations.
+ bool isInvalid() const { return Invalid; }
+
+ /// Determine whether we are already instantiating this
+ /// specialization in some surrounding active instantiation.
+ bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
+
+ private:
+ Sema &SemaRef;
+ bool Invalid;
+ bool AlreadyInstantiating;
+ bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+ SourceRange InstantiationRange);
+
+ InstantiatingTemplate(
+ Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
+ SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
+ Decl *Entity, NamedDecl *Template = nullptr,
+ ArrayRef<TemplateArgument> TemplateArgs = std::nullopt,
+ sema::TemplateDeductionInfo *DeductionInfo = nullptr);
+
+ InstantiatingTemplate(const InstantiatingTemplate&) = delete;
+
+ InstantiatingTemplate&
+ operator=(const InstantiatingTemplate&) = delete;
+ };
+
+ void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
+ void popCodeSynthesisContext();
+
+ /// Determine whether we are currently performing template instantiation.
+ bool inTemplateInstantiation() const {
+ return CodeSynthesisContexts.size() > NonInstantiationEntries;
+ }
+
+ void PrintContextStack() {
+ if (!CodeSynthesisContexts.empty() &&
+ CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
+ PrintInstantiationStack();
+ LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
+ }
+ if (PragmaAttributeCurrentTargetDecl)
+ PrintPragmaAttributeInstantiationPoint();
+ }
+ void PrintInstantiationStack();
+
+ void PrintPragmaAttributeInstantiationPoint();
+
+ /// 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;
+
+ /// Determines whether we are currently in a context that
+ /// is not evaluated as per C++ [expr] p5.
+ bool isUnevaluatedContext() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back().isUnevaluated();
+ }
+
+ bool isConstantEvaluatedContext() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back().isConstantEvaluated();
+ }
+
+ bool isImmediateFunctionContext() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ return ExprEvalContexts.back().isImmediateFunctionContext();
+ }
+
+ bool isCheckingDefaultArgumentOrInitializer() const {
+ assert(!ExprEvalContexts.empty() &&
+ "Must be in an expression evaluation context");
+ const ExpressionEvaluationContextRecord &Ctx = ExprEvalContexts.back();
+ return (Ctx.Context ==
+ ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
+ Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ /// 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;
+
+ 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;
+ }
+ };
+
+ /// 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;
+ }
+ };
+
+ /// The current instantiation scope used to store local
+ /// variables.
+ LocalInstantiationScope *CurrentInstantiationScope;
+
+ /// 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;
+
+ /// 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;
+
+ /// Worker object for performing CFG-based warnings.
+ sema::AnalysisBasedWarnings AnalysisWarnings;
+ threadSafety::BeforeSet *ThreadSafetyDeclCache;
+
+ /// 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;
+
+ class GlobalEagerInstantiationScope {
+ public:
+ GlobalEagerInstantiationScope(Sema &S, bool Enabled)
+ : S(S), Enabled(Enabled) {
+ if (!Enabled) return;
+
+ SavedPendingInstantiations.swap(S.PendingInstantiations);
+ SavedVTableUses.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(SavedVTableUses);
+
+ // 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(SavedPendingInstantiations);
+ } else {
+ // Template instantiations in the PCH may be delayed until the TU.
+ S.PendingInstantiations.swap(SavedPendingInstantiations);
+ S.PendingInstantiations.insert(S.PendingInstantiations.end(),
+ SavedPendingInstantiations.begin(),
+ SavedPendingInstantiations.end());
+ }
+ }
+
+ private:
+ Sema &S;
+ SmallVector<VTableUse, 16> SavedVTableUses;
+ std::deque<PendingImplicitInstantiation> SavedPendingInstantiations;
+ bool Enabled;
+ };
+
+ /// 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;
+ };
+
+ /// 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();
+ }
+ };
+
+ void PerformPendingInstantiations(bool LocalOnly = false);
+
+ TypeSourceInfo *SubstType(TypeSourceInfo *T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity,
+ bool AllowDeducedTST = false);
+
+ QualType SubstType(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
+ TypeSourceInfo *SubstType(TypeLoc TL,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SourceLocation Loc, DeclarationName Entity);
+
+ 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); }
+ };
+
+ // Unlike the above, this evaluates constraints, which should only happen at
+ // 'constraint checking' time.
+ ExprResult
+ SubstConstraintExpr(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ /// Substitute the given template arguments into a list of
+ /// expressions, expanding pack expansions if required.
+ ///
+ /// \param Exprs The list of expressions to substitute into.
+ ///
+ /// \param IsCall Whether this is some form of call, in which case
+ /// default arguments will be dropped.
+ ///
+ /// \param TemplateArgs The set of template arguments to substitute.
+ ///
+ /// \param Outputs Will receive all of the substituted arguments.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool SubstExprs(ArrayRef<Expr *> Exprs, bool IsCall,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<Expr *> &Outputs);
+
+ StmtResult SubstStmt(Stmt *S,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool EvaluateConstraints = true);
+
+ bool
+ SubstTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateArgumentListInfo &Outputs);
+
+ Decl *SubstDecl(Decl *D, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ /// Substitute the name and return type of a defaulted 'operator<=>' to form
+ /// an implicit 'operator=='.
+ FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
+ FunctionDecl *Spaceship);
+
+ ExprResult SubstInitializer(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool CXXDirectInit);
+
+ bool
+ SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+ CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ 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);
+
+ 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
+ InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs,
+ const Decl *Pattern, Decl *Inst,
+ LateInstantiatedAttrVec *LateAttrs = nullptr,
+ LocalInstantiationScope *OuterMostScope = nullptr);
+
+ void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor);
+
+ 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);
+
+ 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 &TemplateArgList,
+ 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);
+
+ // Objective-C declarations.
+ enum ObjCContainerKind {
+ OCK_None = -1,
+ OCK_Interface = 0,
+ OCK_Protocol,
+ OCK_Category,
+ OCK_ClassExtension,
+ OCK_Implementation,
+ OCK_CategoryImplementation
+ };
+ ObjCContainerKind getObjCContainerKind() const;
+
+ DeclResult 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 ActOnForwardClassDeclaration(SourceLocation Loc,
+ IdentifierInfo **IdentList,
+ SourceLocation *IdentLocs,
+ ArrayRef<ObjCTypeParamList *> TypeParamLists,
+ unsigned NumElts);
+
+ 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);
+
+ /// 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);
+
+ /// 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);
+
+
+ void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+ ObjCPropertyDecl *SuperProperty,
+ const IdentifierInfo *Name,
+ bool OverridingProtocolProperty);
+
+ void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+ ObjCInterfaceDecl *ID);
+
+ Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
+ ArrayRef<Decl *> allMethods = std::nullopt,
+ ArrayRef<DeclGroupPtrTy> allTUVars = std::nullopt);
+
+ 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);
+
+ enum ObjCSpecialMethodKind {
+ OSMK_None,
+ OSMK_Alloc,
+ OSMK_New,
+ OSMK_Copy,
+ OSMK_RetainingInit,
+ OSMK_NonRetainingInit
+ };
+
+ struct ObjCArgInfo {
+ IdentifierInfo *Name;
+ SourceLocation NameLoc;
+ // The Type is null if no type was specified, and the DeclSpec is invalid
+ // in this case.
+ ParsedType Type;
+ ObjCDeclSpec DeclSpec;
+
+ /// ArgAttrs - Attribute list for this argument.
+ ParsedAttributesView ArgAttrs;
+ };
+
+ Decl *ActOnMethodDeclaration(
+ Scope *S,
+ SourceLocation BeginLoc, // location of the + or -.
+ SourceLocation EndLoc, // location of the ; or {.
+ tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+ ArrayRef<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);
+
+ ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
+ const ObjCObjectPointerType *OPT,
+ bool IsInstance);
+ ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
+ bool IsInstance);
+
+ bool CheckARCMethodDecl(ObjCMethodDecl *method);
+ bool inferObjCARCLifetime(ValueDecl *decl);
+
+ void deduceOpenCLAddressSpace(ValueDecl *decl);
+
+ 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);
+
+ 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
+ };
+
+ ObjCMessageKind getObjCMessageKind(Scope *S,
+ IdentifierInfo *Name,
+ SourceLocation NameLoc,
+ bool IsSuper,
+ bool HasTrailingDot,
+ ParsedType &ReceiverType);
+
+ ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ 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 BuildClassMessageImplicit(QualType ReceiverType,
+ bool isSuperReceiver,
+ SourceLocation Loc,
+ Selector Sel,
+ ObjCMethodDecl *Method,
+ MultiExprArg Args);
+
+ ExprResult ActOnClassMessage(Scope *S,
+ ParsedType Receiver,
+ Selector Sel,
+ SourceLocation LBracLoc,
+ ArrayRef<SourceLocation> SelectorLocs,
+ SourceLocation RBracLoc,
+ MultiExprArg Args);
+
+ 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);
+
+ void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr);
+
+ bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
+ CastKind &Kind);
+
+ bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
+ QualType DestType, QualType SrcType,
+ ObjCInterfaceDecl *&RelatedClass,
+ ObjCMethodDecl *&ClassMethod,
+ ObjCMethodDecl *&InstanceMethod,
+ TypedefNameDecl *&TDNDecl,
+ bool CfToNs, bool Diagnose = true);
+
+ 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);
+
+ /// Check whether the given new method is a valid override of the
+ /// given overridden method, and set any properties that should be inherited.
+ void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
+ const ObjCMethodDecl *Overridden);
+
+ /// Describes the compatibility of a result type with its method.
+ enum ResultTypeCompatibilityKind {
+ RTC_Compatible,
+ RTC_Incompatible,
+ RTC_Unknown
+ };
+
+ void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
+ ObjCMethodDecl *overridden);
+
+ void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
+ ObjCInterfaceDecl *CurrentClass,
+ ResultTypeCompatibilityKind RTC);
+
+ 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
+ };
+
+ /// 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);
+
+ enum class PragmaAlignPackDiagnoseKind {
+ NonDefaultStateAtInclude,
+ ChangedStateAtExit
+ };
+
+ 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);
+
+ /// ActOnPragmaMSComment - Called on well formed
+ /// \#pragma comment(kind, "arg").
+ void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
+ StringRef Arg);
+
+ /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
+ /// pointers_to_members(representation method[, general purpose
+ /// representation]).
+ void ActOnPragmaMSPointersToMembers(
+ LangOptions::PragmaMSPointersToMembersKind Kind,
+ SourceLocation PragmaLoc);
+
+ /// Called on well formed \#pragma vtordisp().
+ void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
+ SourceLocation PragmaLoc,
+ MSVtorDispMode Value);
+
+ enum PragmaSectionKind {
+ PSK_DataSeg,
+ PSK_BSSSeg,
+ PSK_ConstSeg,
+ PSK_CodeSeg,
+ };
+
+ bool UnifySection(StringRef SectionName, int SectionFlags,
+ NamedDecl *TheDecl);
+ 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);
+
+ /// Called on well formed \#pragma section().
+ void ActOnPragmaMSSection(SourceLocation PragmaLocation,
+ int SectionFlags, StringLiteral *SegmentName);
+
+ /// Called on well-formed \#pragma init_seg().
+ void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
+ StringLiteral *SegmentName);
+
+ /// Called on well-formed \#pragma alloc_text().
+ void ActOnPragmaMSAllocText(
+ SourceLocation PragmaLocation, StringRef Section,
+ const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>>
+ &Functions);
+
+ /// Called on #pragma clang __debug dump II
+ void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
+
+ /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
+ void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+ StringRef Value);
+
+ /// Are precise floating point semantics currently enabled?
+ bool isPreciseFPEnabled() {
+ return !CurFPFeatures.getAllowFPReassociate() &&
+ !CurFPFeatures.getNoSignedZero() &&
+ !CurFPFeatures.getAllowReciprocal() &&
+ !CurFPFeatures.getAllowApproxFunc();
+ }
+
+ void ActOnPragmaFPEvalMethod(SourceLocation Loc,
+ LangOptions::FPEvalMethodKind Value);
+
+ /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
+ void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
+ PragmaFloatControlKind Value);
+
+ /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
+ void ActOnPragmaUnused(const Token &Identifier,
+ Scope *curScope,
+ SourceLocation PragmaLoc);
+
+ /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
+ void ActOnPragmaVisibility(const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc);
+
+ NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
+ SourceLocation Loc);
+ void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W);
+
+ /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
+ void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc);
+
+ /// ActOnPragmaRedefineExtname - Called on well formed
+ /// \#pragma redefine_extname oldname newname.
+ 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,
+ SourceLocation PragmaLoc,
+ SourceLocation WeakNameLoc,
+ SourceLocation AliasNameLoc);
+
+ /// ActOnPragmaFPContract - Called on well formed
+ /// \#pragma {STDC,OPENCL} FP_CONTRACT and
+ /// \#pragma clang fp contract
+ void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
+
+ /// Called on well formed
+ /// \#pragma clang fp reassociate
+ void ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled);
+
+ /// ActOnPragmaFenvAccess - Called on well formed
+ /// \#pragma STDC FENV_ACCESS
+ void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
+
+ /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
+ void ActOnPragmaFPExceptions(SourceLocation Loc,
+ LangOptions::FPExceptionModeKind);
+
+ /// Called to set constant rounding mode for floating point operations.
+ void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
+
+ /// Called to set exception behavior for floating point operations.
+ void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
+
+ /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
+ /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
+ void AddAlignmentAttributesForRecord(RecordDecl *RD);
+
+ /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
+ void AddMsStructLayoutForRecord(RecordDecl *RD);
+
+ /// 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);
+
+ /// FreeVisContext - Deallocate and null out VisContext.
+ void FreeVisContext();
+
+ /// 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);
+
+ void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
+ SourceLocation PragmaLoc,
+ attr::ParsedSubjectMatchRuleSet Rules);
+ void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace);
+
+ /// Called on well-formed '\#pragma clang attribute pop'.
+ void ActOnPragmaAttributePop(SourceLocation PragmaLoc,
+ const IdentifierInfo *Namespace);
+
+ /// Adds the attributes that have been specified using the
+ /// '\#pragma clang attribute push' directives to the given declaration.
+ void AddPragmaAttributes(Scope *S, Decl *D);
+
+ void DiagnoseUnterminatedPragmaAttribute();
+
+ /// Called on well formed \#pragma clang optimize.
+ void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
+
+ /// #pragma optimize("[optimization-list]", on | off).
+ void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn);
+
+ /// 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;
+ }
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
+ /// declaration.
+ void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+ Expr *OE);
+
+ /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
+ /// declaration.
+ void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *ParamExpr);
+
+ /// AddAlignValueAttr - Adds an align_value attribute to a particular
+ /// declaration.
+ void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
+
+ /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
+ void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
+ StringRef Annot, MutableArrayRef<Expr *> Args);
+
+ /// 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);
+
+ /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
+ /// declaration.
+ void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *MaxThreads, Expr *MinBlocks);
+
+ /// AddModeAttr - Adds a mode attribute to a particular declaration.
+ void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,
+ bool InInstantiation = false);
+
+ void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
+ ParameterABI ABI);
+
+ enum class RetainOwnershipKind {NS, CF, OS};
+ void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
+ RetainOwnershipKind K, bool IsTemplateInstantiation);
+
+ /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
+ /// attribute to a particular declaration.
+ void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *Min, Expr *Max);
+
+ /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
+ /// particular declaration.
+ void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
+ Expr *Min, Expr *Max);
+
+ bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
+
+ //===--------------------------------------------------------------------===//
+ // C++ Coroutines TS
+ //
+ 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);
+
+ 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);
+ /// Lookup 'coroutine_traits' in std namespace and std::experimental
+ /// namespace. The namespace found is recorded in Namespace.
+ ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
+ SourceLocation FuncLoc,
+ NamespaceDecl *&Namespace);
+ /// Check that the expression co_await promise.final_suspend() shall not be
+ /// potentially-throwing.
+ bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend);
+
+ //===--------------------------------------------------------------------===//
+ // OpenMP directives and clauses.
+ //
+private:
+ void *VarDataSharingAttributesStack;
+
+ 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 'device_type' as parsed from the clause.
+ OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
+
+ /// The directive kind, `begin declare target` or `declare target`.
+ OpenMPDirectiveKind Kind;
+
+ /// The directive with indirect clause.
+ std::optional<Expr *> Indirect;
+
+ /// The directive location.
+ SourceLocation Loc;
+
+ DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc)
+ : Kind(Kind), Loc(Loc) {}
+ };
+
+ /// Number of nested '#pragma omp declare target' directives.
+ SmallVector<DeclareTargetContextInfo, 4> DeclareTargetNesting;
+
+ /// Initialization of data-sharing attributes stack.
+ void InitDataSharingAttributesStack();
+ void DestroyDataSharingAttributesStack();
+ ExprResult
+ VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
+ bool StrictlyPositive = true,
+ bool SuppressExprDiags = false);
+ /// Returns OpenMP nesting level for current directive.
+ unsigned getOpenMPNestingLevel() const;
+
+ /// Adjusts the function scopes index for the target-based regions.
+ void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
+ unsigned Level) const;
+
+ /// Returns the number of scopes associated with the construct on the given
+ /// OpenMP level.
+ int getNumberOfConstructScopes(unsigned Level) const;
+
+ /// Push new OpenMP function region for non-capturing function.
+ void pushOpenMPFunctionRegion();
+
+ /// Pop OpenMP function region for non-capturing function.
+ void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI);
+
+ /// 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);
+
+ /// Helper to keep information about the current `omp begin/end declare
+ /// variant` nesting.
+ struct OMPDeclareVariantScope {
+ /// The associated OpenMP context selector.
+ OMPTraitInfo *TI;
+
+ /// The associated OpenMP context selector mangling.
+ std::string NameSuffix;
+
+ OMPDeclareVariantScope(OMPTraitInfo &TI);
+ };
+
+ /// Return the OMPTraitInfo for the surrounding scope, if any.
+ OMPTraitInfo *getOMPTraitInfoForSurroundingScope() {
+ return OMPDeclareVariantScopes.empty() ? nullptr
+ : OMPDeclareVariantScopes.back().TI;
+ }
+
+ /// The current `omp begin/end declare variant` scopes.
+ SmallVector<OMPDeclareVariantScope, 4> OMPDeclareVariantScopes;
+
+ /// The current `omp begin/end assumes` scopes.
+ SmallVector<AssumptionAttr *, 4> OMPAssumeScoped;
+
+ /// All `omp assumes` we encountered so far.
+ SmallVector<AssumptionAttr *, 4> OMPAssumeGlobal;
+
+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);
+
+ /// 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();
+ }
+
+ /// 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();
+
+ /// 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);
+
+ /// 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);
+
+ /// 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;
+
+ /// 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;
+
+ 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);
+
+ /// 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);
+
+ /// Called on well-formed '\#pragma omp metadirective' after parsing
+ /// of the associated statement.
+ StmtResult ActOnOpenMPMetaDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ // 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);
+
+ /// Called on well-formed '#pragma omp [begin] assume[s]'.
+ void ActOnOpenMPAssumesDirective(SourceLocation Loc,
+ OpenMPDirectiveKind DKind,
+ ArrayRef<std::string> Assumptions,
+ bool SkippedClauses);
+
+ /// Check if there is an active global `omp begin assumes` directive.
+ bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); }
+
+ /// Check if there is an active global `omp assumes` directive.
+ bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); }
+
+ /// Called on well-formed '#pragma omp end assumes'.
+ void ActOnOpenMPEndAssumesDirective();
+
+ /// 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);
+
+ /// 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;
+
+ /// Called on the start of target region i.e. '#pragma omp declare target'.
+ bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
+
+ /// Called at the end of target region i.e. '#pragma omp end declare target'.
+ const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective();
+
+ /// 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);
+
+ /// Report unterminated 'omp declare target' or 'omp begin declare target' at
+ /// the end of a compilation unit.
+ void DiagnoseUnterminatedOpenMPDeclareTarget();
+
+ /// Searches for the provided declaration name for OpenMP declare target
+ /// directive.
+ NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id);
+
+ /// Called on correct id-expression from the '#pragma omp declare target'.
+ void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
+ OMPDeclareTargetDeclAttr::MapTypeTy MT,
+ DeclareTargetContextInfo &DTCI);
+
+ /// Check declaration inside target region.
+ void
+ checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+ SourceLocation IdLoc = SourceLocation());
+ /// 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);
+
+ /// Return true if currently in OpenMP task with untied clause context.
+ bool isInOpenMPTaskUntiedContext() const;
+
+ /// Return true inside OpenMP declare target region.
+ bool isInOpenMPDeclareTargetContext() const {
+ return !DeclareTargetNesting.empty();
+ }
+ /// Return true inside OpenMP target region.
+ bool isInOpenMPTargetExecutionDirective() const;
+
+ /// Return the number of captured regions created for an OpenMP directive.
+ static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
+
+ /// Initialization of captured region for OpenMP region.
+ void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
+
+ /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
+ /// an OpenMP loop directive.
+ StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
+
+ /// 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);
+
+ /// 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);
+ /// 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 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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 '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 'init' clause.
+ OMPClause *
+ ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation VarLoc, SourceLocation EndLoc);
+
+ /// Called on well-formed 'use' clause.
+ OMPClause *ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation VarLoc, SourceLocation EndLoc);
+
+ /// 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);
+
+ /// Called on well-formed 'unified_address' clause.
+ OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'reverse_offload' clause.
+ OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'dynamic_allocators' clause.
+ OMPClause *ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'atomic_default_mem_order' clause.
+ OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause(
+ OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+
+ /// Called on well-formed 'at' clause.
+ OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'severity' clause.
+ OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ /// Called on well-formed 'message' clause.
+ /// passing string for message.
+ OMPClause *ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ /// 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;
+ };
+
+ 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 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;
+ };
+ /// 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);
+
+ /// 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
+ };
+
+ static bool isCast(CheckedConversionKind CCK) {
+ return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
+ CCK == CCK_OtherCast;
+ }
+
+ /// 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);
+
+ /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
+ /// to the conversion from scalar type ScalarTy to the Boolean type.
+ static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
+
+ /// IgnoredValueConversions - Given that an expression's result is
+ /// syntactically ignored, perform any conversions that are
+ /// required.
+ ExprResult IgnoredValueConversions(Expr *E);
+
+ // 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);
+
+ /// CallExprUnaryConversions - a special case of an unary conversion
+ /// performed on a function designator of a call expression.
+ ExprResult CallExprUnaryConversions(Expr *E);
+
+ // DefaultFunctionArrayConversion - converts functions and arrays
+ // to their respective pointers (C99 6.3.2.1).
+ ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
+
+ // DefaultFunctionArrayLvalueConversion - converts functions and
+ // arrays to their respective pointers and performs the
+ // lvalue-to-rvalue conversion.
+ ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
+ bool Diagnose = true);
+
+ // 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);
+
+ // 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);
+
+ /// 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);
+
+ // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+ enum VariadicCallType {
+ VariadicFunction,
+ VariadicBlock,
+ VariadicMethod,
+ VariadicConstructor,
+ VariadicDoesNotApply
+ };
+
+ VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
+ const FunctionProtoType *Proto,
+ Expr *Fn);
+
+ // 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
+ };
+
+ // Determines which VarArgKind fits an expression.
+ VarArgKind isValidVarArgType(const QualType &Ty);
+
+ /// 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);
+
+ /// 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);
+
+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);
+
+public:
+ /// Check to see if a given expression could have '.c_str()' called on it.
+ bool hasCStrMethod(const Expr *E);
+
+ /// 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);
+
+ // 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);
+
+ /// 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,
+ };
+
+ // 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);
+
+ /// 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,
+
+ /// PointerToInt - The assignment converts a pointer to an int, which we
+ /// accept as an extension.
+ PointerToInt,
+
+ /// IntToPointer - The assignment converts an int to a pointer, which we
+ /// accept as an extension.
+ IntToPointer,
+
+ /// FunctionVoidPointer - The assignment is between a function pointer and
+ /// void*, which the standard doesn't allow, but we accept as an extension.
+ FunctionVoidPointer,
+
+ /// IncompatiblePointer - The assignment is between two pointers types that
+ /// are not compatible, but we accept them as an extension.
+ IncompatiblePointer,
+
+ /// IncompatibleFunctionPointer - The assignment is between two function
+ /// pointers types that are not compatible, but we accept them as an
+ /// extension.
+ IncompatibleFunctionPointer,
+
+ /// 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,
+
+ /// 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,
+
+ /// CompatiblePointerDiscardsQualifiers - The assignment discards
+ /// c/v/r qualifiers, which we accept as an extension.
+ CompatiblePointerDiscardsQualifiers,
+
+ /// IncompatiblePointerDiscardsQualifiers - The assignment
+ /// discards qualifiers that we don't permit to be discarded,
+ /// like address spaces.
+ IncompatiblePointerDiscardsQualifiers,
+
+ /// 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,
+
+ /// 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,
+
+ /// IncompatibleVectors - The assignment is between two vector types that
+ /// have the same size, which we accept as an extension.
+ IncompatibleVectors,
+
+ /// IntToBlockPointer - The assignment converts an int to a block
+ /// pointer. We disallow this.
+ IntToBlockPointer,
+
+ /// 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,
+
+ /// Incompatible - We reject this conversion outright, it is invalid to
+ /// represent it in the AST.
+ Incompatible
+ };
+
+ /// 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);
+
+ /// 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;
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ // 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);
+
+ bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+
+ bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ AssignmentAction Action,
+ bool AllowExplicit = false);
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ const ImplicitConversionSequence& ICS,
+ AssignmentAction Action,
+ CheckedConversionKind CCK
+ = CCK_ImplicitConversion);
+ ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+ const StandardConversionSequence& SCS,
+ AssignmentAction Action,
+ CheckedConversionKind CCK);
+
+ ExprResult PerformQualificationConversion(
+ Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
+ CheckedConversionKind CCK = CCK_ImplicitConversion);
+
+ /// the following "Check" methods will return a valid/converted QualType
+ /// or a null QualType (indicating an error diagnostic was issued).
+
+ /// 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);
+
+ 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);
+
+ 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);
+
+ 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;
+ }
+
+ QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation QuestionLoc);
+
+ bool DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
+ SourceLocation QuestionLoc);
+
+ void DiagnoseAlwaysNonNullPointer(Expr *E,
+ Expr::NullPointerConstantKind NullType,
+ bool IsEqual, SourceRange Range);
+
+ /// 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);
+
+ // type checking for sizeless vector binary operators.
+ QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc, bool IsCompAssign,
+ ArithConvKind OperationKind);
+
+ /// 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);
+
+ bool isValidSveBitcast(QualType srcType, QualType destType);
+
+ bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
+
+ bool areVectorTypesSameSize(QualType srcType, QualType destType);
+ bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
+ bool isLaxVectorConversion(QualType srcType, QualType destType);
+ bool areSameVectorElemTypes(QualType srcType, QualType destType);
+ bool anyAltivecTypes(QualType srcType, QualType destType);
+
+ /// type checking declaration initializers (C99 6.7.8)
+ bool CheckForConstantInitializer(Expr *e, QualType t);
+
+ // type checking C++ declaration initializers (C++ [dcl.init]).
+
+ /// 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
+ };
+
+ // 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,
+
+ LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime)
+ };
+ };
+ using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions;
+
+ ReferenceCompareResult
+ CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
+ ReferenceConversions *Conv = nullptr);
+
+ ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
+ Expr *CastExpr, CastKind &CastKind,
+ ExprValueKind &VK, CXXCastPath &Path);
+
+ /// Force an expression with unknown-type to an expression of the
+ /// given type.
+ ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
+
+ /// Type-check an expression that's being passed to an
+ /// __unknown_anytype parameter.
+ ExprResult checkUnknownAnyArg(SourceLocation callLoc,
+ Expr *result, QualType &paramType);
+
+ // 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);
+
+ // 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);
+
+ /// Prepare `SplattedExpr` for a vector splat operation, adding
+ /// implicit casts if necessary.
+ ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
+
+ // 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 BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type,
+ SourceLocation LParenLoc,
+ Expr *CastExpr,
+ SourceLocation RParenLoc);
+
+ enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error };
+
+ /// Checks for invalid conversions and casts between
+ /// retainable pointers and other pointer kinds for ARC and Weak.
+ ARCConversionResult CheckObjCConversion(SourceRange castRange,
+ QualType castType, Expr *&op,
+ CheckedConversionKind CCK,
+ bool Diagnose = true,
+ bool DiagnoseCFAudited = false,
+ BinaryOperatorKind Opc = BO_PtrMemD
+ );
+
+ Expr *stripARCUnbridgedCast(Expr *e);
+ void diagnoseARCUnbridgedCast(Expr *e);
+
+ 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.
+ /// \return true iff there were any incompatible types.
+ bool CheckMessageArgumentTypes(const Expr *Receiver, QualType ReceiverType,
+ MultiExprArg Args, Selector Sel,
+ ArrayRef<SourceLocation> SelectorLocs,
+ ObjCMethodDecl *Method, bool isClassMessage,
+ bool isSuperMessage, SourceLocation lbrac,
+ SourceLocation rbrac, SourceRange RecRange,
+ QualType &ReturnType, ExprValueKind &VK);
+
+ /// Determine the result of a message send expression based on
+ /// the type of the receiver, the method expected to receive the message,
+ /// and the form of the message send.
+ QualType getMessageSendResultType(const Expr *Receiver, QualType ReceiverType,
+ ObjCMethodDecl *Method, bool isClassMessage,
+ bool isSuperMessage);
+
+ /// If the given expression involves a message send to a method
+ /// with a related result type, emit a note describing what happened.
+ void EmitRelatedResultTypeNote(const Expr *E);
+
+ /// Given that we had incompatible pointer types in a return
+ /// statement, check whether we're in a method with a related result
+ /// type, and if so, emit a note describing what happened.
+ void EmitRelatedResultTypeNoteForReturn(QualType destType);
+
+ class ConditionResult {
+ Decl *ConditionVar;
+ FullExprArg Condition;
+ bool Invalid;
+ bool HasKnownValue;
+ bool KnownValue;
+
+ friend class Sema;
+ ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition,
+ bool IsConstexpr)
+ : ConditionVar(ConditionVar), Condition(Condition), Invalid(false),
+ HasKnownValue(IsConstexpr && Condition.get() &&
+ !Condition.get()->isValueDependent()),
+ KnownValue(HasKnownValue &&
+ !!Condition.get()->EvaluateKnownConstInt(S.Context)) {}
+ explicit ConditionResult(bool Invalid)
+ : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid),
+ HasKnownValue(false), KnownValue(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 {
+ if (!HasKnownValue)
+ return std::nullopt;
+ return KnownValue;
+ }
+ };
+ static ConditionResult ConditionError() { return ConditionResult(true); }
+
+ enum class ConditionKind {
+ Boolean, ///< A boolean condition, from 'if', 'while', 'for', or 'do'.
+ ConstexprIf, ///< A constant boolean condition from 'if constexpr'.
+ Switch ///< An integral condition for a 'switch' statement.
+ };
+ QualType PreferredConditionType(ConditionKind K) const {
+ return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy;
+ }
+
+ 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// DiagnoseAssignmentAsCondition - Given that an expression is
+ /// being used as a boolean condition, warn if it's an assignment.
+ void DiagnoseAssignmentAsCondition(Expr *E);
+
+ /// Redundant parentheses over an equality comparison can indicate
+ /// that the user intended an assignment used as condition.
+ void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
+
+ /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
+ ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false);
+
+ /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
+ /// the specified width and sign. If an overflow occurs, detect it and emit
+ /// the specified diagnostic.
+ void ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &OldVal,
+ unsigned NewWidth, bool NewSign,
+ SourceLocation Loc, unsigned DiagID);
+
+ /// 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) { }
+
+ virtual SemaDiagnosticBuilder
+ diagnoseNotICEType(Sema &S, SourceLocation Loc, QualType T);
+ virtual SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
+ SourceLocation Loc) = 0;
+ virtual SemaDiagnosticBuilder diagnoseFold(Sema &S, SourceLocation Loc);
+ virtual ~VerifyICEDiagnoser() {}
+ };
+
+ enum AllowFoldKind {
+ NoFold,
+ AllowFold,
+ };
+
+ /// 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);
+
+private:
+ unsigned ForceCUDAHostDeviceDepth = 0;
+
+public:
+ /// Increments our count of the number of times we've seen a pragma forcing
+ /// functions to be __host__ __device__. So long as this count is greater
+ /// than zero, all functions encountered will be __host__ __device__.
+ void PushForceCUDAHostDevice();
+
+ /// Decrements our count of the number of times we've seen a pragma forcing
+ /// functions to be __host__ __device__. Returns false if the count is 0
+ /// before incrementing, so you can emit an error.
+ bool PopForceCUDAHostDevice();
+
+ /// 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.
+ llvm::DenseMap<CanonicalDeclPtr<FunctionDecl>,
+ std::vector<PartialDiagnosticAt>>
+ DeviceDeferredDiags;
+
+ /// A pair of a canonical FunctionDecl and a SourceLocation. When used as the
+ /// key in a hashtable, both the FD and location are hashed.
+ struct FunctionDeclAndLoc {
+ CanonicalDeclPtr<FunctionDecl> FD;
+ SourceLocation Loc;
+ };
+
+ /// FunctionDecls and SourceLocations for which CheckCUDACall has emitted a
+ /// (maybe deferred) "bad call" diagnostic. We use this to avoid emitting the
+ /// same deferred diag twice.
+ llvm::DenseSet<FunctionDeclAndLoc> LocsWithCUDACallDiags;
+
+ /// An inverse call graph, mapping known-emitted functions to one of their
+ /// known-emitted callers (plus the location of the call).
+ ///
+ /// Functions that we can tell a priori must be emitted aren't added to this
+ /// map.
+ llvm::DenseMap</* Callee = */ CanonicalDeclPtr<FunctionDecl>,
+ /* Caller = */ FunctionDeclAndLoc>
+ DeviceKnownEmittedFns;
+
+ /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
+ /// context is "used as device code".
+ ///
+ /// - If CurContext is a __host__ function, does not emit any diagnostics
+ /// unless \p EmitOnBothSides is true.
+ /// - If CurContext is a __device__ or __global__ function, emits the
+ /// diagnostics immediately.
+ /// - If CurContext is a __host__ __device__ 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 CUDA device code.
+ /// if (CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget())
+ /// return ExprError();
+ /// // Otherwise, continue parsing as normal.
+ SemaDiagnosticBuilder CUDADiagIfDeviceCode(SourceLocation Loc,
+ unsigned DiagID);
+
+ /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
+ /// context is "used as host code".
+ ///
+ /// 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, 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, FunctionDecl *FD);
+
+ SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID,
+ FunctionDecl *FD = nullptr);
+ SemaDiagnosticBuilder targetDiag(SourceLocation Loc,
+ const PartialDiagnostic &PD,
+ 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);
+
+ enum CUDAFunctionTarget {
+ CFT_Device,
+ CFT_Global,
+ CFT_Host,
+ CFT_HostDevice,
+ CFT_InvalidTarget
+ };
+
+ /// Determines whether the given function is a CUDA device/host/kernel/etc.
+ /// function.
+ ///
+ /// Use this rather than examining the function's attributes yourself -- you
+ /// will get it wrong. Returns CFT_Host if D is null.
+ CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D,
+ bool IgnoreImplicitHDAttr = false);
+ CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs);
+
+ enum CUDAVariableTarget {
+ CVT_Device, /// Emitted on device side with a shadow variable on host side
+ CVT_Host, /// Emitted on host side only
+ CVT_Both, /// Emitted on both sides with different addresses
+ CVT_Unified, /// Emitted as a unified address, e.g. managed variables
+ };
+ /// Determines whether the given variable is emitted on host or device side.
+ CUDAVariableTarget IdentifyCUDATarget(const VarDecl *D);
+
+ /// Gets the CUDA target for the current context.
+ CUDAFunctionTarget CurrentCUDATarget() {
+ return IdentifyCUDATarget(dyn_cast<FunctionDecl>(CurContext));
+ }
+
+ static bool isCUDAImplicitHostDeviceFunction(const FunctionDecl *D);
+
+ // CUDA function call preference. Must be ordered numerically from
+ // worst to best.
+ enum CUDAFunctionPreference {
+ CFP_Never, // Invalid caller/callee combination.
+ CFP_WrongSide, // Calls from host-device to host or device
+ // function that do not match current compilation
+ // mode.
+ CFP_HostDevice, // Any calls to host/device functions.
+ CFP_SameSide, // Calls from host-device to host or device
+ // function matching current compilation mode.
+ CFP_Native, // host-to-host or device-to-device calls.
+ };
+
+ /// Identifies relative preference of a given Caller/Callee
+ /// combination, based on their host/device attributes.
+ /// \param Caller function which needs address of \p Callee.
+ /// nullptr in case of global context.
+ /// \param Callee target function
+ ///
+ /// \returns preference value for particular Caller/Callee combination.
+ CUDAFunctionPreference IdentifyCUDAPreference(const FunctionDecl *Caller,
+ const FunctionDecl *Callee);
+
+ /// Determines whether Caller may invoke Callee, based on their CUDA
+ /// host/device attributes. Returns false if the call is not allowed.
+ ///
+ /// Note: Will return true for CFP_WrongSide calls. These may appear in
+ /// semantically correct CUDA programs, but only if they're never codegen'ed.
+ bool IsAllowedCUDACall(const FunctionDecl *Caller,
+ const FunctionDecl *Callee) {
+ return IdentifyCUDAPreference(Caller, Callee) != CFP_Never;
+ }
+
+ /// May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD,
+ /// depending on FD and the current compilation settings.
+ void maybeAddCUDAHostDeviceAttrs(FunctionDecl *FD,
+ const LookupResult &Previous);
+
+ /// May add implicit CUDAConstantAttr attribute to VD, depending on VD
+ /// 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
+ /// (CFP_Never), emits an error and returns false.
+ ///
+ /// - If the call is allowed in semantically-correct programs, but only if
+ /// it's never codegen'ed (CFP_WrongSide), creates a deferred diagnostic to
+ /// be emitted if and when the caller is codegen'ed, and returns true.
+ ///
+ /// Will only create deferred diagnostics for a given SourceLocation once,
+ /// so you can safely call this multiple times without generating duplicate
+ /// deferred errors.
+ ///
+ /// - Otherwise, returns true without emitting any diagnostics.
+ bool CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee);
+
+ void CUDACheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture);
+
+ /// Set __device__ or __host__ __device__ attributes on the given lambda
+ /// operator() method.
+ ///
+ /// CUDA lambdas by default is host device function unless it has explicit
+ /// host or device attribute.
+ void CUDASetLambdaAttrs(CXXMethodDecl *Method);
+
+ /// Finds a function in \p Matches with highest calling priority
+ /// from \p Caller context and erases all functions with lower
+ /// calling priority.
+ void EraseUnwantedCUDAMatches(
+ const FunctionDecl *Caller,
+ SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches);
+
+ /// Given a implicit special member, infer its CUDA target from the
+ /// calls it needs to make to underlying base/field special members.
+ /// \param ClassDecl the class for which the member is being created.
+ /// \param CSM the kind of special member.
+ /// \param MemberDecl the special member itself.
+ /// \param ConstRHS true if this is a copy operation with a const object on
+ /// its RHS.
+ /// \param Diagnose true if this call should emit diagnostics.
+ /// \return true if there was an error inferring.
+ /// The result of this call is implicit CUDA target attribute(s) attached to
+ /// the member declaration.
+ bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
+ CXXSpecialMember CSM,
+ CXXMethodDecl *MemberDecl,
+ bool ConstRHS,
+ bool Diagnose);
+
+ /// \return true if \p CD can be considered empty according to CUDA
+ /// (E.2.3.1 in CUDA 7.5 Programming guide).
+ bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD);
+ bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD);
+
+ // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In
+ // case of error emits appropriate diagnostic and invalidates \p Var.
+ //
+ // \details CUDA allows only empty constructors as initializers for global
+ // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all
+ // __shared__ variables whether they are local or not (they all are implicitly
+ // static in CUDA). One exception is that CUDA allows constant initializers
+ // for __constant__ and __device__ variables.
+ void checkAllowedCUDAInitializer(VarDecl *VD);
+
+ /// Check whether NewFD is a valid overload for CUDA. Emits
+ /// diagnostics and invalidates NewFD if not.
+ void checkCUDATargetOverload(FunctionDecl *NewFD,
+ const LookupResult &Previous);
+ /// Copies target attributes from the template TD to the function FD.
+ void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD);
+
+ /// Returns the name of the launch configuration function. This is the name
+ /// of the function that will be called to configure kernel call, with the
+ /// parameters specified via <<<>>>.
+ std::string getCudaConfigureFuncName() const;
+
+ /// \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
+ };
+
+ void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
+ void CodeCompleteOrdinaryName(Scope *S,
+ ParserCompletionContext CompletionContext);
+ void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
+ bool AllowNonIdentifiers,
+ bool AllowNestedNameSpecifiers);
+
+ struct CodeCompleteExpressionData;
+ void CodeCompleteExpression(Scope *S,
+ const CodeCompleteExpressionData &Data);
+ void CodeCompleteExpression(Scope *S, QualType PreferredType,
+ bool IsParenthesized = false);
+ void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase,
+ SourceLocation OpLoc, bool IsArrow,
+ bool IsBaseExprStatement,
+ QualType PreferredType);
+ void CodeCompletePostfixExpression(Scope *S, ExprResult LHS,
+ QualType PreferredType);
+ void CodeCompleteTag(Scope *S, unsigned TagSpec);
+ void CodeCompleteTypeQualifiers(DeclSpec &DS);
+ void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
+ const VirtSpecifiers *VS = nullptr);
+ void CodeCompleteBracketDeclarator(Scope *S);
+ void CodeCompleteCase(Scope *S);
+ enum class AttributeCompletion {
+ Attribute,
+ Scope,
+ None,
+ };
+ void CodeCompleteAttribute(
+ AttributeCommonInfo::Syntax Syntax,
+ AttributeCompletion Completion = AttributeCompletion::Attribute,
+ const IdentifierInfo *Scope = nullptr);
+ /// Determines the preferred type of the current function argument, by
+ /// examining the signatures of all possible overloads.
+ /// Returns null if unknown or ambiguous, or if code completion is off.
+ ///
+ /// 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);
+
+ 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);
+
+ void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
+ bool AfterAmpersand);
+ void CodeCompleteAfterFunctionEquals(Declarator &D);
+
+ 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 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);
+ //@}
+
+ //===--------------------------------------------------------------------===//
+ // Extra semantic analysis beyond the C type system
+
+public:
+ SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+ unsigned ByteNo) const;
+
+ 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
+ };
+
+ // Used to grab the relevant information from a FormatAttr and a
+ // FunctionDeclaration.
+ struct FormatStringInfo {
+ unsigned FormatIdx;
+ unsigned FirstDataArg;
+ FormatArgumentPassingKind ArgPassingKind;
+ };
+
+ static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+ bool IsVariadic, FormatStringInfo *FSI);
+
+private:
+ void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
+ const ArraySubscriptExpr *ASE = nullptr,
+ bool AllowOnePastEnd = true, bool IndexNegated = false);
+ void CheckArrayAccess(const Expr *E);
+
+ 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);
+
+ void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
+
+ void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
+ StringRef ParamName, QualType ArgTy, QualType ParamTy);
+
+ void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
+ const Expr *ThisArg, ArrayRef<const Expr *> Args,
+ bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
+ VariadicCallType CallType);
+
+ bool CheckObjCString(Expr *Arg);
+ ExprResult CheckOSLogFormatStringArg(Expr *Arg);
+
+ ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
+ unsigned BuiltinID, CallExpr *TheCall);
+
+ bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+ CallExpr *TheCall);
+
+ void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
+
+ 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 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);
+
+ 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);
+ bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
+ unsigned BuiltinID, CallExpr *TheCall);
+
+ bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
+ bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call);
+ bool SemaBuiltinUnorderedCompare(CallExpr *TheCall);
+ bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs);
+ bool SemaBuiltinComplex(CallExpr *TheCall);
+ bool SemaBuiltinVSX(CallExpr *TheCall);
+ bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
+ bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
+
+public:
+ // Used by C++ template instantiation.
+ ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+ ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+ SourceLocation BuiltinLoc,
+ SourceLocation RParenLoc);
+
+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);
+
+ bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
+
+ bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
+ bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
+ bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);
+
+ // Matrix builtin handling.
+ ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
+ ExprResult CallResult);
+ ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
+ ExprResult CallResult);
+ ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
+ ExprResult CallResult);
+
+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);
+
+ bool FormatStringHasSArg(const StringLiteral *FExpr);
+
+ static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
+
+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);
+
+ void CheckAbsoluteValueFunction(const CallExpr *Call,
+ const FunctionDecl *FDecl);
+
+ void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
+
+ void CheckMemaccessArguments(const CallExpr *Call,
+ unsigned BId,
+ IdentifierInfo *FnName);
+
+ void CheckStrlcpycatArguments(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,
+ const AttrVec *Attrs = nullptr,
+ const FunctionDecl *FD = nullptr);
+
+public:
+ void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
+ BinaryOperatorKind Opcode);
+
+private:
+ void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+ void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
+ void CheckForIntOverflow(Expr *E);
+ void CheckUnsequencedOperations(const Expr *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);
+
+ void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
+ Expr *Init);
+
+ /// Check if there is a field shadowing.
+ void CheckShadowInheritedFields(const SourceLocation &Loc,
+ DeclarationName FieldName,
+ const CXXRecordDecl *RD,
+ bool DeclIsField = true);
+
+ /// Check if the given expression contains 'break' or 'continue'
+ /// statement that produces control flow different from GCC.
+ void CheckBreakContinueBinding(Expr *E);
+
+ /// Check whether receiver is mutable ObjC container which
+ /// attempts to add itself into the container
+ void CheckObjCCircularContainer(ObjCMessageExpr *Message);
+
+ void CheckTCBEnforcement(const SourceLocation CallExprLoc,
+ const NamedDecl *Callee);
+
+ 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);
+
+ struct TypeTagData {
+ TypeTagData() {}
+
+ TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) :
+ Type(Type), LayoutCompatible(LayoutCompatible),
+ MustBeNull(MustBeNull)
+ {}
+
+ QualType Type;
+
+ /// If true, \c Type should be compared with other expression's types for
+ /// layout-compatibility.
+ unsigned LayoutCompatible : 1;
+ unsigned MustBeNull : 1;
+ };
+
+ /// 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);
+
+ /// 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);
+
+ /// The parser's current scope.
+ ///
+ /// The parser maintains this state here.
+ Scope *CurScope;
+
+ mutable IdentifierInfo *Ident_super;
+ mutable IdentifierInfo *Ident___float128;
+
+ /// Nullability type specifiers.
+ IdentifierInfo *Ident__Nonnull = nullptr;
+ IdentifierInfo *Ident__Nullable = nullptr;
+ IdentifierInfo *Ident__Nullable_result = nullptr;
+ IdentifierInfo *Ident__Null_unspecified = nullptr;
+
+ IdentifierInfo *Ident_NSError = nullptr;
+
+ /// The handler for the FileChanged preprocessor events.
+ ///
+ /// Used for diagnostics that implement custom semantic analysis for #include
+ /// directives, like -Wpragma-pack.
+ sema::SemaPPCallbacks *SemaPPCallbackHandler;
+
+protected:
+ friend class Parser;
+ friend class InitializationSequence;
+ friend class ASTReader;
+ friend class ASTDeclReader;
+ friend class ASTWriter;
+
+public:
+ /// 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();
+
+ /// 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; }
+
+ void incrementMSManglingNumber() const {
+ return CurScope->incrementMSManglingNumber();
+ }
+
+ IdentifierInfo *getSuperIdentifier() const;
+ IdentifierInfo *getFloat128Identifier() const;
+
+ ObjCContainerDecl *getObjCDeclContext() const;
+
+ DeclContext *getCurLexicalContext() const {
+ return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
+ }
+
+ 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;
+ }
+
+ /// 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;
+
+ /// 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;
+ }
+
+ // 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();
+ }
+
+ private:
+ Sema &S;
+ decltype(DelayedOverridingExceptionSpecChecks)
+ SavedOverridingExceptionSpecChecks;
+ decltype(DelayedEquivalentExceptionSpecChecks)
+ SavedEquivalentExceptionSpecChecks;
+
+ void swapSavedState() {
+ SavedOverridingExceptionSpecChecks.swap(
+ S.DelayedOverridingExceptionSpecChecks);
+ SavedEquivalentExceptionSpecChecks.swap(
+ S.DelayedEquivalentExceptionSpecChecks);
+ }
+ };
+
+ /// Helper class that collects misaligned member designations and
+ /// their location info for delayed diagnostics.
+ struct MisalignedMember {
+ Expr *E;
+ RecordDecl *RD;
+ ValueDecl *MD;
+ CharUnits Alignment;
+
+ 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);
+
+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".
+ ///
+ /// - If CurLexicalContext is a kernel function or it is known that the
+ /// function will be emitted for the device, emits the diagnostics
+ /// immediately.
+ /// - If CurLexicalContext is a function and we are compiling
+ /// for the device, but we don't know that this function will be codegen'ed
+ /// for devive yet, creates a diagnostic which is emitted if and when we
+ /// realize that the function will be codegen'ed.
+ ///
+ /// Example usage:
+ ///
+ /// Diagnose __float128 type usage only from SYCL device code if the current
+ /// target doesn't support it
+ /// if (!S.Context.getTargetInfo().hasFloat128Type() &&
+ /// S.getLangOpts().SYCLIsDevice)
+ /// SYCLDiagIfDeviceCode(Loc, diag::err_type_unsupported) << "__float128";
+ SemaDiagnosticBuilder SYCLDiagIfDeviceCode(SourceLocation Loc,
+ unsigned DiagID);
+
+ /// Check whether we're allowed to call Callee from the current context.
+ ///
+ /// - If the call is never allowed in a semantically-correct program
+ /// emits an error and returns false.
+ ///
+ /// - If the call is allowed in semantically-correct programs, but only if
+ /// it's never codegen'ed, creates a deferred diagnostic to be emitted if
+ /// and when the caller is codegen'ed, and returns true.
+ ///
+ /// - Otherwise, returns true without emitting any diagnostics.
+ ///
+ /// Adds Callee to DeviceCallGraph if we don't know if its caller will be
+ /// codegen'ed yet.
+ bool checkSYCLDeviceFunction(SourceLocation Loc, FunctionDecl *Callee);
+ void deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
+ llvm::DenseSet<QualType> Visited,
+ ValueDecl *DeclToCheck);
+};
+
+/// RAII object that enters a new expression evaluation context.
+class EnterExpressionEvaluationContext {
+ Sema &Actions;
+ bool Entered = true;
+
+public:
+ EnterExpressionEvaluationContext(
+ Sema &Actions, Sema::ExpressionEvaluationContext NewContext,
+ Decl *LambdaContextDecl = nullptr,
+ Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext =
+ Sema::ExpressionEvaluationContextRecord::EK_Other,
+ bool ShouldEnter = true)
+ : Actions(Actions), Entered(ShouldEnter) {
+ if (Entered)
+ Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
+ ExprContext);
+ }
+ EnterExpressionEvaluationContext(
+ Sema &Actions, Sema::ExpressionEvaluationContext NewContext,
+ Sema::ReuseLambdaContextDecl_t,
+ Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext =
+ Sema::ExpressionEvaluationContextRecord::EK_Other)
+ : Actions(Actions) {
+ Actions.PushExpressionEvaluationContext(
+ NewContext, Sema::ReuseLambdaContextDecl, ExprContext);
+ }
+
+ enum InitListTag { InitList };
+ EnterExpressionEvaluationContext(Sema &Actions, InitListTag,
+ bool ShouldEnter = true)
+ : Actions(Actions), Entered(false) {
+ // In C++11 onwards, narrowing checks are performed on the contents of
+ // braced-init-lists, even when they occur within unevaluated operands.
+ // Therefore we still need to instantiate constexpr functions used in such
+ // a context.
+ if (ShouldEnter && Actions.isUnevaluatedContext() &&
+ Actions.getLangOpts().CPlusPlus11) {
+ Actions.PushExpressionEvaluationContext(
+ Sema::ExpressionEvaluationContext::UnevaluatedList);
+ Entered = true;
+ }
+ }
+
+ ~EnterExpressionEvaluationContext() {
+ if (Entered)
+ Actions.PopExpressionEvaluationContext();
+ }
+};
+
+DeductionFailureInfo
+MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK,
+ sema::TemplateDeductionInfo &Info);
+
+/// Contains a late templated function.
+/// Will be parsed at the end of the translation unit, used by Sema & Parser.
+struct LateParsedTemplate {
+ CachedTokens Toks;
+ /// The template function declaration to be late parsed.
+ Decl *D;
+};
+
+template <>
+void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation,
+ PragmaMsStackAction Action,
+ llvm::StringRef StackSlotLabel,
+ AlignPackInfo Value);
+
+std::unique_ptr<sema::RISCVIntrinsicManager>
+CreateRISCVIntrinsicManager(Sema &S);
+} // end namespace clang
+
+namespace llvm {
+// Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its
+// SourceLocation.
+template <> struct DenseMapInfo<clang::Sema::FunctionDeclAndLoc> {
+ using FunctionDeclAndLoc = clang::Sema::FunctionDeclAndLoc;
+ using FDBaseInfo = DenseMapInfo<clang::CanonicalDeclPtr<clang::FunctionDecl>>;
+
+ static FunctionDeclAndLoc getEmptyKey() {
+ return {FDBaseInfo::getEmptyKey(), clang::SourceLocation()};
+ }
+
+ static FunctionDeclAndLoc getTombstoneKey() {
+ return {FDBaseInfo::getTombstoneKey(), clang::SourceLocation()};
+ }
+
+ static unsigned getHashValue(const FunctionDeclAndLoc &FDL) {
+ return hash_combine(FDBaseInfo::getHashValue(FDL.FD),
+ FDL.Loc.getHashValue());
+ }
+
+ static bool isEqual(const FunctionDeclAndLoc &LHS,
+ const FunctionDeclAndLoc &RHS) {
+ return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc;
+ }
+};
+} // namespace llvm
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/SemaConcept.h b/contrib/libs/clang16/include/clang/Sema/SemaConcept.h
new file mode 100644
index 0000000000..12dd0d6c91
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/SemaConcept.h
@@ -0,0 +1,166 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===-- SemaConcept.h - Semantic Analysis for Constraints and Concepts ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+// This file provides semantic analysis for C++ constraints and concepts.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMACONCEPT_H
+#define LLVM_CLANG_SEMA_SEMACONCEPT_H
+#include "clang/AST/ASTConcept.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include <optional>
+#include <string>
+#include <utility>
+
+namespace clang {
+class Sema;
+
+struct AtomicConstraint {
+ const Expr *ConstraintExpr;
+ std::optional<ArrayRef<TemplateArgumentLoc>> ParameterMapping;
+
+ AtomicConstraint(Sema &S, const Expr *ConstraintExpr) :
+ ConstraintExpr(ConstraintExpr) { };
+
+ bool hasMatchingParameterMapping(ASTContext &C,
+ const AtomicConstraint &Other) const {
+ if (!ParameterMapping != !Other.ParameterMapping)
+ return false;
+ if (!ParameterMapping)
+ return true;
+ if (ParameterMapping->size() != Other.ParameterMapping->size())
+ return false;
+
+ for (unsigned I = 0, S = ParameterMapping->size(); I < S; ++I) {
+ llvm::FoldingSetNodeID IDA, IDB;
+ C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
+ .Profile(IDA, C);
+ C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
+ .Profile(IDB, C);
+ if (IDA != IDB)
+ return false;
+ }
+ return true;
+ }
+
+ bool subsumes(ASTContext &C, const AtomicConstraint &Other) const {
+ // C++ [temp.constr.order] p2
+ // - an atomic constraint A subsumes another atomic constraint B
+ // if and only if the A and B are identical [...]
+ //
+ // C++ [temp.constr.atomic] p2
+ // Two atomic constraints are identical if they are formed from the
+ // same expression and the targets of the parameter mappings are
+ // equivalent according to the rules for expressions [...]
+
+ // We do not actually substitute the parameter mappings into the
+ // constraint expressions, therefore the constraint expressions are
+ // the originals, and comparing them will suffice.
+ if (ConstraintExpr != Other.ConstraintExpr)
+ return false;
+
+ // Check that the parameter lists are identical
+ return hasMatchingParameterMapping(C, Other);
+ }
+};
+
+/// \brief A normalized constraint, as defined in C++ [temp.constr.normal], is
+/// either an atomic constraint, a conjunction of normalized constraints or a
+/// disjunction of normalized constraints.
+struct NormalizedConstraint {
+ friend class Sema;
+
+ enum CompoundConstraintKind { CCK_Conjunction, CCK_Disjunction };
+
+ using CompoundConstraint = llvm::PointerIntPair<
+ std::pair<NormalizedConstraint, NormalizedConstraint> *, 1,
+ CompoundConstraintKind>;
+
+ llvm::PointerUnion<AtomicConstraint *, CompoundConstraint> Constraint;
+
+ NormalizedConstraint(AtomicConstraint *C): Constraint{C} { };
+ NormalizedConstraint(ASTContext &C, NormalizedConstraint LHS,
+ NormalizedConstraint RHS, CompoundConstraintKind Kind)
+ : Constraint{CompoundConstraint{
+ new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
+ std::move(LHS), std::move(RHS)}, Kind}} { };
+
+ NormalizedConstraint(ASTContext &C, const NormalizedConstraint &Other) {
+ if (Other.isAtomic()) {
+ Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
+ } else {
+ Constraint = CompoundConstraint(
+ new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
+ NormalizedConstraint(C, Other.getLHS()),
+ NormalizedConstraint(C, Other.getRHS())},
+ Other.getCompoundKind());
+ }
+ }
+ NormalizedConstraint(NormalizedConstraint &&Other):
+ Constraint(Other.Constraint) {
+ Other.Constraint = nullptr;
+ }
+ NormalizedConstraint &operator=(const NormalizedConstraint &Other) = delete;
+ NormalizedConstraint &operator=(NormalizedConstraint &&Other) {
+ if (&Other != this) {
+ NormalizedConstraint Temp(std::move(Other));
+ std::swap(Constraint, Temp.Constraint);
+ }
+ return *this;
+ }
+
+ CompoundConstraintKind getCompoundKind() const {
+ assert(!isAtomic() && "getCompoundKind called on atomic constraint.");
+ return Constraint.get<CompoundConstraint>().getInt();
+ }
+
+ bool isAtomic() const { return Constraint.is<AtomicConstraint *>(); }
+
+ NormalizedConstraint &getLHS() const {
+ assert(!isAtomic() && "getLHS called on atomic constraint.");
+ return Constraint.get<CompoundConstraint>().getPointer()->first;
+ }
+
+ NormalizedConstraint &getRHS() const {
+ assert(!isAtomic() && "getRHS called on atomic constraint.");
+ return Constraint.get<CompoundConstraint>().getPointer()->second;
+ }
+
+ AtomicConstraint *getAtomicConstraint() const {
+ assert(isAtomic() &&
+ "getAtomicConstraint called on non-atomic constraint.");
+ return Constraint.get<AtomicConstraint *>();
+ }
+
+private:
+ static std::optional<NormalizedConstraint>
+ fromConstraintExprs(Sema &S, NamedDecl *D, ArrayRef<const Expr *> E);
+ static std::optional<NormalizedConstraint>
+ fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E);
+};
+
+} // clang
+
+#endif // LLVM_CLANG_SEMA_SEMACONCEPT_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/SemaConsumer.h b/contrib/libs/clang16/include/clang/Sema/SemaConsumer.h
new file mode 100644
index 0000000000..ca42099f68
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/SemaConsumer.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- SemaConsumer.h - Abstract interface for AST semantics --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the SemaConsumer class, a subclass of
+// ASTConsumer that is used by AST clients that also require
+// additional semantic analysis.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_SEMACONSUMER_H
+#define LLVM_CLANG_SEMA_SEMACONSUMER_H
+
+#include "clang/AST/ASTConsumer.h"
+
+namespace clang {
+ class Sema;
+
+ /// An abstract interface that should be implemented by
+ /// clients that read ASTs and then require further semantic
+ /// analysis of the entities in those ASTs.
+ class SemaConsumer : public ASTConsumer {
+ virtual void anchor();
+ public:
+ SemaConsumer() {
+ ASTConsumer::SemaConsumer = true;
+ }
+
+ /// Initialize the semantic consumer with the Sema instance
+ /// being used to perform semantic analysis on the abstract syntax
+ /// tree.
+ virtual void InitializeSema(Sema &S) {}
+
+ /// Inform the semantic consumer that Sema is no longer available.
+ virtual void ForgetSema() {}
+
+ // isa/cast/dyn_cast support
+ static bool classof(const ASTConsumer *Consumer) {
+ return Consumer->SemaConsumer;
+ }
+ };
+}
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/SemaDiagnostic.h b/contrib/libs/clang16/include/clang/Sema/SemaDiagnostic.h
new file mode 100644
index 0000000000..149af51256
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/SemaDiagnostic.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- DiagnosticSema.h - Diagnostics for libsema -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMADIAGNOSTIC_H
+#define LLVM_CLANG_SEMA_SEMADIAGNOSTIC_H
+
+#include "clang/Basic/DiagnosticSema.h"
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/SemaFixItUtils.h b/contrib/libs/clang16/include/clang/Sema/SemaFixItUtils.h
new file mode 100644
index 0000000000..d84583dd41
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/SemaFixItUtils.h
@@ -0,0 +1,101 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- SemaFixItUtils.h - Sema FixIts -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines helper classes for generation of Sema FixItHints.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SEMA_SEMAFIXITUTILS_H
+#define LLVM_CLANG_SEMA_SEMAFIXITUTILS_H
+
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+enum OverloadFixItKind {
+ OFIK_Undefined = 0,
+ OFIK_Dereference,
+ OFIK_TakeAddress,
+ OFIK_RemoveDereference,
+ OFIK_RemoveTakeAddress
+};
+
+class Sema;
+
+/// The class facilities generation and storage of conversion FixIts. Hints for
+/// new conversions are added using TryToFixConversion method. The default type
+/// conversion checker can be reset.
+struct ConversionFixItGenerator {
+ /// Performs a simple check to see if From type can be converted to To type.
+ static bool compareTypesSimple(CanQualType From,
+ CanQualType To,
+ Sema &S,
+ SourceLocation Loc,
+ ExprValueKind FromVK);
+
+ /// The list of Hints generated so far.
+ std::vector<FixItHint> Hints;
+
+ /// The number of Conversions fixed. This can be different from the size
+ /// of the Hints vector since we allow multiple FixIts per conversion.
+ unsigned NumConversionsFixed;
+
+ /// The type of fix applied. If multiple conversions are fixed, corresponds
+ /// to the kid of the very first conversion.
+ OverloadFixItKind Kind;
+
+ typedef bool (*TypeComparisonFuncTy) (const CanQualType FromTy,
+ const CanQualType ToTy,
+ Sema &S,
+ SourceLocation Loc,
+ ExprValueKind FromVK);
+ /// The type comparison function used to decide if expression FromExpr of
+ /// type FromTy can be converted to ToTy. For example, one could check if
+ /// an implicit conversion exists. Returns true if comparison exists.
+ TypeComparisonFuncTy CompareTypes;
+
+ ConversionFixItGenerator(TypeComparisonFuncTy Foo): NumConversionsFixed(0),
+ Kind(OFIK_Undefined),
+ CompareTypes(Foo) {}
+
+ ConversionFixItGenerator(): NumConversionsFixed(0),
+ Kind(OFIK_Undefined),
+ CompareTypes(compareTypesSimple) {}
+
+ /// Resets the default conversion checker method.
+ void setConversionChecker(TypeComparisonFuncTy Foo) {
+ CompareTypes = Foo;
+ }
+
+ /// If possible, generates and stores a fix for the given conversion.
+ bool tryToFixConversion(const Expr *FromExpr,
+ const QualType FromQTy, const QualType ToQTy,
+ Sema &S);
+
+ void clear() {
+ Hints.clear();
+ NumConversionsFixed = 0;
+ }
+
+ bool isNull() {
+ return (NumConversionsFixed == 0);
+ }
+};
+
+} // endof namespace clang
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/SemaInternal.h b/contrib/libs/clang16/include/clang/Sema/SemaInternal.h
new file mode 100644
index 0000000000..009c1a7a29
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/SemaInternal.h
@@ -0,0 +1,348 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- SemaInternal.h - Internal Sema Interfaces --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides common API and #includes for the internal
+// implementation of Sema.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMAINTERNAL_H
+#define LLVM_CLANG_SEMA_SEMAINTERNAL_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+namespace clang {
+
+inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {
+ return PartialDiagnostic(DiagID, Context.getDiagAllocator());
+}
+
+inline bool
+FTIHasSingleVoidParameter(const DeclaratorChunk::FunctionTypeInfo &FTI) {
+ return FTI.NumParams == 1 && !FTI.isVariadic &&
+ FTI.Params[0].Ident == nullptr && FTI.Params[0].Param &&
+ cast<ParmVarDecl>(FTI.Params[0].Param)->getType()->isVoidType();
+}
+
+inline bool
+FTIHasNonVoidParameters(const DeclaratorChunk::FunctionTypeInfo &FTI) {
+ // Assume FTI is well-formed.
+ return FTI.NumParams && !FTIHasSingleVoidParameter(FTI);
+}
+
+// Helper function to check whether D's attributes match current CUDA mode.
+// Decls with mismatched attributes and related diagnostics may have to be
+// ignored during this CUDA compilation pass.
+inline bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D) {
+ if (!LangOpts.CUDA || !D)
+ return true;
+ bool isDeviceSideDecl = D->hasAttr<CUDADeviceAttr>() ||
+ D->hasAttr<CUDASharedAttr>() ||
+ D->hasAttr<CUDAGlobalAttr>();
+ return isDeviceSideDecl == LangOpts.CUDAIsDevice;
+}
+
+/// Return a DLL attribute from the declaration.
+inline InheritableAttr *getDLLAttr(Decl *D) {
+ assert(!(D->hasAttr<DLLImportAttr>() && D->hasAttr<DLLExportAttr>()) &&
+ "A declaration cannot be both dllimport and dllexport.");
+ if (auto *Import = D->getAttr<DLLImportAttr>())
+ return Import;
+ if (auto *Export = D->getAttr<DLLExportAttr>())
+ return Export;
+ return nullptr;
+}
+
+/// Retrieve the depth and index of a template parameter.
+inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) {
+ if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ const auto *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
+/// Retrieve the depth and index of an unexpanded parameter pack.
+inline std::pair<unsigned, unsigned>
+getDepthAndIndex(UnexpandedParameterPack UPP) {
+ if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>())
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ return getDepthAndIndex(UPP.first.get<NamedDecl *>());
+}
+
+class TypoCorrectionConsumer : public VisibleDeclConsumer {
+ typedef SmallVector<TypoCorrection, 1> TypoResultList;
+ typedef llvm::StringMap<TypoResultList> TypoResultsMap;
+ typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
+
+public:
+ TypoCorrectionConsumer(Sema &SemaRef,
+ const DeclarationNameInfo &TypoName,
+ Sema::LookupNameKind LookupKind,
+ Scope *S, CXXScopeSpec *SS,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ DeclContext *MemberContext,
+ bool EnteringContext)
+ : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0),
+ SavedTCIndex(0), SemaRef(SemaRef), S(S),
+ SS(SS ? std::make_unique<CXXScopeSpec>(*SS) : nullptr),
+ CorrectionValidator(std::move(CCC)), MemberContext(MemberContext),
+ Result(SemaRef, TypoName, LookupKind),
+ Namespaces(SemaRef.Context, SemaRef.CurContext, SS),
+ EnteringContext(EnteringContext), SearchNamespaces(false) {
+ Result.suppressDiagnostics();
+ // Arrange for ValidatedCorrections[0] to always be an empty correction.
+ ValidatedCorrections.push_back(TypoCorrection());
+ }
+
+ bool includeHiddenDecls() const override { return true; }
+
+ // Methods for adding potential corrections to the consumer.
+ void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+ bool InBaseClass) override;
+ void FoundName(StringRef Name);
+ void addKeywordResult(StringRef Keyword);
+ void addCorrection(TypoCorrection Correction);
+
+ bool empty() const {
+ return CorrectionResults.empty() && ValidatedCorrections.size() == 1;
+ }
+
+ /// Return the list of TypoCorrections for the given identifier from
+ /// the set of corrections that have the closest edit distance, if any.
+ TypoResultList &operator[](StringRef Name) {
+ return CorrectionResults.begin()->second[Name];
+ }
+
+ /// Return the edit distance of the corrections that have the
+ /// closest/best edit distance from the original typop.
+ unsigned getBestEditDistance(bool Normalized) {
+ if (CorrectionResults.empty())
+ return (std::numeric_limits<unsigned>::max)();
+
+ unsigned BestED = CorrectionResults.begin()->first;
+ return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED;
+ }
+
+ /// Set-up method to add to the consumer the set of namespaces to use
+ /// in performing corrections to nested name specifiers. This method also
+ /// implicitly adds all of the known classes in the current AST context to the
+ /// to the consumer for correcting nested name specifiers.
+ void
+ addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces);
+
+ /// Return the next typo correction that passes all internal filters
+ /// and is deemed valid by the consumer's CorrectionCandidateCallback,
+ /// starting with the corrections that have the closest edit distance. An
+ /// empty TypoCorrection is returned once no more viable corrections remain
+ /// in the consumer.
+ const TypoCorrection &getNextCorrection();
+
+ /// Get the last correction returned by getNextCorrection().
+ const TypoCorrection &getCurrentCorrection() {
+ return CurrentTCIndex < ValidatedCorrections.size()
+ ? ValidatedCorrections[CurrentTCIndex]
+ : ValidatedCorrections[0]; // The empty correction.
+ }
+
+ /// Return the next typo correction like getNextCorrection, but keep
+ /// the internal state pointed to the current correction (i.e. the next time
+ /// getNextCorrection is called, it will return the same correction returned
+ /// by peekNextcorrection).
+ const TypoCorrection &peekNextCorrection() {
+ auto Current = CurrentTCIndex;
+ const TypoCorrection &TC = getNextCorrection();
+ CurrentTCIndex = Current;
+ return TC;
+ }
+
+ /// In the case of deeply invalid expressions, `getNextCorrection()` will
+ /// never be called since the transform never makes progress. If we don't
+ /// detect this we risk trying to correct typos forever.
+ bool hasMadeAnyCorrectionProgress() const { return CurrentTCIndex != 0; }
+
+ /// Reset the consumer's position in the stream of viable corrections
+ /// (i.e. getNextCorrection() will return each of the previously returned
+ /// corrections in order before returning any new corrections).
+ void resetCorrectionStream() {
+ CurrentTCIndex = 0;
+ }
+
+ /// Return whether the end of the stream of corrections has been
+ /// reached.
+ bool finished() {
+ return CorrectionResults.empty() &&
+ CurrentTCIndex >= ValidatedCorrections.size();
+ }
+
+ /// Save the current position in the correction stream (overwriting any
+ /// previously saved position).
+ void saveCurrentPosition() {
+ SavedTCIndex = CurrentTCIndex;
+ }
+
+ /// Restore the saved position in the correction stream.
+ void restoreSavedPosition() {
+ CurrentTCIndex = SavedTCIndex;
+ }
+
+ ASTContext &getContext() const { return SemaRef.Context; }
+ const LookupResult &getLookupResult() const { return Result; }
+
+ bool isAddressOfOperand() const { return CorrectionValidator->IsAddressOfOperand; }
+ const CXXScopeSpec *getSS() const { return SS.get(); }
+ Scope *getScope() const { return S; }
+ CorrectionCandidateCallback *getCorrectionValidator() const {
+ return CorrectionValidator.get();
+ }
+
+private:
+ class NamespaceSpecifierSet {
+ struct SpecifierInfo {
+ DeclContext* DeclCtx;
+ NestedNameSpecifier* NameSpecifier;
+ unsigned EditDistance;
+ };
+
+ typedef SmallVector<DeclContext*, 4> DeclContextList;
+ typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList;
+
+ ASTContext &Context;
+ DeclContextList CurContextChain;
+ std::string CurNameSpecifier;
+ SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers;
+ SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers;
+
+ std::map<unsigned, SpecifierInfoList> DistanceMap;
+
+ /// Helper for building the list of DeclContexts between the current
+ /// context and the top of the translation unit
+ static DeclContextList buildContextChain(DeclContext *Start);
+
+ unsigned buildNestedNameSpecifier(DeclContextList &DeclChain,
+ NestedNameSpecifier *&NNS);
+
+ public:
+ NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext,
+ CXXScopeSpec *CurScopeSpec);
+
+ /// Add the DeclContext (a namespace or record) to the set, computing
+ /// the corresponding NestedNameSpecifier and its distance in the process.
+ void addNameSpecifier(DeclContext *Ctx);
+
+ /// Provides flat iteration over specifiers, sorted by distance.
+ class iterator
+ : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag,
+ SpecifierInfo> {
+ /// Always points to the last element in the distance map.
+ const std::map<unsigned, SpecifierInfoList>::iterator OuterBack;
+ /// Iterator on the distance map.
+ std::map<unsigned, SpecifierInfoList>::iterator Outer;
+ /// Iterator on an element in the distance map.
+ SpecifierInfoList::iterator Inner;
+
+ public:
+ iterator(NamespaceSpecifierSet &Set, bool IsAtEnd)
+ : OuterBack(std::prev(Set.DistanceMap.end())),
+ Outer(Set.DistanceMap.begin()),
+ Inner(!IsAtEnd ? Outer->second.begin() : OuterBack->second.end()) {
+ assert(!Set.DistanceMap.empty());
+ }
+
+ iterator &operator++() {
+ ++Inner;
+ if (Inner == Outer->second.end() && Outer != OuterBack) {
+ ++Outer;
+ Inner = Outer->second.begin();
+ }
+ return *this;
+ }
+
+ SpecifierInfo &operator*() { return *Inner; }
+ bool operator==(const iterator &RHS) const { return Inner == RHS.Inner; }
+ };
+
+ iterator begin() { return iterator(*this, /*IsAtEnd=*/false); }
+ iterator end() { return iterator(*this, /*IsAtEnd=*/true); }
+ };
+
+ void addName(StringRef Name, NamedDecl *ND,
+ NestedNameSpecifier *NNS = nullptr, bool isKeyword = false);
+
+ /// Find any visible decls for the given typo correction candidate.
+ /// If none are found, it to the set of candidates for which qualified lookups
+ /// will be performed to find possible nested name specifier changes.
+ bool resolveCorrection(TypoCorrection &Candidate);
+
+ /// Perform qualified lookups on the queued set of typo correction
+ /// candidates and add the nested name specifier changes to each candidate if
+ /// a lookup succeeds (at which point the candidate will be returned to the
+ /// main pool of potential corrections).
+ void performQualifiedLookups();
+
+ /// The name written that is a typo in the source.
+ IdentifierInfo *Typo;
+
+ /// The results found that have the smallest edit distance
+ /// found (so far) with the typo name.
+ ///
+ /// The pointer value being set to the current DeclContext indicates
+ /// whether there is a keyword with this name.
+ TypoEditDistanceMap CorrectionResults;
+
+ SmallVector<TypoCorrection, 4> ValidatedCorrections;
+ size_t CurrentTCIndex;
+ size_t SavedTCIndex;
+
+ Sema &SemaRef;
+ Scope *S;
+ std::unique_ptr<CXXScopeSpec> SS;
+ std::unique_ptr<CorrectionCandidateCallback> CorrectionValidator;
+ DeclContext *MemberContext;
+ LookupResult Result;
+ NamespaceSpecifierSet Namespaces;
+ SmallVector<TypoCorrection, 2> QualifiedResults;
+ bool EnteringContext;
+ bool SearchNamespaces;
+};
+
+inline Sema::TypoExprState::TypoExprState() {}
+
+inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) noexcept {
+ *this = std::move(other);
+}
+
+inline Sema::TypoExprState &Sema::TypoExprState::
+operator=(Sema::TypoExprState &&other) noexcept {
+ Consumer = std::move(other.Consumer);
+ DiagHandler = std::move(other.DiagHandler);
+ RecoveryHandler = std::move(other.RecoveryHandler);
+ return *this;
+}
+
+} // end namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/SemaLambda.h b/contrib/libs/clang16/include/clang/Sema/SemaLambda.h
new file mode 100644
index 0000000000..095024f23c
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/SemaLambda.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file provides some common utility functions for processing
+/// Lambdas.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMALAMBDA_H
+#define LLVM_CLANG_SEMA_SEMALAMBDA_H
+
+#include "clang/AST/ASTLambda.h"
+#include <optional>
+
+namespace clang {
+namespace sema {
+class FunctionScopeInfo;
+}
+class Sema;
+
+/// Examines the FunctionScopeInfo stack to determine the nearest
+/// enclosing lambda (to the current lambda) that is 'capture-capable' for
+/// the variable referenced in the current lambda (i.e. \p VarToCapture).
+/// If successful, returns the index into Sema's FunctionScopeInfo stack
+/// of the capture-capable lambda's LambdaScopeInfo.
+/// See Implementation for more detailed comments.
+
+std::optional<unsigned> getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
+ ValueDecl *VarToCapture, Sema &S);
+
+} // clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Template.h b/contrib/libs/clang16/include/clang/Sema/Template.h
new file mode 100644
index 0000000000..0eba6e7528
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Template.h
@@ -0,0 +1,713 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//===----------------------------------------------------------------------===//
+//
+// This file provides types used in the semantic analysis of C++ templates.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
+#define LLVM_CLANG_SEMA_TEMPLATE_H
+
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <optional>
+#include <utility>
+
+namespace clang {
+
+class ASTContext;
+class BindingDecl;
+class CXXMethodDecl;
+class Decl;
+class DeclaratorDecl;
+class DeclContext;
+class EnumDecl;
+class FunctionDecl;
+class NamedDecl;
+class ParmVarDecl;
+class TagDecl;
+class TypedefNameDecl;
+class TypeSourceInfo;
+class VarDecl;
+
+/// The kind of template substitution being performed.
+enum class TemplateSubstitutionKind : char {
+ /// We are substituting template parameters for template arguments in order
+ /// to form a template specialization.
+ Specialization,
+ /// We are substituting template parameters for (typically) other template
+ /// parameters in order to rewrite a declaration as a different declaration
+ /// (for example, when forming a deduction guide from a constructor).
+ Rewrite,
+};
+
+ /// Data structure that captures multiple levels of template argument
+ /// lists for use in template instantiation.
+ ///
+ /// Multiple levels of template arguments occur when instantiating the
+ /// definitions of member templates. For example:
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct X {
+ /// template<T Value>
+ /// struct Y {
+ /// void f();
+ /// };
+ /// };
+ /// \endcode
+ ///
+ /// When instantiating X<int>::Y<17>::f, the multi-level template argument
+ /// list will contain a template argument list (int) at depth 0 and a
+ /// template argument list (17) at depth 1.
+ class MultiLevelTemplateArgumentList {
+ /// The template argument list at a certain template depth
+
+ using ArgList = ArrayRef<TemplateArgument>;
+ struct ArgumentListLevel {
+ llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
+ ArgList Args;
+ };
+ using ContainerType = SmallVector<ArgumentListLevel, 4>;
+
+ using ArgListsIterator = ContainerType::iterator;
+ using ConstArgListsIterator = ContainerType::const_iterator;
+
+ /// The template argument lists, stored from the innermost template
+ /// argument list (first) to the outermost template argument list (last).
+ ContainerType TemplateArgumentLists;
+
+ /// The number of outer levels of template arguments that are not
+ /// being substituted.
+ unsigned NumRetainedOuterLevels = 0;
+
+ /// The kind of substitution described by this argument list.
+ TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization;
+
+ public:
+ /// Construct an empty set of template argument lists.
+ MultiLevelTemplateArgumentList() = default;
+
+ /// Construct a single-level template argument list.
+ MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) {
+ addOuterTemplateArguments(D, Args, Final);
+ }
+
+ void setKind(TemplateSubstitutionKind K) { Kind = K; }
+
+ /// Determine the kind of template substitution being performed.
+ TemplateSubstitutionKind getKind() const { return Kind; }
+
+ /// Determine whether we are rewriting template parameters rather than
+ /// substituting for them. If so, we should not leave references to the
+ /// original template parameters behind.
+ bool isRewrite() const {
+ return Kind == TemplateSubstitutionKind::Rewrite;
+ }
+
+ /// Determine the number of levels in this template argument
+ /// list.
+ unsigned getNumLevels() const {
+ return TemplateArgumentLists.size() + NumRetainedOuterLevels;
+ }
+
+ /// Determine the number of substituted levels in this template
+ /// argument list.
+ unsigned getNumSubstitutedLevels() const {
+ return TemplateArgumentLists.size();
+ }
+
+ // Determine the number of substituted args at 'Depth'.
+ unsigned getNumSubsitutedArgs(unsigned Depth) const {
+ assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
+ return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size();
+ }
+
+ unsigned getNumRetainedOuterLevels() const {
+ return NumRetainedOuterLevels;
+ }
+
+ /// Determine how many of the \p OldDepth outermost template parameter
+ /// lists would be removed by substituting these arguments.
+ unsigned getNewDepth(unsigned OldDepth) const {
+ if (OldDepth < NumRetainedOuterLevels)
+ return OldDepth;
+ if (OldDepth < getNumLevels())
+ return NumRetainedOuterLevels;
+ return OldDepth - TemplateArgumentLists.size();
+ }
+
+ /// Retrieve the template argument at a given depth and index.
+ const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
+ assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
+ assert(Index <
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
+ return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index];
+ }
+
+ /// A template-like entity which owns the whole pattern being substituted.
+ /// This will usually own a set of template parameters, or in some
+ /// cases might even be a template parameter itself.
+ std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const {
+ assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
+ auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
+ .AssociatedDeclAndFinal;
+ return {AD.getPointer(), AD.getInt()};
+ }
+
+ /// Determine whether there is a non-NULL template argument at the
+ /// given depth and index.
+ ///
+ /// There must exist a template argument list at the given depth.
+ bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
+ assert(Depth < getNumLevels());
+
+ if (Depth < NumRetainedOuterLevels)
+ return false;
+
+ if (Index >=
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
+ return false;
+
+ return !(*this)(Depth, Index).isNull();
+ }
+
+ bool isAnyArgInstantiationDependent() const {
+ for (ArgumentListLevel ListLevel : TemplateArgumentLists)
+ for (const TemplateArgument &TA : ListLevel.Args)
+ if (TA.isInstantiationDependent())
+ return true;
+ return false;
+ }
+
+ /// Clear out a specific template argument.
+ void setArgument(unsigned Depth, unsigned Index,
+ TemplateArgument Arg) {
+ assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
+ assert(Index <
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
+ const_cast<TemplateArgument &>(
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
+ }
+
+ /// Add a new outmost level to the multi-level template argument
+ /// list.
+ /// A 'Final' substitution means that Subst* nodes won't be built
+ /// for the replacements.
+ void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
+ bool Final) {
+ assert(!NumRetainedOuterLevels &&
+ "substituted args outside retained args?");
+ assert(getKind() == TemplateSubstitutionKind::Specialization);
+ TemplateArgumentLists.push_back(
+ {{AssociatedDecl->getCanonicalDecl(), Final}, Args});
+ }
+
+ void addOuterTemplateArguments(ArgList Args) {
+ assert(!NumRetainedOuterLevels &&
+ "substituted args outside retained args?");
+ assert(getKind() == TemplateSubstitutionKind::Rewrite);
+ TemplateArgumentLists.push_back({{}, Args});
+ }
+
+ void addOuterTemplateArguments(std::nullopt_t) {
+ assert(!NumRetainedOuterLevels &&
+ "substituted args outside retained args?");
+ TemplateArgumentLists.push_back({});
+ }
+
+ /// Replaces the current 'innermost' level with the provided argument list.
+ /// This is useful for type deduction cases where we need to get the entire
+ /// list from the AST, but then add the deduced innermost list.
+ void replaceInnermostTemplateArguments(ArgList Args) {
+ assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?");
+ TemplateArgumentLists[0].Args = Args;
+ }
+
+ /// Add an outermost level that we are not substituting. We have no
+ /// arguments at this level, and do not remove it from the depth of inner
+ /// template parameters that we instantiate.
+ void addOuterRetainedLevel() {
+ ++NumRetainedOuterLevels;
+ }
+ void addOuterRetainedLevels(unsigned Num) {
+ NumRetainedOuterLevels += Num;
+ }
+
+ /// Retrieve the innermost template argument list.
+ const ArgList &getInnermost() const {
+ return TemplateArgumentLists.front().Args;
+ }
+ /// Retrieve the outermost template argument list.
+ const ArgList &getOutermost() const {
+ return TemplateArgumentLists.back().Args;
+ }
+ ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
+ ConstArgListsIterator begin() const {
+ return TemplateArgumentLists.begin();
+ }
+ ArgListsIterator end() { return TemplateArgumentLists.end(); }
+ ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+ };
+
+ /// The context in which partial ordering of function templates occurs.
+ enum TPOC {
+ /// Partial ordering of function templates for a function call.
+ TPOC_Call,
+
+ /// Partial ordering of function templates for a call to a
+ /// conversion function.
+ TPOC_Conversion,
+
+ /// Partial ordering of function templates in other contexts, e.g.,
+ /// taking the address of a function template or matching a function
+ /// template specialization to a function template.
+ TPOC_Other
+ };
+
+ // This is lame but unavoidable in a world without forward
+ // declarations of enums. The alternatives are to either pollute
+ // Sema.h (by including this file) or sacrifice type safety (by
+ // making Sema.h declare things as enums).
+ class TemplatePartialOrderingContext {
+ TPOC Value;
+
+ public:
+ TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
+
+ operator TPOC() const { return Value; }
+ };
+
+ /// Captures a template argument whose value has been deduced
+ /// via c++ template argument deduction.
+ class DeducedTemplateArgument : public TemplateArgument {
+ /// For a non-type template argument, whether the value was
+ /// deduced from an array bound.
+ bool DeducedFromArrayBound = false;
+
+ public:
+ DeducedTemplateArgument() = default;
+
+ DeducedTemplateArgument(const TemplateArgument &Arg,
+ bool DeducedFromArrayBound = false)
+ : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {}
+
+ /// Construct an integral non-type template argument that
+ /// has been deduced, possibly from an array bound.
+ DeducedTemplateArgument(ASTContext &Ctx,
+ const llvm::APSInt &Value,
+ QualType ValueType,
+ bool DeducedFromArrayBound)
+ : TemplateArgument(Ctx, Value, ValueType),
+ DeducedFromArrayBound(DeducedFromArrayBound) {}
+
+ /// For a non-type template argument, determine whether the
+ /// template argument was deduced from an array bound.
+ bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
+
+ /// Specify whether the given non-type template argument
+ /// was deduced from an array bound.
+ void setDeducedFromArrayBound(bool Deduced) {
+ DeducedFromArrayBound = Deduced;
+ }
+ };
+
+ /// A stack-allocated class that identifies which local
+ /// variable declaration instantiations are present in this scope.
+ ///
+ /// A new instance of this class type will be created whenever we
+ /// instantiate a new function declaration, which will have its own
+ /// set of parameter declarations.
+ class LocalInstantiationScope {
+ public:
+ /// A set of declarations.
+ using DeclArgumentPack = SmallVector<VarDecl *, 4>;
+
+ private:
+ /// Reference to the semantic analysis that is performing
+ /// this template instantiation.
+ Sema &SemaRef;
+
+ using LocalDeclsMap =
+ llvm::SmallDenseMap<const Decl *,
+ llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
+
+ /// A mapping from local declarations that occur
+ /// within a template to their instantiations.
+ ///
+ /// This mapping is used during instantiation to keep track of,
+ /// e.g., function parameter and variable declarations. For example,
+ /// given:
+ ///
+ /// \code
+ /// template<typename T> T add(T x, T y) { return x + y; }
+ /// \endcode
+ ///
+ /// when we instantiate add<int>, we will introduce a mapping from
+ /// the ParmVarDecl for 'x' that occurs in the template to the
+ /// instantiated ParmVarDecl for 'x'.
+ ///
+ /// For a parameter pack, the local instantiation scope may contain a
+ /// set of instantiated parameters. This is stored as a DeclArgumentPack
+ /// pointer.
+ LocalDeclsMap LocalDecls;
+
+ /// The set of argument packs we've allocated.
+ SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
+
+ /// The outer scope, which contains local variable
+ /// definitions from some other instantiation (that may not be
+ /// relevant to this particular scope).
+ LocalInstantiationScope *Outer;
+
+ /// Whether we have already exited this scope.
+ bool Exited = false;
+
+ /// Whether to combine this scope with the outer scope, such that
+ /// lookup will search our outer scope.
+ bool CombineWithOuterScope;
+
+ /// If non-NULL, the template parameter pack that has been
+ /// partially substituted per C++0x [temp.arg.explicit]p9.
+ NamedDecl *PartiallySubstitutedPack = nullptr;
+
+ /// If \c PartiallySubstitutedPack is non-null, the set of
+ /// explicitly-specified template arguments in that pack.
+ const TemplateArgument *ArgsInPartiallySubstitutedPack;
+
+ /// If \c PartiallySubstitutedPack, the number of
+ /// explicitly-specified template arguments in
+ /// ArgsInPartiallySubstitutedPack.
+ unsigned NumArgsInPartiallySubstitutedPack;
+
+ public:
+ LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
+ : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
+ CombineWithOuterScope(CombineWithOuterScope) {
+ SemaRef.CurrentInstantiationScope = this;
+ }
+
+ LocalInstantiationScope(const LocalInstantiationScope &) = delete;
+ LocalInstantiationScope &
+ operator=(const LocalInstantiationScope &) = delete;
+
+ ~LocalInstantiationScope() {
+ Exit();
+ }
+
+ const Sema &getSema() const { return SemaRef; }
+
+ /// Exit this local instantiation scope early.
+ void Exit() {
+ if (Exited)
+ return;
+
+ for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
+ delete ArgumentPacks[I];
+
+ SemaRef.CurrentInstantiationScope = Outer;
+ Exited = true;
+ }
+
+ /// Clone this scope, and all outer scopes, down to the given
+ /// outermost scope.
+ LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
+ if (this == Outermost) return this;
+
+ // Save the current scope from SemaRef since the LocalInstantiationScope
+ // will overwrite it on construction
+ LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope;
+
+ LocalInstantiationScope *newScope =
+ new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
+
+ newScope->Outer = nullptr;
+ if (Outer)
+ newScope->Outer = Outer->cloneScopes(Outermost);
+
+ newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
+ newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
+ newScope->NumArgsInPartiallySubstitutedPack =
+ NumArgsInPartiallySubstitutedPack;
+
+ for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
+ I != E; ++I) {
+ const Decl *D = I->first;
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
+ newScope->LocalDecls[D];
+ if (I->second.is<Decl *>()) {
+ Stored = I->second.get<Decl *>();
+ } else {
+ DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>();
+ DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
+ Stored = NewPack;
+ newScope->ArgumentPacks.push_back(NewPack);
+ }
+ }
+ // Restore the saved scope to SemaRef
+ SemaRef.CurrentInstantiationScope = oldScope;
+ return newScope;
+ }
+
+ /// deletes the given scope, and all outer scopes, down to the
+ /// given outermost scope.
+ static void deleteScopes(LocalInstantiationScope *Scope,
+ LocalInstantiationScope *Outermost) {
+ while (Scope && Scope != Outermost) {
+ LocalInstantiationScope *Out = Scope->Outer;
+ delete Scope;
+ Scope = Out;
+ }
+ }
+
+ /// Find the instantiation of the declaration D within the current
+ /// instantiation scope.
+ ///
+ /// \param D The declaration whose instantiation we are searching for.
+ ///
+ /// \returns A pointer to the declaration or argument pack of declarations
+ /// to which the declaration \c D is instantiated, if found. Otherwise,
+ /// returns NULL.
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *
+ findInstantiationOf(const Decl *D);
+
+ void InstantiatedLocal(const Decl *D, Decl *Inst);
+ void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
+ void MakeInstantiatedLocalArgPack(const Decl *D);
+
+ /// Note that the given parameter pack has been partially substituted
+ /// via explicit specification of template arguments
+ /// (C++0x [temp.arg.explicit]p9).
+ ///
+ /// \param Pack The parameter pack, which will always be a template
+ /// parameter pack.
+ ///
+ /// \param ExplicitArgs The explicitly-specified template arguments provided
+ /// for this parameter pack.
+ ///
+ /// \param NumExplicitArgs The number of explicitly-specified template
+ /// arguments provided for this parameter pack.
+ void SetPartiallySubstitutedPack(NamedDecl *Pack,
+ const TemplateArgument *ExplicitArgs,
+ unsigned NumExplicitArgs);
+
+ /// Reset the partially-substituted pack when it is no longer of
+ /// interest.
+ void ResetPartiallySubstitutedPack() {
+ assert(PartiallySubstitutedPack && "No partially-substituted pack");
+ PartiallySubstitutedPack = nullptr;
+ ArgsInPartiallySubstitutedPack = nullptr;
+ NumArgsInPartiallySubstitutedPack = 0;
+ }
+
+ /// Retrieve the partially-substitued template parameter pack.
+ ///
+ /// If there is no partially-substituted parameter pack, returns NULL.
+ NamedDecl *
+ getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
+ unsigned *NumExplicitArgs = nullptr) const;
+
+ /// Determine whether D is a pack expansion created in this scope.
+ bool isLocalPackExpansion(const Decl *D);
+ };
+
+ class TemplateDeclInstantiator
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *>
+ {
+ Sema &SemaRef;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
+ DeclContext *Owner;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
+ Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
+ LocalInstantiationScope *StartingScope = nullptr;
+ bool EvaluateConstraints = true;
+
+ /// A list of out-of-line class template partial
+ /// specializations that will need to be instantiated after the
+ /// enclosing class's instantiation is complete.
+ SmallVector<std::pair<ClassTemplateDecl *,
+ ClassTemplatePartialSpecializationDecl *>, 4>
+ OutOfLinePartialSpecs;
+
+ /// A list of out-of-line variable template partial
+ /// specializations that will need to be instantiated after the
+ /// enclosing variable's instantiation is complete.
+ /// FIXME: Verify that this is needed.
+ SmallVector<
+ std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
+ OutOfLineVarPartialSpecs;
+
+ public:
+ TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs)
+ : SemaRef(SemaRef),
+ SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
+ Owner(Owner), TemplateArgs(TemplateArgs) {}
+
+ void setEvaluateConstraints(bool B) {
+ EvaluateConstraints = B;
+ }
+ bool getEvaluateConstraints() {
+ return EvaluateConstraints;
+ }
+
+// Define all the decl visitors using DeclNodes.inc
+#define DECL(DERIVED, BASE) \
+ Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
+#define ABSTRACT_DECL(DECL)
+
+// Decls which never appear inside a class or function.
+#define OBJCCONTAINER(DERIVED, BASE)
+#define FILESCOPEASM(DERIVED, BASE)
+#define TOPLEVELSTMT(DERIVED, BASE)
+#define IMPORT(DERIVED, BASE)
+#define EXPORT(DERIVED, BASE)
+#define LINKAGESPEC(DERIVED, BASE)
+#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
+#define OBJCMETHOD(DERIVED, BASE)
+#define OBJCTYPEPARAM(DERIVED, BASE)
+#define OBJCIVAR(DERIVED, BASE)
+#define OBJCPROPERTY(DERIVED, BASE)
+#define OBJCPROPERTYIMPL(DERIVED, BASE)
+#define EMPTY(DERIVED, BASE)
+#define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)
+
+ // Decls which use special-case instantiation code.
+#define BLOCK(DERIVED, BASE)
+#define CAPTURED(DERIVED, BASE)
+#define IMPLICITPARAM(DERIVED, BASE)
+
+#include "clang/AST/DeclNodes.inc"
+
+ enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual };
+
+ void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T,
+ TypeSourceInfo *&TInfo,
+ DeclarationNameInfo &NameInfo);
+
+ // A few supplemental visitor functions.
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams,
+ std::optional<const ASTTemplateArgumentListInfo *>
+ ClassScopeSpecializationArgs = std::nullopt,
+ RewriteKind RK = RewriteKind::None);
+ Decl *VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams,
+ RewriteKind RK = RewriteKind::None);
+ Decl *VisitDecl(Decl *D);
+ Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate,
+ ArrayRef<BindingDecl *> *Bindings = nullptr);
+ Decl *VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst,
+ LookupResult *Lookup);
+
+ // Enable late instantiation of attributes. Late instantiated attributes
+ // will be stored in LA.
+ void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
+ LateAttrs = LA;
+ StartingScope = SemaRef.CurrentInstantiationScope;
+ }
+
+ // Disable late instantiation of attributes.
+ void disableLateAttributeInstantiation() {
+ LateAttrs = nullptr;
+ StartingScope = nullptr;
+ }
+
+ LocalInstantiationScope *getStartingScope() const { return StartingScope; }
+
+ using delayed_partial_spec_iterator = SmallVectorImpl<std::pair<
+ ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator;
+
+ using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair<
+ VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator;
+
+ /// Return an iterator to the beginning of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_begin() {
+ return OutOfLinePartialSpecs.begin();
+ }
+
+ delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
+ return OutOfLineVarPartialSpecs.begin();
+ }
+
+ /// Return an iterator to the end of the set of
+ /// "delayed" partial specializations, which must be passed to
+ /// InstantiateClassTemplatePartialSpecialization once the class
+ /// definition has been completed.
+ delayed_partial_spec_iterator delayed_partial_spec_end() {
+ return OutOfLinePartialSpecs.end();
+ }
+
+ delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
+ return OutOfLineVarPartialSpecs.end();
+ }
+
+ // Helper functions for instantiating methods.
+ TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
+ SmallVectorImpl<ParmVarDecl *> &Params);
+ bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
+ bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
+
+ bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl);
+
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *List);
+
+ bool SubstQualifier(const DeclaratorDecl *OldDecl,
+ DeclaratorDecl *NewDecl);
+ bool SubstQualifier(const TagDecl *OldDecl,
+ TagDecl *NewDecl);
+
+ Decl *VisitVarTemplateSpecializationDecl(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ ArrayRef<TemplateArgument> Converted,
+ VarTemplateSpecializationDecl *PrevDecl = nullptr);
+
+ Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
+ ClassTemplatePartialSpecializationDecl *
+ InstantiateClassTemplatePartialSpecialization(
+ ClassTemplateDecl *ClassTemplate,
+ ClassTemplatePartialSpecializationDecl *PartialSpec);
+ VarTemplatePartialSpecializationDecl *
+ InstantiateVarTemplatePartialSpecialization(
+ VarTemplateDecl *VarTemplate,
+ VarTemplatePartialSpecializationDecl *PartialSpec);
+ void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
+
+ private:
+ template<typename T>
+ Decl *instantiateUnresolvedUsingDecl(T *D,
+ bool InstantiatingPackElement = false);
+ };
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_TEMPLATE_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/TemplateDeduction.h b/contrib/libs/clang16/include/clang/Sema/TemplateDeduction.h
new file mode 100644
index 0000000000..b7c52f477b
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/TemplateDeduction.h
@@ -0,0 +1,386 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides types used with Sema's template argument deduction
+// routines.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
+#define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
+
+#include "clang/Sema/Ownership.h"
+#include "clang/Sema/SemaConcept.h"
+#include "clang/AST/ASTConcept.h"
+#include "clang/AST/DeclAccessPair.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <cstddef>
+#include <optional>
+#include <utility>
+
+namespace clang {
+
+class Decl;
+struct DeducedPack;
+class Sema;
+
+namespace sema {
+
+/// Provides information about an attempted template argument
+/// deduction, whose success or failure was described by a
+/// TemplateDeductionResult value.
+class TemplateDeductionInfo {
+ /// The deduced template argument list.
+ TemplateArgumentList *DeducedSugared = nullptr, *DeducedCanonical = nullptr;
+
+ /// The source location at which template argument
+ /// deduction is occurring.
+ SourceLocation Loc;
+
+ /// Have we suppressed an error during deduction?
+ bool HasSFINAEDiagnostic = false;
+
+ /// The template parameter depth for which we're performing deduction.
+ unsigned DeducedDepth;
+
+ /// The number of parameters with explicitly-specified template arguments,
+ /// up to and including the partially-specified pack (if any).
+ unsigned ExplicitArgs = 0;
+
+ /// Warnings (and follow-on notes) that were suppressed due to
+ /// SFINAE while performing template argument deduction.
+ SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
+
+public:
+ TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth = 0)
+ : Loc(Loc), DeducedDepth(DeducedDepth) {}
+ TemplateDeductionInfo(const TemplateDeductionInfo &) = delete;
+ TemplateDeductionInfo &operator=(const TemplateDeductionInfo &) = delete;
+
+ enum ForBaseTag { ForBase };
+ /// Create temporary template deduction info for speculatively deducing
+ /// against a base class of an argument's type.
+ TemplateDeductionInfo(ForBaseTag, const TemplateDeductionInfo &Info)
+ : DeducedSugared(Info.DeducedSugared), Loc(Info.Loc),
+ DeducedDepth(Info.DeducedDepth), ExplicitArgs(Info.ExplicitArgs) {}
+
+ /// Returns the location at which template argument is
+ /// occurring.
+ SourceLocation getLocation() const {
+ return Loc;
+ }
+
+ /// The depth of template parameters for which deduction is being
+ /// performed.
+ unsigned getDeducedDepth() const {
+ return DeducedDepth;
+ }
+
+ /// Get the number of explicitly-specified arguments.
+ unsigned getNumExplicitArgs() const {
+ return ExplicitArgs;
+ }
+
+ /// Take ownership of the deduced template argument lists.
+ TemplateArgumentList *takeSugared() {
+ TemplateArgumentList *Result = DeducedSugared;
+ DeducedSugared = nullptr;
+ return Result;
+ }
+ TemplateArgumentList *takeCanonical() {
+ TemplateArgumentList *Result = DeducedCanonical;
+ DeducedCanonical = nullptr;
+ return Result;
+ }
+
+ /// Take ownership of the SFINAE diagnostic.
+ void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
+ assert(HasSFINAEDiagnostic);
+ PD.first = SuppressedDiagnostics.front().first;
+ PD.second.swap(SuppressedDiagnostics.front().second);
+ clearSFINAEDiagnostic();
+ }
+
+ /// Discard any SFINAE diagnostics.
+ void clearSFINAEDiagnostic() {
+ SuppressedDiagnostics.clear();
+ HasSFINAEDiagnostic = false;
+ }
+
+ /// Peek at the SFINAE diagnostic.
+ const PartialDiagnosticAt &peekSFINAEDiagnostic() const {
+ assert(HasSFINAEDiagnostic);
+ return SuppressedDiagnostics.front();
+ }
+
+ /// Provide an initial template argument list that contains the
+ /// explicitly-specified arguments.
+ void setExplicitArgs(TemplateArgumentList *NewDeducedSugared,
+ TemplateArgumentList *NewDeducedCanonical) {
+ assert(NewDeducedSugared->size() == NewDeducedCanonical->size());
+ DeducedSugared = NewDeducedSugared;
+ DeducedCanonical = NewDeducedCanonical;
+ ExplicitArgs = DeducedSugared->size();
+ }
+
+ /// Provide a new template argument list that contains the
+ /// results of template argument deduction.
+ void reset(TemplateArgumentList *NewDeducedSugared,
+ TemplateArgumentList *NewDeducedCanonical) {
+ DeducedSugared = NewDeducedSugared;
+ DeducedCanonical = NewDeducedCanonical;
+ }
+
+ /// Is a SFINAE diagnostic available?
+ bool hasSFINAEDiagnostic() const {
+ return HasSFINAEDiagnostic;
+ }
+
+ /// Set the diagnostic which caused the SFINAE failure.
+ void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) {
+ // Only collect the first diagnostic.
+ if (HasSFINAEDiagnostic)
+ return;
+ SuppressedDiagnostics.clear();
+ SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
+ HasSFINAEDiagnostic = true;
+ }
+
+ /// Add a new diagnostic to the set of diagnostics
+ void addSuppressedDiagnostic(SourceLocation Loc,
+ PartialDiagnostic PD) {
+ if (HasSFINAEDiagnostic)
+ return;
+ SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
+ }
+
+ /// Iterator over the set of suppressed diagnostics.
+ using diag_iterator = SmallVectorImpl<PartialDiagnosticAt>::const_iterator;
+
+ /// Returns an iterator at the beginning of the sequence of suppressed
+ /// diagnostics.
+ diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
+
+ /// Returns an iterator at the end of the sequence of suppressed
+ /// diagnostics.
+ diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
+
+ /// The template parameter to which a template argument
+ /// deduction failure refers.
+ ///
+ /// Depending on the result of template argument deduction, this
+ /// template parameter may have different meanings:
+ ///
+ /// TDK_Incomplete: this is the first template parameter whose
+ /// corresponding template argument was not deduced.
+ ///
+ /// TDK_IncompletePack: this is the expanded parameter pack for
+ /// which we deduced too few arguments.
+ ///
+ /// TDK_Inconsistent: this is the template parameter for which
+ /// two different template argument values were deduced.
+ TemplateParameter Param;
+
+ /// The first template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// Depending on the result of the template argument deduction,
+ /// this template argument may have different meanings:
+ ///
+ /// TDK_IncompletePack: this is the number of arguments we deduced
+ /// for the pack.
+ ///
+ /// TDK_Inconsistent: this argument is the first value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_SubstitutionFailure: this argument is the template
+ /// argument we were instantiating when we encountered an error.
+ ///
+ /// TDK_DeducedMismatch: this is the parameter type, after substituting
+ /// deduced arguments.
+ ///
+ /// TDK_NonDeducedMismatch: this is the component of the 'parameter'
+ /// of the deduction, directly provided in the source code.
+ TemplateArgument FirstArg;
+
+ /// The second template argument to which the template
+ /// argument deduction failure refers.
+ ///
+ /// TDK_Inconsistent: this argument is the second value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_DeducedMismatch: this is the (adjusted) call argument type.
+ ///
+ /// TDK_NonDeducedMismatch: this is the mismatching component of the
+ /// 'argument' of the deduction, from which we are deducing arguments.
+ ///
+ /// FIXME: Finish documenting this.
+ TemplateArgument SecondArg;
+
+ /// The index of the function argument that caused a deduction
+ /// failure.
+ ///
+ /// TDK_DeducedMismatch: this is the index of the argument that had a
+ /// different argument type from its substituted parameter type.
+ unsigned CallArgIndex = 0;
+
+ /// Information on packs that we're currently expanding.
+ ///
+ /// FIXME: This should be kept internal to SemaTemplateDeduction.
+ SmallVector<DeducedPack *, 8> PendingDeducedPacks;
+
+ /// \brief The constraint satisfaction details resulting from the associated
+ /// constraints satisfaction tests.
+ ConstraintSatisfaction AssociatedConstraintsSatisfaction;
+};
+
+} // namespace sema
+
+/// A structure used to record information about a failed
+/// template argument deduction, for diagnosis.
+struct DeductionFailureInfo {
+ /// A Sema::TemplateDeductionResult.
+ unsigned Result : 8;
+
+ /// Indicates whether a diagnostic is stored in Diagnostic.
+ unsigned HasDiagnostic : 1;
+
+ /// Opaque pointer containing additional data about
+ /// this deduction failure.
+ void *Data;
+
+ /// A diagnostic indicating why deduction failed.
+ alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)];
+
+ /// Retrieve the diagnostic which caused this deduction failure,
+ /// if any.
+ PartialDiagnosticAt *getSFINAEDiagnostic();
+
+ /// Retrieve the template parameter this deduction failure
+ /// refers to, if any.
+ TemplateParameter getTemplateParameter();
+
+ /// Retrieve the template argument list associated with this
+ /// deduction failure, if any.
+ TemplateArgumentList *getTemplateArgumentList();
+
+ /// Return the first template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getFirstArg();
+
+ /// Return the second template argument this deduction failure
+ /// refers to, if any.
+ const TemplateArgument *getSecondArg();
+
+ /// Return the index of the call argument that this deduction
+ /// failure refers to, if any.
+ std::optional<unsigned> getCallArgIndex();
+
+ /// Free any memory associated with this deduction failure.
+ void Destroy();
+};
+
+/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
+/// which keeps track of template argument deduction failure info, when
+/// handling explicit specializations (and instantiations) of templates
+/// beyond function overloading.
+/// For now, assume that the candidates are non-matching specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidate.
+struct TemplateSpecCandidate {
+ /// The declaration that was looked up, together with its access.
+ /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl.
+ DeclAccessPair FoundDecl;
+
+ /// Specialization - The actual specialization that this candidate
+ /// represents. When NULL, this may be a built-in candidate.
+ Decl *Specialization;
+
+ /// Template argument deduction info
+ DeductionFailureInfo DeductionFailure;
+
+ void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) {
+ FoundDecl = Found;
+ Specialization = Spec;
+ DeductionFailure = Info;
+ }
+
+ /// Diagnose a template argument deduction failure.
+ void NoteDeductionFailure(Sema &S, bool ForTakingAddress);
+};
+
+/// TemplateSpecCandidateSet - A set of generalized overload candidates,
+/// used in template specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidateSet.
+class TemplateSpecCandidateSet {
+ SmallVector<TemplateSpecCandidate, 16> Candidates;
+ SourceLocation Loc;
+
+ // Stores whether we're taking the address of these candidates. This helps us
+ // produce better error messages when dealing with the pass_object_size
+ // attribute on parameters.
+ bool ForTakingAddress;
+
+ void destroyCandidates();
+
+public:
+ TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false)
+ : Loc(Loc), ForTakingAddress(ForTakingAddress) {}
+ TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete;
+ TemplateSpecCandidateSet &
+ operator=(const TemplateSpecCandidateSet &) = delete;
+ ~TemplateSpecCandidateSet() { destroyCandidates(); }
+
+ SourceLocation getLocation() const { return Loc; }
+
+ /// Clear out all of the candidates.
+ /// TODO: This may be unnecessary.
+ void clear();
+
+ using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator;
+
+ iterator begin() { return Candidates.begin(); }
+ iterator end() { return Candidates.end(); }
+
+ size_t size() const { return Candidates.size(); }
+ bool empty() const { return Candidates.empty(); }
+
+ /// Add a new candidate with NumConversions conversion sequence slots
+ /// to the overload set.
+ TemplateSpecCandidate &addCandidate() {
+ Candidates.emplace_back();
+ return Candidates.back();
+ }
+
+ void NoteCandidates(Sema &S, SourceLocation Loc);
+
+ void NoteCandidates(Sema &S, SourceLocation Loc) const {
+ const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/TemplateInstCallback.h b/contrib/libs/clang16/include/clang/Sema/TemplateInstCallback.h
new file mode 100644
index 0000000000..79ae05ba06
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/TemplateInstCallback.h
@@ -0,0 +1,93 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- TemplateInstCallback.h - Template Instantiation Callback - C++ --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// This file defines the TemplateInstantiationCallback class, which is the
+// base class for callbacks that will be notified at template instantiations.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TEMPLATEINSTCALLBACK_H
+#define LLVM_CLANG_SEMA_TEMPLATEINSTCALLBACK_H
+
+#include "clang/Sema/Sema.h"
+
+namespace clang {
+
+/// This is a base class for callbacks that will be notified at every
+/// template instantiation.
+class TemplateInstantiationCallback {
+public:
+ virtual ~TemplateInstantiationCallback() = default;
+
+ /// Called before doing AST-parsing.
+ virtual void initialize(const Sema &TheSema) = 0;
+
+ /// Called after AST-parsing is completed.
+ virtual void finalize(const Sema &TheSema) = 0;
+
+ /// Called when instantiation of a template just began.
+ virtual void atTemplateBegin(const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) = 0;
+
+ /// Called when instantiation of a template is just about to end.
+ virtual void atTemplateEnd(const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) = 0;
+};
+
+template <class TemplateInstantiationCallbackPtrs>
+void initialize(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->initialize(TheSema);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void finalize(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->finalize(TheSema);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void atTemplateBegin(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->atTemplateBegin(TheSema, Inst);
+ }
+}
+
+template <class TemplateInstantiationCallbackPtrs>
+void atTemplateEnd(TemplateInstantiationCallbackPtrs &Callbacks,
+ const Sema &TheSema,
+ const Sema::CodeSynthesisContext &Inst) {
+ for (auto &C : Callbacks) {
+ if (C)
+ C->atTemplateEnd(TheSema, Inst);
+ }
+}
+
+} // namespace clang
+
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/TypoCorrection.h b/contrib/libs/clang16/include/clang/Sema/TypoCorrection.h
new file mode 100644
index 0000000000..378d9c04f7
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/TypoCorrection.h
@@ -0,0 +1,429 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- TypoCorrection.h - Class for typo correction results -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TypoCorrection class, which stores the results of
+// Sema's typo correction (Sema::CorrectTypo).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H
+#define LLVM_CLANG_SEMA_TYPOCORRECTION_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/DeclSpec.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Casting.h"
+#include <cstddef>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace clang {
+
+class DeclContext;
+class IdentifierInfo;
+class LangOptions;
+class MemberExpr;
+class NestedNameSpecifier;
+class Sema;
+
+/// Simple class containing the result of Sema::CorrectTypo
+class TypoCorrection {
+public:
+ // "Distance" for unusable corrections
+ static const unsigned InvalidDistance = std::numeric_limits<unsigned>::max();
+
+ // The largest distance still considered valid (larger edit distances are
+ // mapped to InvalidDistance by getEditDistance).
+ static const unsigned MaximumDistance = 10000U;
+
+ // Relative weightings of the "edit distance" components. The higher the
+ // weight, the more of a penalty to fitness the component will give (higher
+ // weights mean greater contribution to the total edit distance, with the
+ // best correction candidates having the lowest edit distance).
+ static const unsigned CharDistanceWeight = 100U;
+ static const unsigned QualifierDistanceWeight = 110U;
+ static const unsigned CallbackDistanceWeight = 150U;
+
+ TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
+ NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0,
+ unsigned QualifierDistance = 0)
+ : CorrectionName(Name), CorrectionNameSpec(NNS),
+ CharDistance(CharDistance), QualifierDistance(QualifierDistance) {
+ if (NameDecl)
+ CorrectionDecls.push_back(NameDecl);
+ }
+
+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr,
+ unsigned CharDistance = 0)
+ : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
+ CharDistance(CharDistance) {
+ if (Name)
+ CorrectionDecls.push_back(Name);
+ }
+
+ TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr,
+ unsigned CharDistance = 0)
+ : CorrectionName(Name), CorrectionNameSpec(NNS),
+ CharDistance(CharDistance) {}
+
+ TypoCorrection() = default;
+
+ /// Gets the DeclarationName of the typo correction
+ DeclarationName getCorrection() const { return CorrectionName; }
+
+ IdentifierInfo *getCorrectionAsIdentifierInfo() const {
+ return CorrectionName.getAsIdentifierInfo();
+ }
+
+ /// Gets the NestedNameSpecifier needed to use the typo correction
+ NestedNameSpecifier *getCorrectionSpecifier() const {
+ return CorrectionNameSpec;
+ }
+
+ void setCorrectionSpecifier(NestedNameSpecifier *NNS) {
+ CorrectionNameSpec = NNS;
+ ForceSpecifierReplacement = (NNS != nullptr);
+ }
+
+ void WillReplaceSpecifier(bool ForceReplacement) {
+ ForceSpecifierReplacement = ForceReplacement;
+ }
+
+ bool WillReplaceSpecifier() const {
+ return ForceSpecifierReplacement;
+ }
+
+ void setQualifierDistance(unsigned ED) {
+ QualifierDistance = ED;
+ }
+
+ void setCallbackDistance(unsigned ED) {
+ CallbackDistance = ED;
+ }
+
+ // Convert the given weighted edit distance to a roughly equivalent number of
+ // single-character edits (typically for comparison to the length of the
+ // string being edited).
+ static unsigned NormalizeEditDistance(unsigned ED) {
+ if (ED > MaximumDistance)
+ return InvalidDistance;
+ return (ED + CharDistanceWeight / 2) / CharDistanceWeight;
+ }
+
+ /// Gets the "edit distance" of the typo correction from the typo.
+ /// If Normalized is true, scale the distance down by the CharDistanceWeight
+ /// to return the edit distance in terms of single-character edits.
+ unsigned getEditDistance(bool Normalized = true) const {
+ if (CharDistance > MaximumDistance || QualifierDistance > MaximumDistance ||
+ CallbackDistance > MaximumDistance)
+ return InvalidDistance;
+ unsigned ED =
+ CharDistance * CharDistanceWeight +
+ QualifierDistance * QualifierDistanceWeight +
+ CallbackDistance * CallbackDistanceWeight;
+ if (ED > MaximumDistance)
+ return InvalidDistance;
+ // Half the CharDistanceWeight is added to ED to simulate rounding since
+ // integer division truncates the value (i.e. round-to-nearest-int instead
+ // of round-to-zero).
+ return Normalized ? NormalizeEditDistance(ED) : ED;
+ }
+
+ /// Get the correction declaration found by name lookup (before we
+ /// looked through using shadow declarations and the like).
+ NamedDecl *getFoundDecl() const {
+ return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr;
+ }
+
+ /// Gets the pointer to the declaration of the typo correction
+ NamedDecl *getCorrectionDecl() const {
+ auto *D = getFoundDecl();
+ return D ? D->getUnderlyingDecl() : nullptr;
+ }
+ template <class DeclClass>
+ DeclClass *getCorrectionDeclAs() const {
+ return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
+ }
+
+ /// Clears the list of NamedDecls.
+ void ClearCorrectionDecls() {
+ CorrectionDecls.clear();
+ }
+
+ /// Clears the list of NamedDecls before adding the new one.
+ void setCorrectionDecl(NamedDecl *CDecl) {
+ CorrectionDecls.clear();
+ addCorrectionDecl(CDecl);
+ }
+
+ /// Clears the list of NamedDecls and adds the given set.
+ void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) {
+ CorrectionDecls.clear();
+ CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end());
+ }
+
+ /// Add the given NamedDecl to the list of NamedDecls that are the
+ /// declarations associated with the DeclarationName of this TypoCorrection
+ void addCorrectionDecl(NamedDecl *CDecl);
+
+ std::string getAsString(const LangOptions &LO) const;
+
+ std::string getQuoted(const LangOptions &LO) const {
+ return "'" + getAsString(LO) + "'";
+ }
+
+ /// Returns whether this TypoCorrection has a non-empty DeclarationName
+ explicit operator bool() const { return bool(CorrectionName); }
+
+ /// Mark this TypoCorrection as being a keyword.
+ /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be
+ /// added to the list of the correction's NamedDecl pointers, NULL is added
+ /// as the only element in the list to mark this TypoCorrection as a keyword.
+ void makeKeyword() {
+ CorrectionDecls.clear();
+ CorrectionDecls.push_back(nullptr);
+ ForceSpecifierReplacement = true;
+ }
+
+ // Check if this TypoCorrection is a keyword by checking if the first
+ // item in CorrectionDecls is NULL.
+ bool isKeyword() const {
+ return !CorrectionDecls.empty() && CorrectionDecls.front() == nullptr;
+ }
+
+ // Check if this TypoCorrection is the given keyword.
+ template<std::size_t StrLen>
+ bool isKeyword(const char (&Str)[StrLen]) const {
+ return isKeyword() && getCorrectionAsIdentifierInfo()->isStr(Str);
+ }
+
+ // Returns true if the correction either is a keyword or has a known decl.
+ bool isResolved() const { return !CorrectionDecls.empty(); }
+
+ bool isOverloaded() const {
+ return CorrectionDecls.size() > 1;
+ }
+
+ void setCorrectionRange(CXXScopeSpec *SS,
+ const DeclarationNameInfo &TypoName) {
+ CorrectionRange = TypoName.getSourceRange();
+ if (ForceSpecifierReplacement && SS && !SS->isEmpty())
+ CorrectionRange.setBegin(SS->getBeginLoc());
+ }
+
+ SourceRange getCorrectionRange() const {
+ return CorrectionRange;
+ }
+
+ using decl_iterator = SmallVectorImpl<NamedDecl *>::iterator;
+
+ decl_iterator begin() {
+ return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
+ }
+
+ decl_iterator end() { return CorrectionDecls.end(); }
+
+ using const_decl_iterator = SmallVectorImpl<NamedDecl *>::const_iterator;
+
+ const_decl_iterator begin() const {
+ return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin();
+ }
+
+ const_decl_iterator end() const { return CorrectionDecls.end(); }
+
+ /// Returns whether this typo correction is correcting to a
+ /// declaration that was declared in a module that has not been imported.
+ bool requiresImport() const { return RequiresImport; }
+ void setRequiresImport(bool Req) { RequiresImport = Req; }
+
+ /// Extra diagnostics are printed after the first diagnostic for the typo.
+ /// This can be used to attach external notes to the diag.
+ void addExtraDiagnostic(PartialDiagnostic PD) {
+ ExtraDiagnostics.push_back(std::move(PD));
+ }
+ ArrayRef<PartialDiagnostic> getExtraDiagnostics() const {
+ return ExtraDiagnostics;
+ }
+
+private:
+ bool hasCorrectionDecl() const {
+ return (!isKeyword() && !CorrectionDecls.empty());
+ }
+
+ // Results.
+ DeclarationName CorrectionName;
+ NestedNameSpecifier *CorrectionNameSpec = nullptr;
+ SmallVector<NamedDecl *, 1> CorrectionDecls;
+ unsigned CharDistance = 0;
+ unsigned QualifierDistance = 0;
+ unsigned CallbackDistance = 0;
+ SourceRange CorrectionRange;
+ bool ForceSpecifierReplacement = false;
+ bool RequiresImport = false;
+
+ std::vector<PartialDiagnostic> ExtraDiagnostics;
+};
+
+/// Base class for callback objects used by Sema::CorrectTypo to check
+/// the validity of a potential typo correction.
+class CorrectionCandidateCallback {
+public:
+ static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;
+
+ explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr,
+ NestedNameSpecifier *TypoNNS = nullptr)
+ : Typo(Typo), TypoNNS(TypoNNS) {}
+
+ virtual ~CorrectionCandidateCallback() = default;
+
+ /// Simple predicate used by the default RankCandidate to
+ /// determine whether to return an edit distance of 0 or InvalidDistance.
+ /// This can be overridden by validators that only need to determine if a
+ /// candidate is viable, without ranking potentially viable candidates.
+ /// Only ValidateCandidate or RankCandidate need to be overridden by a
+ /// callback wishing to check the viability of correction candidates.
+ /// The default predicate always returns true if the candidate is not a type
+ /// name or keyword, true for types if WantTypeSpecifiers is true, and true
+ /// for keywords if WantTypeSpecifiers, WantExpressionKeywords,
+ /// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true.
+ virtual bool ValidateCandidate(const TypoCorrection &candidate);
+
+ /// Method used by Sema::CorrectTypo to assign an "edit distance" rank
+ /// to a candidate (where a lower value represents a better candidate), or
+ /// returning InvalidDistance if the candidate is not at all viable. For
+ /// validation callbacks that only need to determine if a candidate is viable,
+ /// the default RankCandidate returns either 0 or InvalidDistance depending
+ /// whether ValidateCandidate returns true or false.
+ virtual unsigned RankCandidate(const TypoCorrection &candidate) {
+ return (!MatchesTypo(candidate) && ValidateCandidate(candidate))
+ ? 0
+ : InvalidDistance;
+ }
+
+ /// Clone this CorrectionCandidateCallback. CorrectionCandidateCallbacks are
+ /// initially stack-allocated. However in case where delayed typo-correction
+ /// is done we need to move the callback to storage with a longer lifetime.
+ /// Every class deriving from CorrectionCandidateCallback must implement
+ /// this method.
+ virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0;
+
+ void setTypoName(IdentifierInfo *II) { Typo = II; }
+ void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }
+
+ // Flags for context-dependent keywords. WantFunctionLikeCasts is only
+ // used/meaningful when WantCXXNamedCasts is false.
+ // TODO: Expand these to apply to non-keywords or possibly remove them.
+ bool WantTypeSpecifiers = true;
+ bool WantExpressionKeywords = true;
+ bool WantCXXNamedCasts = true;
+ bool WantFunctionLikeCasts = true;
+ bool WantRemainingKeywords = true;
+ bool WantObjCSuper = false;
+ // Temporary hack for the one case where a CorrectTypoContext enum is used
+ // when looking up results.
+ bool IsObjCIvarLookup = false;
+ bool IsAddressOfOperand = false;
+
+protected:
+ bool MatchesTypo(const TypoCorrection &candidate) {
+ return Typo && candidate.isResolved() && !candidate.requiresImport() &&
+ candidate.getCorrectionAsIdentifierInfo() == Typo &&
+ // FIXME: This probably does not return true when both
+ // NestedNameSpecifiers have the same textual representation.
+ candidate.getCorrectionSpecifier() == TypoNNS;
+ }
+
+ IdentifierInfo *Typo;
+ NestedNameSpecifier *TypoNNS;
+};
+
+class DefaultFilterCCC final : public CorrectionCandidateCallback {
+public:
+ explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr,
+ NestedNameSpecifier *TypoNNS = nullptr)
+ : CorrectionCandidateCallback(Typo, TypoNNS) {}
+
+ std::unique_ptr<CorrectionCandidateCallback> clone() override {
+ return std::make_unique<DefaultFilterCCC>(*this);
+ }
+};
+
+/// Simple template class for restricting typo correction candidates
+/// to ones having a single Decl* of the given type.
+template <class C>
+class DeclFilterCCC final : public CorrectionCandidateCallback {
+public:
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ return candidate.getCorrectionDeclAs<C>();
+ }
+ std::unique_ptr<CorrectionCandidateCallback> clone() override {
+ return std::make_unique<DeclFilterCCC>(*this);
+ }
+};
+
+// Callback class to limit the allowed keywords and to only accept typo
+// corrections that are keywords or whose decls refer to functions (or template
+// functions) that accept the given number of arguments.
+class FunctionCallFilterCCC : public CorrectionCandidateCallback {
+public:
+ FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
+ bool HasExplicitTemplateArgs,
+ MemberExpr *ME = nullptr);
+
+ bool ValidateCandidate(const TypoCorrection &candidate) override;
+ std::unique_ptr<CorrectionCandidateCallback> clone() override {
+ return std::make_unique<FunctionCallFilterCCC>(*this);
+ }
+
+private:
+ unsigned NumArgs;
+ bool HasExplicitTemplateArgs;
+ DeclContext *CurContext;
+ MemberExpr *MemberFn;
+};
+
+// Callback class that effectively disabled typo correction
+class NoTypoCorrectionCCC final : public CorrectionCandidateCallback {
+public:
+ NoTypoCorrectionCCC() {
+ WantTypeSpecifiers = false;
+ WantExpressionKeywords = false;
+ WantCXXNamedCasts = false;
+ WantFunctionLikeCasts = false;
+ WantRemainingKeywords = false;
+ }
+
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ return false;
+ }
+ std::unique_ptr<CorrectionCandidateCallback> clone() override {
+ return std::make_unique<NoTypoCorrectionCCC>(*this);
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_TYPOCORRECTION_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
diff --git a/contrib/libs/clang16/include/clang/Sema/Weak.h b/contrib/libs/clang16/include/clang/Sema/Weak.h
new file mode 100644
index 0000000000..b50c18e926
--- /dev/null
+++ b/contrib/libs/clang16/include/clang/Sema/Weak.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===-- UnresolvedSet.h - Unresolved sets of declarations ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the WeakInfo class, which is used to store
+// information about the target of a #pragma weak directive.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_WEAK_H
+#define LLVM_CLANG_SEMA_WEAK_H
+
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMapInfo.h"
+
+namespace clang {
+
+class IdentifierInfo;
+
+/// Captures information about a \#pragma weak directive.
+class WeakInfo {
+ const IdentifierInfo *alias = nullptr; // alias (optional)
+ SourceLocation loc; // for diagnostics
+public:
+ WeakInfo() = default;
+ WeakInfo(const IdentifierInfo *Alias, SourceLocation Loc)
+ : alias(Alias), loc(Loc) {}
+ inline const IdentifierInfo *getAlias() const { return alias; }
+ inline SourceLocation getLocation() const { return loc; }
+ bool operator==(WeakInfo RHS) const = delete;
+ bool operator!=(WeakInfo RHS) const = delete;
+
+ struct DenseMapInfoByAliasOnly
+ : private llvm::DenseMapInfo<const IdentifierInfo *> {
+ static inline WeakInfo getEmptyKey() {
+ return WeakInfo(DenseMapInfo::getEmptyKey(), SourceLocation());
+ }
+ static inline WeakInfo getTombstoneKey() {
+ return WeakInfo(DenseMapInfo::getTombstoneKey(), SourceLocation());
+ }
+ static unsigned getHashValue(const WeakInfo &W) {
+ return DenseMapInfo::getHashValue(W.getAlias());
+ }
+ static bool isEqual(const WeakInfo &LHS, const WeakInfo &RHS) {
+ return DenseMapInfo::isEqual(LHS.getAlias(), RHS.getAlias());
+ }
+ };
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_WEAK_H
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif