summaryrefslogtreecommitdiff
path: root/clang-r353983e/include/clang/Sema
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2019-07-02 16:25:20 -0700
committerAli B <abittin@gmail.com>2019-07-05 19:33:16 +0300
commit9afee4e65dc5f9f5eb371683729ff67b8df81d03 (patch)
tree4cf241d6c9044f91ee8c06e6920174d06f8de0b6 /clang-r353983e/include/clang/Sema
parent2f19bd722c4c825320d1511c1ed83161b7f95d51 (diff)
Update prebuilt Clang to r353983e.HEADq10.0
clang 9.0.5 (based on r353983e) from build 5696680. Bug: http://b/135931688 Bug: http://b/136008926 Test: N/A Change-Id: I922d17410047d2e2df4625615352c588ee71b203
Diffstat (limited to 'clang-r353983e/include/clang/Sema')
-rw-r--r--clang-r353983e/include/clang/Sema/AnalysisBasedWarnings.h102
-rw-r--r--clang-r353983e/include/clang/Sema/AttrParsedAttrImpl.inc3329
-rw-r--r--clang-r353983e/include/clang/Sema/AttrParsedAttrKinds.inc4288
-rw-r--r--clang-r353983e/include/clang/Sema/AttrParsedAttrList.inc276
-rw-r--r--clang-r353983e/include/clang/Sema/AttrSpellingListIndex.inc2123
-rw-r--r--clang-r353983e/include/clang/Sema/AttrTemplateInstantiate.inc2143
-rw-r--r--clang-r353983e/include/clang/Sema/CXXFieldCollector.h79
-rw-r--r--clang-r353983e/include/clang/Sema/CleanupInfo.h46
-rw-r--r--clang-r353983e/include/clang/Sema/CodeCompleteConsumer.h1208
-rw-r--r--clang-r353983e/include/clang/Sema/CodeCompleteOptions.h55
-rw-r--r--clang-r353983e/include/clang/Sema/DeclSpec.h2594
-rw-r--r--clang-r353983e/include/clang/Sema/DelayedDiagnostic.h337
-rw-r--r--clang-r353983e/include/clang/Sema/Designator.h209
-rw-r--r--clang-r353983e/include/clang/Sema/ExternalSemaSource.h233
-rw-r--r--clang-r353983e/include/clang/Sema/IdentifierResolver.h205
-rw-r--r--clang-r353983e/include/clang/Sema/Initialization.h1393
-rw-r--r--clang-r353983e/include/clang/Sema/Lookup.h812
-rw-r--r--clang-r353983e/include/clang/Sema/MultiplexExternalSemaSource.h362
-rw-r--r--clang-r353983e/include/clang/Sema/ObjCMethodList.h61
-rw-r--r--clang-r353983e/include/clang/Sema/Overload.h1007
-rw-r--r--clang-r353983e/include/clang/Sema/Ownership.h300
-rw-r--r--clang-r353983e/include/clang/Sema/ParsedAttr.h1038
-rw-r--r--clang-r353983e/include/clang/Sema/ParsedTemplate.h244
-rw-r--r--clang-r353983e/include/clang/Sema/Scope.h500
-rw-r--r--clang-r353983e/include/clang/Sema/ScopeInfo.h1019
-rw-r--r--clang-r353983e/include/clang/Sema/Sema.h11063
-rw-r--r--clang-r353983e/include/clang/Sema/SemaConsumer.h47
-rw-r--r--clang-r353983e/include/clang/Sema/SemaDiagnostic.h14
-rw-r--r--clang-r353983e/include/clang/Sema/SemaFixItUtils.h90
-rw-r--r--clang-r353983e/include/clang/Sema/SemaInternal.h371
-rw-r--r--clang-r353983e/include/clang/Sema/SemaLambda.h39
-rw-r--r--clang-r353983e/include/clang/Sema/Template.h568
-rw-r--r--clang-r353983e/include/clang/Sema/TemplateDeduction.h351
-rw-r--r--clang-r353983e/include/clang/Sema/TemplateInstCallback.h82
-rw-r--r--clang-r353983e/include/clang/Sema/TypoCorrection.h391
-rw-r--r--clang-r353983e/include/clang/Sema/Weak.h45
36 files changed, 37024 insertions, 0 deletions
diff --git a/clang-r353983e/include/clang/Sema/AnalysisBasedWarnings.h b/clang-r353983e/include/clang/Sema/AnalysisBasedWarnings.h
new file mode 100644
index 00000000..d5df5364
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/AnalysisBasedWarnings.h
@@ -0,0 +1,102 @@
+//=- 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"
+
+namespace clang {
+
+class BlockExpr;
+class Decl;
+class FunctionDecl;
+class ObjCMethodDecl;
+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;
+
+ 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);
+
+ void IssueWarnings(Policy P, FunctionScopeInfo *fscope,
+ const Decl *D, const BlockExpr *blkExpr);
+
+ Policy getDefaultPolicy() { return DefaultPolicy; }
+
+ void PrintStats() const;
+};
+
+}} // end namespace clang::sema
+
+#endif
diff --git a/clang-r353983e/include/clang/Sema/AttrParsedAttrImpl.inc b/clang-r353983e/include/clang/Sema/AttrParsedAttrImpl.inc
new file mode 100644
index 00000000..b6579368
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/AttrParsedAttrImpl.inc
@@ -0,0 +1,3329 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|* *|
+|* Parsed attribute helpers *|
+|* *|
+|* Automatically generated file, do not edit! *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+static bool defaultAppertainsTo(Sema &, const ParsedAttr &,const Decl *) {
+ return true;
+}
+
+static bool defaultDiagnoseLangOpts(Sema &, const ParsedAttr &) {
+ return true;
+}
+
+static bool defaultTargetRequirements(const TargetInfo &) {
+ return true;
+}
+
+static unsigned defaultSpellingIndexToSemanticSpelling(const ParsedAttr &Attr) {
+ return UINT_MAX;
+}
+
+static bool checkAMDGPUFlatWorkGroupSizeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "kernel functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAMDGPUFlatWorkGroupSize(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkAMDGPUNumSGPRAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "kernel functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAMDGPUNumSGPR(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkAMDGPUNumVGPRAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "kernel functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAMDGPUNumVGPR(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkAMDGPUWavesPerEUAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "kernel functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAMDGPUWavesPerEU(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool isTargetarmthumbarmebthumbebavrx86x86_64msp430mipsmipselriscv32riscv64(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::arm || T.getArch() == llvm::Triple::thumb || T.getArch() == llvm::Triple::armeb || T.getArch() == llvm::Triple::thumbeb || T.getArch() == llvm::Triple::avr || T.getArch() == llvm::Triple::x86 || T.getArch() == llvm::Triple::x86_64 || T.getArch() == llvm::Triple::msp430 || T.getArch() == llvm::Triple::mips || T.getArch() == llvm::Triple::mipsel || T.getArch() == llvm::Triple::riscv32 || T.getArch() == llvm::Triple::riscv64);
+}
+
+static bool checkAVRSignalAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool isTargetavr(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::avr);
+}
+
+static void matchRulesForAVRSignal(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool isStruct(const Decl *D) {
+ if (const auto *S = dyn_cast<RecordDecl>(D))
+ return !S->isUnion();
+ return false;
+}
+
+static bool checkAbiTagAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isStruct(D) && !isa<VarDecl>(D) && !isa<FunctionDecl>(D) && !isa<NamespaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "structs, variables, functions, and namespaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAbiTag(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record_not_is_union, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_namespace, /*IsSupported=*/LangOpts.CPlusPlus));
+}
+
+static bool checkAcquireCapabilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned AcquireCapabilityAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_acquire_capability = 0,
+ CXX11_clang_acquire_capability = 1,
+ GNU_acquire_shared_capability = 2,
+ CXX11_clang_acquire_shared_capability = 3,
+ GNU_exclusive_lock_function = 4,
+ GNU_shared_lock_function = 5
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_acquire_capability;
+ case 1: return CXX11_clang_acquire_capability;
+ case 2: return GNU_acquire_shared_capability;
+ case 3: return CXX11_clang_acquire_shared_capability;
+ case 4: return GNU_exclusive_lock_function;
+ case 5: return GNU_shared_lock_function;
+ }
+}
+
+static bool isSharedVar(const Decl *D) {
+ if (const auto *S = dyn_cast<VarDecl>(D))
+ return S->hasGlobalStorage() && !S->getTLSKind();
+ return false;
+}
+
+static bool checkAcquiredAfterAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FieldDecl>(D) && !isSharedVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-static data members and global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkAcquiredBeforeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FieldDecl>(D) && !isSharedVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-static data members and global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool isGlobalVar(const Decl *D) {
+ if (const auto *S = dyn_cast<VarDecl>(D))
+ return S->hasGlobalStorage();
+ return false;
+}
+
+static bool checkAliasAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isGlobalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions and global variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAlias(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_global, /*IsSupported=*/true));
+}
+
+static bool checkAlignValueAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D) && !isa<TypedefNameDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables and typedefs";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAlignValue(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_type_alias, /*IsSupported=*/true));
+}
+
+static unsigned AlignedAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_aligned = 0,
+ CXX11_gnu_aligned = 1,
+ Declspec_align = 2,
+ Keyword_alignas = 3,
+ Keyword_Alignas = 4
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_aligned;
+ case 1: return CXX11_gnu_aligned;
+ case 2: return Declspec_align;
+ case 3: return Keyword_alignas;
+ case 4: return Keyword_Alignas;
+ }
+}
+
+static bool isHasFunctionProto(const Decl *D) {
+ if (const auto *S = dyn_cast<Decl>(D))
+ return (S->getFunctionType(true) != nullptr &&
+ isa<FunctionProtoType>(S->getFunctionType())) ||
+ isa<ObjCMethodDecl>(S) ||
+ isa<BlockDecl>(S);
+ return false;
+}
+
+static bool checkAllocAlignAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isHasFunctionProto(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-K&R-style functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkAllocSizeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAllocSize(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkAlwaysDestroyAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAlwaysDestroy(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkAlwaysInlineAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned AlwaysInlineAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_always_inline = 0,
+ CXX11_gnu_always_inline = 1,
+ Keyword_forceinline = 2
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_always_inline;
+ case 1: return CXX11_gnu_always_inline;
+ case 2: return Keyword_forceinline;
+ }
+}
+
+static void matchRulesForAlwaysInline(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static void matchRulesForAnnotate(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+}
+
+static bool isTargetx86x86_64(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::x86 || T.getArch() == llvm::Triple::x86_64);
+}
+
+static bool isFunctionLike(const Decl *D) {
+ if (const auto *S = dyn_cast<Decl>(D))
+ return S->getFunctionType(false) != nullptr;
+ return false;
+}
+
+static bool checkAnyX86NoCfCheckAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isFunctionLike(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions and function pointers";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAnyX86NoCfCheck(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_hasType_functionType, /*IsSupported=*/true));
+}
+
+static bool checkArcWeakrefUnavailableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForArcWeakrefUnavailable(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkArgumentWithTypeTagAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isHasFunctionProto(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "non-K&R-style functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned ArgumentWithTypeTagAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_argument_with_type_tag = 0,
+ CXX11_clang_argument_with_type_tag = 1,
+ C2x_clang_argument_with_type_tag = 2,
+ GNU_pointer_with_type_tag = 3,
+ CXX11_clang_pointer_with_type_tag = 4,
+ C2x_clang_pointer_with_type_tag = 5
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_argument_with_type_tag;
+ case 1: return CXX11_clang_argument_with_type_tag;
+ case 2: return C2x_clang_argument_with_type_tag;
+ case 3: return GNU_pointer_with_type_tag;
+ case 4: return CXX11_clang_pointer_with_type_tag;
+ case 5: return C2x_clang_pointer_with_type_tag;
+ }
+}
+
+static bool isInlineFunction(const Decl *D) {
+ if (const auto *S = dyn_cast<FunctionDecl>(D))
+ return S->isInlineSpecified();
+ return false;
+}
+
+static bool checkArtificialAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isInlineFunction(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "inline functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkAssertCapabilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned AssertCapabilityAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_assert_capability = 0,
+ CXX11_clang_assert_capability = 1,
+ GNU_assert_shared_capability = 2,
+ CXX11_clang_assert_shared_capability = 3
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_assert_capability;
+ case 1: return CXX11_clang_assert_capability;
+ case 2: return GNU_assert_shared_capability;
+ case 3: return CXX11_clang_assert_shared_capability;
+ }
+}
+
+static bool checkAssertExclusiveLockAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkAssertSharedLockAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkAssumeAlignedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods and functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAssumeAligned(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkAvailabilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<NamedDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "named declarations";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForAvailability(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_enum, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_enum_constant, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_field, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_namespace, /*IsSupported=*/LangOpts.CPlusPlus));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_category, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_property, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_protocol, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_type_alias, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkCFAuditedTransferAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCFAuditedTransfer(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCFConsumedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCFConsumed(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkCFUnknownTransferAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCFUnknownTransfer(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCPUDispatchAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCPUDispatch(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCPUSpecificAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCPUSpecific(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCUDAConstantAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkCUDALangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.CUDA)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static void matchRulesForCUDAConstant(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkCUDADeviceAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions and variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCUDADevice(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkCUDAGlobalAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCUDAGlobal(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCUDAHostAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCUDAHost(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCUDAInvalidTargetAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkCUDALaunchBoundsAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isFunctionLike(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods, functions, and function pointers";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCUDALaunchBounds(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_hasType_functionType, /*IsSupported=*/true));
+}
+
+static bool checkCUDASharedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCUDAShared(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkCXX11NoReturnAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCXX11NoReturn(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCallableWhenAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCallableWhen(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function_is_member, /*IsSupported=*/LangOpts.CPlusPlus));
+}
+
+static bool checkCallbackAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCallback(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCapabilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D) && !isa<TypedefNameDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, classes, and typedefs";
+ return false;
+ }
+ return true;
+}
+
+static unsigned CapabilityAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_capability = 0,
+ CXX11_clang_capability = 1,
+ GNU_shared_capability = 2,
+ CXX11_clang_shared_capability = 3
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_capability;
+ case 1: return CXX11_clang_capability;
+ case 2: return GNU_shared_capability;
+ case 3: return CXX11_clang_shared_capability;
+ }
+}
+
+static void matchRulesForCapability(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_type_alias, /*IsSupported=*/true));
+}
+
+static bool checkCarriesDependencyAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D) && !isa<ObjCMethodDecl>(D) && !isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "parameters, Objective-C methods, and functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCarriesDependency(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool isLocalVar(const Decl *D) {
+ if (const auto *S = dyn_cast<VarDecl>(D))
+ return S->hasLocalStorage() && !isa<ParmVarDecl>(S);
+ return false;
+}
+
+static bool checkCleanupAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isLocalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "local variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkCodeSegAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions and classes";
+ return false;
+ }
+ return true;
+}
+
+static bool checkColdAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCold(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkCommonAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForCommon(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkConstructorAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForConstructor(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkConsumableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForConsumable(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkConsumableAutoCastAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForConsumableAutoCast(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkConsumableSetOnReadAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForConsumableSetOnRead(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkConvergentAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForConvergent(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkDLLExportAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<VarDecl>(D) && !isa<CXXRecordDecl>(D) && !isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions, variables, classes, and Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static bool isTargetx86x86_64armthumbaarch64Win32(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::x86 || T.getArch() == llvm::Triple::x86_64 || T.getArch() == llvm::Triple::arm || T.getArch() == llvm::Triple::thumb || T.getArch() == llvm::Triple::aarch64) && (T.getOS() == llvm::Triple::Win32);
+}
+
+static void matchRulesForDLLExport(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkDLLExportStaticLocalAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkDLLImportAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<VarDecl>(D) && !isa<CXXRecordDecl>(D) && !isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions, variables, classes, and Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForDLLImport(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkDLLImportStaticLocalAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkDestructorAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForDestructor(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkDiagnoseIfAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D) && !isa<ObjCPropertyDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions, Objective-C methods, and Objective-C properties";
+ return false;
+ }
+ return true;
+}
+
+static bool checkDisableTailCallsAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForDisableTailCalls(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkEmptyBasesAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static bool isTargetx86x86_64armthumbaarch64Microsoft(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::x86 || T.getArch() == llvm::Triple::x86_64 || T.getArch() == llvm::Triple::arm || T.getArch() == llvm::Triple::thumb || T.getArch() == llvm::Triple::aarch64) && (Target.getCXXABI().getKind() == TargetCXXABI::Microsoft);
+}
+
+static bool checkEnableIfAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForEnableIf(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkEnumExtensibilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<EnumDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "enums";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForEnumExtensibility(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_enum, /*IsSupported=*/true));
+}
+
+static bool checkExcludeFromExplicitInstantiationAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D) && !isa<FunctionDecl>(D) && !isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables, functions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForExcludeFromExplicitInstantiation(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkExclusiveTrylockFunctionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkExtVectorTypeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<TypedefNameDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "typedefs";
+ return false;
+ }
+ return true;
+}
+
+static bool checkExternalSourceSymbolAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<NamedDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "named declarations";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForExternalSourceSymbol(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_enum, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_enum_constant, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_field, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_namespace, /*IsSupported=*/LangOpts.CPlusPlus));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_category, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_property, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_protocol, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_type_alias, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkFlagEnumAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<EnumDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "enums";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForFlagEnum(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_enum, /*IsSupported=*/true));
+}
+
+static bool checkFlattenAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForFlatten(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkFormatAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isa<BlockDecl>(D) && !isHasFunctionProto(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods, blocks, and non-K&R-style functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkFormatArgAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isHasFunctionProto(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods and non-K&R-style functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkFortifyStdLibAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForFortifyStdLib(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkGNUInlineAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForGNUInline(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkGuardedByAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FieldDecl>(D) && !isSharedVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-static data members and global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkGuardedVarAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FieldDecl>(D) && !isSharedVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-static data members and global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkHotAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForHot(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool isObjCInstanceMethod(const Decl *D) {
+ if (const auto *S = dyn_cast<ObjCMethodDecl>(D))
+ return S->isInstanceMethod();
+ return false;
+}
+
+static bool checkIBActionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isObjCInstanceMethod(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C instance methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForIBAction(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method_is_instance, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkIFuncAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool isTargetELF(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getObjectFormat() == llvm::Triple::ELF);
+}
+
+static void matchRulesForIFunc(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkInitPriorityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForInitPriority(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkInternalLinkageAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D) && !isa<FunctionDecl>(D) && !isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables, functions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForInternalLinkage(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkLTOVisibilityPublicAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForLTOVisibilityPublic(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkLayoutVersionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static bool isImplicitObjectParameter(const Decl *D) {
+ if (const auto *S = dyn_cast<FunctionDecl>(D))
+ return static_cast<void>(S), false;
+ return false;
+}
+
+static bool checkLifetimeBoundAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D) && !isImplicitObjectParameter(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "parameters and implicit object parameters";
+ return false;
+ }
+ return true;
+}
+
+static bool checkCPlusPlusLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.CPlusPlus)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static bool checkLockReturnedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkLockableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForLockable(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkLocksExcludedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned LoopHintAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ Pragma_clang_loop = 0,
+ Pragma_unroll = 1,
+ Pragma_nounroll = 2,
+ Pragma_unroll_and_jam = 3,
+ Pragma_nounroll_and_jam = 4
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return Pragma_clang_loop;
+ case 1: return Pragma_unroll;
+ case 2: return Pragma_nounroll;
+ case 3: return Pragma_unroll_and_jam;
+ case 4: return Pragma_nounroll_and_jam;
+ }
+}
+
+static bool checkMicrosoftExtLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.MicrosoftExt)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static unsigned MSInheritanceAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ Keyword_single_inheritance = 0,
+ Keyword_multiple_inheritance = 1,
+ Keyword_virtual_inheritance = 2,
+ Keyword_unspecified_inheritance = 3
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return Keyword_single_inheritance;
+ case 1: return Keyword_multiple_inheritance;
+ case 2: return Keyword_virtual_inheritance;
+ case 3: return Keyword_unspecified_inheritance;
+ }
+}
+
+static bool checkMSNoVTableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static bool checkMSStructAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForMSStruct(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkMicroMipsAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool isTargetmipsmipsel(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::mips || T.getArch() == llvm::Triple::mipsel);
+}
+
+static void matchRulesForMicroMips(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkMinSizeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForMinSize(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkMinVectorWidthAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForMinVectorWidth(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkMips16AppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForMips16(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkMipsLongCallAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool isTargetmipsmipselmips64mips64el(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::mips || T.getArch() == llvm::Triple::mipsel || T.getArch() == llvm::Triple::mips64 || T.getArch() == llvm::Triple::mips64el);
+}
+
+static unsigned MipsLongCallAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_long_call = 0,
+ CXX11_gnu_long_call = 1,
+ GNU_far = 2,
+ CXX11_gnu_far = 3
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_long_call;
+ case 1: return CXX11_gnu_long_call;
+ case 2: return GNU_far;
+ case 3: return CXX11_gnu_far;
+ }
+}
+
+static void matchRulesForMipsLongCall(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkMipsShortCallAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned MipsShortCallAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_short_call = 0,
+ CXX11_gnu_short_call = 1,
+ GNU_near = 2,
+ CXX11_gnu_near = 3
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_short_call;
+ case 1: return CXX11_gnu_short_call;
+ case 2: return GNU_near;
+ case 3: return CXX11_gnu_near;
+ }
+}
+
+static void matchRulesForMipsShortCall(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkModeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D) && !isa<EnumDecl>(D) && !isa<TypedefNameDecl>(D) && !isa<FieldDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "variables, enums, typedefs, and non-static data members";
+ return false;
+ }
+ return true;
+}
+
+static bool checkNSConsumedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNSConsumed(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkNSConsumesSelfAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNSConsumesSelf(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkNakedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNaked(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoAliasAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkNoCommonAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoCommon(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool isNonParmVar(const Decl *D) {
+ if (const auto *S = dyn_cast<VarDecl>(D))
+ return S->getKind() != Decl::ParmVar;
+ return false;
+}
+
+static bool checkNoDebugAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isFunctionLike(D) && !isa<ObjCMethodDecl>(D) && !isNonParmVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions, function pointers, Objective-C methods, and variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoDebug(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_hasType_functionType, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_not_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkNoDestroyAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoDestroy(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkNoDuplicateAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoDuplicate(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoEscapeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoEscape(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkNoInlineAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoInline(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoInstrumentFunctionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoInstrumentFunction(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoMicroMipsAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoMicroMips(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoMips16AppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoMips16(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoSanitizeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D) && !isGlobalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions, Objective-C methods, and global variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoSanitize(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_global, /*IsSupported=*/true));
+}
+
+static bool checkNoSanitizeSpecificAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isGlobalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions and global variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoSanitizeSpecific(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_global, /*IsSupported=*/true));
+}
+
+static bool checkNoSpeculativeLoadHardeningAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoSpeculativeLoadHardening(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkNoSplitStackAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoSplitStack(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoStackProtectorAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoStackProtector(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoThreadSafetyAnalysisAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoThreadSafetyAnalysis(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNoThrowAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNoThrow(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkNonNullAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isHasFunctionProto(D) && !isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions, methods, and parameters";
+ return false;
+ }
+ return true;
+}
+
+static bool checkNotTailCalledAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForNotTailCalled(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkOSConsumedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOSConsumed(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool isNonStaticCXXMethod(const Decl *D) {
+ if (const auto *S = dyn_cast<CXXMethodDecl>(D))
+ return !S->isStatic();
+ return false;
+}
+
+static bool checkOSConsumesThisAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isNonStaticCXXMethod(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-static member functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkOSReturnsNotRetainedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D) && !isa<ObjCPropertyDecl>(D) && !isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions, Objective-C methods, Objective-C properties, and parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOSReturnsNotRetained(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_property, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkOSReturnsRetainedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D) && !isa<ObjCPropertyDecl>(D) && !isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions, Objective-C methods, Objective-C properties, and parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOSReturnsRetained(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_property, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkOSReturnsRetainedOnNonZeroAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOSReturnsRetainedOnNonZero(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkOSReturnsRetainedOnZeroAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOSReturnsRetainedOnZero(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkObjCBoxableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCBoxable(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkObjCBridgeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D) && !isa<TypedefNameDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, classes, and typedefs";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCBridge(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_type_alias, /*IsSupported=*/true));
+}
+
+static bool checkObjCBridgeMutableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCBridgeMutable(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkObjCBridgeRelatedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCBridgeRelated(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkObjCDesignatedInitializerAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCDesignatedInitializer(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCExceptionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCException(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCExplicitProtocolImplAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCProtocolDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C protocols";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCExplicitProtocolImpl(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_protocol, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCExternallyRetainedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isNonParmVar(D) && !isa<FunctionDecl>(D) && !isa<BlockDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables, functions, blocks, and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static bool checkObjCAutoRefCountLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.ObjCAutoRefCount)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static void matchRulesForObjCExternallyRetained(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_not_is_parameter, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_block, /*IsSupported=*/LangOpts.Blocks));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCMethodFamilyAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCMethodFamily(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCNonLazyClassAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static bool checkObjCLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.ObjC)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static void matchRulesForObjCNonLazyClass(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCPreciseLifetimeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCPreciseLifetime(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkObjCRequiresPropertyDefsAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCRequiresPropertyDefs(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCRequiresSuperAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCRequiresSuper(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCReturnsInnerPointerAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isa<ObjCPropertyDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods and Objective-C properties";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCReturnsInnerPointer(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_property, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCRootClassAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCRootClass(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCRuntimeNameAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D) && !isa<ObjCProtocolDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces and Objective-C protocols";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCRuntimeName(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_protocol, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCRuntimeVisibleAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCRuntimeVisible(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkObjCSubclassingRestrictedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCInterfaceDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C interfaces";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForObjCSubclassingRestricted(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_interface, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkOpenCLAccessAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D) && !isa<TypedefNameDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "parameters and typedefs";
+ return false;
+ }
+ return true;
+}
+
+static unsigned OpenCLAccessAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ Keyword_read_only = 0,
+ Keyword_write_only = 2,
+ Keyword_read_write = 4
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return Keyword_read_only;
+ case 1: return Keyword_read_only;
+ case 2: return Keyword_write_only;
+ case 3: return Keyword_write_only;
+ case 4: return Keyword_read_write;
+ case 5: return Keyword_read_write;
+ }
+}
+
+static bool checkOpenCLIntelReqdSubGroupSizeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOpenCLIntelReqdSubGroupSize(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkOpenCLKernelAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkOpenCLNoSVMAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkOpenCLLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.OpenCL)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static void matchRulesForOpenCLNoSVM(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+}
+
+static bool checkOptimizeNoneAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOptimizeNone(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkOverloadableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForOverloadable(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkOwnershipAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isHasFunctionProto(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-K&R-style functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned OwnershipAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_ownership_holds = 0,
+ CXX11_clang_ownership_holds = 1,
+ C2x_clang_ownership_holds = 2,
+ GNU_ownership_returns = 3,
+ CXX11_clang_ownership_returns = 4,
+ C2x_clang_ownership_returns = 5,
+ GNU_ownership_takes = 6,
+ CXX11_clang_ownership_takes = 7,
+ C2x_clang_ownership_takes = 8
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_ownership_holds;
+ case 1: return CXX11_clang_ownership_holds;
+ case 2: return C2x_clang_ownership_holds;
+ case 3: return GNU_ownership_returns;
+ case 4: return CXX11_clang_ownership_returns;
+ case 5: return C2x_clang_ownership_returns;
+ case 6: return GNU_ownership_takes;
+ case 7: return CXX11_clang_ownership_takes;
+ case 8: return C2x_clang_ownership_takes;
+ }
+}
+
+static bool checkParamTypestateAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForParamTypestate(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkPassObjectSizeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForPassObjectSize(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkPragmaClangBSSSectionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isGlobalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkPragmaClangDataSectionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isGlobalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkPragmaClangRodataSectionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isGlobalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkPragmaClangTextSectionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkPtGuardedByAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FieldDecl>(D) && !isSharedVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-static data members and global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkPtGuardedVarAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FieldDecl>(D) && !isSharedVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "non-static data members and global variables";
+ return false;
+ }
+ return true;
+}
+
+static bool isNonStaticNonConstCXXMethod(const Decl *D) {
+ if (const auto *S = dyn_cast<CXXMethodDecl>(D))
+ return !S->isStatic() && !S->isConst();
+ return false;
+}
+
+static bool checkReinitializesAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isNonStaticNonConstCXXMethod(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "non-static non-const member functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkReleaseCapabilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned ReleaseCapabilityAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_release_capability = 0,
+ CXX11_clang_release_capability = 1,
+ GNU_release_shared_capability = 2,
+ CXX11_clang_release_shared_capability = 3,
+ GNU_release_generic_capability = 4,
+ CXX11_clang_release_generic_capability = 5,
+ GNU_unlock_function = 6,
+ CXX11_clang_unlock_function = 7
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_release_capability;
+ case 1: return CXX11_clang_release_capability;
+ case 2: return GNU_release_shared_capability;
+ case 3: return CXX11_clang_release_shared_capability;
+ case 4: return GNU_release_generic_capability;
+ case 5: return CXX11_clang_release_generic_capability;
+ case 6: return GNU_unlock_function;
+ case 7: return CXX11_clang_unlock_function;
+ }
+}
+
+static bool checkRenderScriptKernelAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkRenderScriptLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.RenderScript)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static void matchRulesForRenderScriptKernel(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkReqdWorkGroupSizeAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForReqdWorkGroupSize(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkRequireConstantInitAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isGlobalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "global variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForRequireConstantInit(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_global, /*IsSupported=*/true));
+}
+
+static bool checkRequiresCapabilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned RequiresCapabilityAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_requires_capability = 0,
+ CXX11_clang_requires_capability = 1,
+ GNU_exclusive_locks_required = 2,
+ CXX11_clang_exclusive_locks_required = 3,
+ GNU_requires_shared_capability = 4,
+ CXX11_clang_requires_shared_capability = 5,
+ GNU_shared_locks_required = 6,
+ CXX11_clang_shared_locks_required = 7
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_requires_capability;
+ case 1: return CXX11_clang_requires_capability;
+ case 2: return GNU_exclusive_locks_required;
+ case 3: return CXX11_clang_exclusive_locks_required;
+ case 4: return GNU_requires_shared_capability;
+ case 5: return CXX11_clang_requires_shared_capability;
+ case 6: return GNU_shared_locks_required;
+ case 7: return CXX11_clang_shared_locks_required;
+ }
+}
+
+static bool checkRestrictAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned RestrictAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ Declspec_restrict = 0,
+ GNU_malloc = 1,
+ CXX11_gnu_malloc = 2
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return Declspec_restrict;
+ case 1: return GNU_malloc;
+ case 2: return CXX11_gnu_malloc;
+ }
+}
+
+static void matchRulesForRestrict(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkReturnTypestateAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions and parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForReturnTypestate(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkReturnsNonNullAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods and functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForReturnsNonNull(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkReturnsTwiceAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForReturnsTwice(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkScopedLockableAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForScopedLockable(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkSectionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isGlobalVar(D) && !isa<ObjCMethodDecl>(D) && !isa<ObjCPropertyDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions, global variables, Objective-C methods, and Objective-C properties";
+ return false;
+ }
+ return true;
+}
+
+static unsigned SectionAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_section = 0,
+ CXX11_gnu_section = 1,
+ Declspec_allocate = 2
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_section;
+ case 1: return CXX11_gnu_section;
+ case 2: return Declspec_allocate;
+ }
+}
+
+static void matchRulesForSection(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_global, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_property, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkSetTypestateAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForSetTypestate(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function_is_member, /*IsSupported=*/LangOpts.CPlusPlus));
+}
+
+static bool checkSharedTrylockFunctionAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool checkSpeculativeLoadHardeningAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForSpeculativeLoadHardening(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkSwiftContextAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForSwiftContext(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkSwiftErrorResultAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForSwiftErrorResult(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool checkSwiftIndirectResultAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ParmVarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "parameters";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForSwiftIndirectResult(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_parameter, /*IsSupported=*/true));
+}
+
+static bool isTLSVar(const Decl *D) {
+ if (const auto *S = dyn_cast<VarDecl>(D))
+ return S->getTLSKind() != 0;
+ return false;
+}
+
+static bool checkTLSModelAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isTLSVar(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "thread-local variables";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForTLSModel(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable_is_thread_local, /*IsSupported=*/true));
+}
+
+static bool checkTargetAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForTarget(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkTestTypestateAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForTestTypestate(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function_is_member, /*IsSupported=*/LangOpts.CPlusPlus));
+}
+
+static bool checkThreadAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkNotCPlusPlusLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (!S.LangOpts.CPlusPlus)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static bool checkTrivialABIAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForTrivialABI(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkTryAcquireCapabilityAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static unsigned TryAcquireCapabilityAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_try_acquire_capability = 0,
+ CXX11_clang_try_acquire_capability = 1,
+ GNU_try_acquire_shared_capability = 2,
+ CXX11_clang_try_acquire_shared_capability = 3
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_try_acquire_capability;
+ case 1: return CXX11_clang_try_acquire_capability;
+ case 2: return GNU_try_acquire_shared_capability;
+ case 3: return CXX11_clang_try_acquire_shared_capability;
+ }
+}
+
+static bool checkUninitializedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isLocalVar(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "local variables";
+ return false;
+ }
+ return true;
+}
+
+static bool checkUnusedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isa<TypeDecl>(D) && !isa<EnumDecl>(D) && !isa<EnumConstantDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D) && !isa<ObjCMethodDecl>(D) && !isFunctionLike(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables, non-static data members, types, enums, enumerators, labels, non-static data members, Objective-C methods, functions, and function pointers";
+ return false;
+ }
+ return true;
+}
+
+static unsigned UnusedAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ CXX11_maybe_unused = 0,
+ GNU_unused = 1,
+ CXX11_gnu_unused = 2,
+ C2x_maybe_unused = 3
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return CXX11_maybe_unused;
+ case 1: return GNU_unused;
+ case 2: return CXX11_gnu_unused;
+ case 3: return C2x_maybe_unused;
+ }
+}
+
+static bool isNonLocalVar(const Decl *D) {
+ if (const auto *S = dyn_cast<VarDecl>(D))
+ return !S->hasLocalStorage();
+ return false;
+}
+
+static bool checkUsedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isNonLocalVar(D) && !isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables with non-local storage, functions, and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static bool checkUuidAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D) && !isa<EnumDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, classes, and enums";
+ return false;
+ }
+ return true;
+}
+
+static bool checkMicrosoftExtBorlandLangOpts(Sema &S, const ParsedAttr &Attr) {
+ if (S.LangOpts.MicrosoftExt || S.LangOpts.Borland)
+ return true;
+
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ return false;
+}
+
+static bool checkVecReturnAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForVecReturn(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkVecTypeHintAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForVecTypeHint(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkWarnUnusedAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<RecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "structs, unions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForWarnUnused(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkWarnUnusedResultAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<ObjCMethodDecl>(D) && !isa<EnumDecl>(D) && !isa<RecordDecl>(D) && !isFunctionLike(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "Objective-C methods, enums, structs, unions, classes, functions, and function pointers";
+ return false;
+ }
+ return true;
+}
+
+static unsigned WarnUnusedResultAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ CXX11_nodiscard = 0,
+ C2x_nodiscard = 1,
+ CXX11_clang_warn_unused_result = 2,
+ GNU_warn_unused_result = 3,
+ CXX11_gnu_warn_unused_result = 4
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return CXX11_nodiscard;
+ case 1: return C2x_nodiscard;
+ case 2: return CXX11_clang_warn_unused_result;
+ case 3: return GNU_warn_unused_result;
+ case 4: return CXX11_gnu_warn_unused_result;
+ }
+}
+
+static void matchRulesForWarnUnusedResult(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_enum, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_hasType_functionType, /*IsSupported=*/true));
+}
+
+static bool checkWeakAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D) && !isa<FunctionDecl>(D) && !isa<CXXRecordDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "variables, functions, and classes";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForWeak(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_record, /*IsSupported=*/true));
+}
+
+static bool checkWeakRefAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<VarDecl>(D) && !isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "variables and functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForWeakRef(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_variable, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkWebAssemblyImportModuleAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static bool isTargetwasm32wasm64(const TargetInfo &Target) {
+ const llvm::Triple &T = Target.getTriple();
+ return true && (T.getArch() == llvm::Triple::wasm32 || T.getArch() == llvm::Triple::wasm64);
+}
+
+static void matchRulesForWebAssemblyImportModule(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkWebAssemblyImportNameAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForWebAssemblyImportName(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkWorkGroupSizeHintAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ << Attr << "functions";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForWorkGroupSizeHint(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+}
+
+static bool checkXRayInstrumentAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static unsigned XRayInstrumentAttrSpellingMap(const ParsedAttr &Attr) {
+ enum Spelling {
+ GNU_xray_always_instrument = 0,
+ CXX11_clang_xray_always_instrument = 1,
+ C2x_clang_xray_always_instrument = 2,
+ GNU_xray_never_instrument = 3,
+ CXX11_clang_xray_never_instrument = 4,
+ C2x_clang_xray_never_instrument = 5
+ };
+
+ unsigned Idx = Attr.getAttributeSpellingListIndex();
+ switch (Idx) {
+ default: llvm_unreachable("Unknown spelling list index");
+ case 0: return GNU_xray_always_instrument;
+ case 1: return CXX11_clang_xray_always_instrument;
+ case 2: return C2x_clang_xray_always_instrument;
+ case 3: return GNU_xray_never_instrument;
+ case 4: return CXX11_clang_xray_never_instrument;
+ case 5: return C2x_clang_xray_never_instrument;
+ }
+}
+
+static void matchRulesForXRayInstrument(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static bool checkXRayLogArgsAppertainsTo(Sema &S, const ParsedAttr &Attr, const Decl *D) {
+ if (!D || (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D))) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ << Attr << "functions and Objective-C methods";
+ return false;
+ }
+ return true;
+}
+
+static void matchRulesForXRayLogArgs(llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules, const LangOptions &LangOpts) {
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_function, /*IsSupported=*/true));
+ MatchRules.push_back(std::make_pair(attr::SubjectMatchRule_objc_method, /*IsSupported=*/LangOpts.ObjC));
+}
+
+static const ParsedAttrInfo AttrInfoMap[ParsedAttr::UnknownAttribute + 1] = {
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AArch64VectorPcs
+ { 2, 0, 0, 0, 0, 0, 0, 1, checkAMDGPUFlatWorkGroupSizeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAMDGPUFlatWorkGroupSize }, // AT_AMDGPUFlatWorkGroupSize
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkAMDGPUNumSGPRAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAMDGPUNumSGPR }, // AT_AMDGPUNumSGPR
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkAMDGPUNumVGPRAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAMDGPUNumVGPR }, // AT_AMDGPUNumVGPR
+ { 1, 1, 0, 0, 0, 0, 0, 1, checkAMDGPUWavesPerEUAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAMDGPUWavesPerEU }, // AT_AMDGPUWavesPerEU
+ { 0, 1, 1, 1, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, isTargetarmthumbarmebthumbebavrx86x86_64msp430mipsmipselriscv32riscv64, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Interrupt
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkAVRSignalAppertainsTo, defaultDiagnoseLangOpts, isTargetavr, defaultSpellingIndexToSemanticSpelling, matchRulesForAVRSignal }, // AT_AVRSignal
+ { 0, 15, 0, 0, 0, 0, 1, 1, checkAbiTagAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAbiTag }, // AT_AbiTag
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkAcquireCapabilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, AcquireCapabilityAttrSpellingMap, nullptr }, // AT_AcquireCapability
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkAcquiredAfterAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AcquiredAfter
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkAcquiredBeforeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AcquiredBefore
+ { 1, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AddressSpace
+ { 1, 0, 0, 0, 0, 0, 1, 1, checkAliasAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAlias }, // AT_Alias
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkAlignValueAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAlignValue }, // AT_AlignValue
+ { 0, 1, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, AlignedAttrSpellingMap, nullptr }, // AT_Aligned
+ { 1, 0, 0, 0, 0, 0, 1, 0, checkAllocAlignAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AllocAlign
+ { 1, 1, 0, 0, 0, 0, 1, 1, checkAllocSizeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAllocSize }, // AT_AllocSize
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkAlwaysDestroyAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAlwaysDestroy }, // AT_AlwaysDestroy
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkAlwaysInlineAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, AlwaysInlineAttrSpellingMap, matchRulesForAlwaysInline }, // AT_AlwaysInline
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AnalyzerNoReturn
+ { 1, 0, 0, 0, 0, 0, 0, 1, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAnnotate }, // AT_Annotate
+ { 0, 0, 0, 1, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AnyX86NoCallerSavedRegisters
+ { 0, 0, 0, 1, 1, 0, 1, 1, checkAnyX86NoCfCheckAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64, defaultSpellingIndexToSemanticSpelling, matchRulesForAnyX86NoCfCheck }, // AT_AnyX86NoCfCheck
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkArcWeakrefUnavailableAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForArcWeakrefUnavailable }, // AT_ArcWeakrefUnavailable
+ { 3, 0, 0, 0, 0, 0, 0, 0, checkArgumentWithTypeTagAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, ArgumentWithTypeTagAttrSpellingMap, nullptr }, // AT_ArgumentWithTypeTag
+ { 0, 0, 0, 0, 0, 0, 1, 0, checkArtificialAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Artificial
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkAssertCapabilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, AssertCapabilityAttrSpellingMap, nullptr }, // AT_AssertCapability
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkAssertExclusiveLockAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AssertExclusiveLock
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkAssertSharedLockAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_AssertSharedLock
+ { 1, 1, 0, 0, 0, 0, 1, 1, checkAssumeAlignedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAssumeAligned }, // AT_AssumeAligned
+ { 9, 0, 1, 0, 0, 0, 0, 1, checkAvailabilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForAvailability }, // AT_Availability
+ { 1, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Blocks
+ { 0, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_CDecl
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCFAuditedTransferAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCFAuditedTransfer }, // AT_CFAuditedTransfer
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCFConsumedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCFConsumed }, // AT_CFConsumed
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_CFReturnsNotRetained
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_CFReturnsRetained
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCFUnknownTransferAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCFUnknownTransfer }, // AT_CFUnknownTransfer
+ { 0, 15, 0, 0, 0, 0, 0, 1, checkCPUDispatchAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCPUDispatch }, // AT_CPUDispatch
+ { 0, 15, 0, 0, 0, 0, 0, 1, checkCPUSpecificAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCPUSpecific }, // AT_CPUSpecific
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCUDAConstantAppertainsTo, checkCUDALangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCUDAConstant }, // AT_CUDAConstant
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCUDADeviceAppertainsTo, checkCUDALangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCUDADevice }, // AT_CUDADevice
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCUDAGlobalAppertainsTo, checkCUDALangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCUDAGlobal }, // AT_CUDAGlobal
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCUDAHostAppertainsTo, checkCUDALangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCUDAHost }, // AT_CUDAHost
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkCUDAInvalidTargetAppertainsTo, checkCUDALangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_CUDAInvalidTarget
+ { 1, 1, 0, 0, 0, 0, 0, 1, checkCUDALaunchBoundsAppertainsTo, checkCUDALangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCUDALaunchBounds }, // AT_CUDALaunchBounds
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCUDASharedAppertainsTo, checkCUDALangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCUDAShared }, // AT_CUDAShared
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCXX11NoReturnAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCXX11NoReturn }, // AT_CXX11NoReturn
+ { 0, 15, 0, 0, 0, 0, 0, 1, checkCallableWhenAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCallableWhen }, // AT_CallableWhen
+ { 0, 15, 0, 0, 0, 0, 0, 1, checkCallbackAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCallback }, // AT_Callback
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkCapabilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, CapabilityAttrSpellingMap, matchRulesForCapability }, // AT_Capability
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkCarriesDependencyAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCarriesDependency }, // AT_CarriesDependency
+ { 1, 0, 0, 0, 0, 0, 1, 0, checkCleanupAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Cleanup
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkCodeSegAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_CodeSeg
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkColdAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCold }, // AT_Cold
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkCommonAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForCommon }, // AT_Common
+ { 0, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Const
+ { 0, 1, 0, 0, 0, 0, 1, 1, checkConstructorAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForConstructor }, // AT_Constructor
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkConsumableAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForConsumable }, // AT_Consumable
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkConsumableAutoCastAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForConsumableAutoCast }, // AT_ConsumableAutoCast
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkConsumableSetOnReadAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForConsumableSetOnRead }, // AT_ConsumableSetOnRead
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkConvergentAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForConvergent }, // AT_Convergent
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkDLLExportAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64armthumbaarch64Win32, defaultSpellingIndexToSemanticSpelling, matchRulesForDLLExport }, // AT_DLLExport
+ { 0, 0, 0, 1, 0, 0, 0, 0, checkDLLExportStaticLocalAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64armthumbaarch64Win32, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_DLLExportStaticLocal
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkDLLImportAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64armthumbaarch64Win32, defaultSpellingIndexToSemanticSpelling, matchRulesForDLLImport }, // AT_DLLImport
+ { 0, 0, 0, 1, 0, 0, 0, 0, checkDLLImportStaticLocalAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64armthumbaarch64Win32, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_DLLImportStaticLocal
+ { 0, 2, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Deprecated
+ { 0, 1, 0, 0, 0, 0, 1, 1, checkDestructorAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForDestructor }, // AT_Destructor
+ { 3, 0, 0, 0, 0, 0, 0, 0, checkDiagnoseIfAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_DiagnoseIf
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkDisableTailCallsAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForDisableTailCalls }, // AT_DisableTailCalls
+ { 0, 0, 0, 1, 0, 0, 0, 0, checkEmptyBasesAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64armthumbaarch64Microsoft, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_EmptyBases
+ { 2, 0, 0, 0, 0, 0, 0, 1, checkEnableIfAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForEnableIf }, // AT_EnableIf
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkEnumExtensibilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForEnumExtensibility }, // AT_EnumExtensibility
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkExcludeFromExplicitInstantiationAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForExcludeFromExplicitInstantiation }, // AT_ExcludeFromExplicitInstantiation
+ { 1, 15, 0, 0, 0, 0, 0, 0, checkExclusiveTrylockFunctionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ExclusiveTrylockFunction
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkExtVectorTypeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ExtVectorType
+ { 0, 3, 1, 0, 0, 0, 0, 1, checkExternalSourceSymbolAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForExternalSourceSymbol }, // AT_ExternalSourceSymbol
+ { 0, 0, 0, 0, 0, 1, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_FallThrough
+ { 0, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_FastCall
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkFlagEnumAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForFlagEnum }, // AT_FlagEnum
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkFlattenAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForFlatten }, // AT_Flatten
+ { 3, 0, 0, 0, 0, 0, 1, 0, checkFormatAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Format
+ { 1, 0, 0, 0, 0, 0, 1, 0, checkFormatArgAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_FormatArg
+ { 2, 0, 0, 0, 0, 0, 0, 1, checkFortifyStdLibAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForFortifyStdLib }, // AT_FortifyStdLib
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkGNUInlineAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForGNUInline }, // AT_GNUInline
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkGuardedByAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_GuardedBy
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkGuardedVarAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_GuardedVar
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkHotAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForHot }, // AT_Hot
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkIBActionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForIBAction }, // AT_IBAction
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_IBOutlet
+ { 0, 1, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_IBOutletCollection
+ { 1, 0, 0, 1, 0, 0, 1, 1, checkIFuncAppertainsTo, defaultDiagnoseLangOpts, isTargetELF, defaultSpellingIndexToSemanticSpelling, matchRulesForIFunc }, // AT_IFunc
+ { 1, 0, 0, 0, 0, 0, 1, 1, checkInitPriorityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForInitPriority }, // AT_InitPriority
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_IntelOclBicc
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkInternalLinkageAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForInternalLinkage }, // AT_InternalLinkage
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkLTOVisibilityPublicAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForLTOVisibilityPublic }, // AT_LTOVisibilityPublic
+ { 1, 0, 0, 1, 0, 0, 0, 0, checkLayoutVersionAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64armthumbaarch64Microsoft, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_LayoutVersion
+ { 0, 0, 0, 0, 1, 0, 0, 0, checkLifetimeBoundAppertainsTo, checkCPlusPlusLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_LifetimeBound
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkLockReturnedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_LockReturned
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkLockableAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForLockable }, // AT_Lockable
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkLocksExcludedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_LocksExcluded
+ { 3, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, LoopHintAttrSpellingMap, nullptr }, // AT_LoopHint
+ { 0, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_MSABI
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, checkMicrosoftExtLangOpts, defaultTargetRequirements, MSInheritanceAttrSpellingMap, nullptr }, // AT_MSInheritance
+ { 0, 0, 0, 1, 0, 0, 0, 0, checkMSNoVTableAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64armthumbaarch64Microsoft, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_MSNoVTable
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkMSStructAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForMSStruct }, // AT_MSStruct
+ { 0, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_MayAlias
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkMicroMipsAppertainsTo, defaultDiagnoseLangOpts, isTargetmipsmipsel, defaultSpellingIndexToSemanticSpelling, matchRulesForMicroMips }, // AT_MicroMips
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkMinSizeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForMinSize }, // AT_MinSize
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkMinVectorWidthAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForMinVectorWidth }, // AT_MinVectorWidth
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkMips16AppertainsTo, defaultDiagnoseLangOpts, isTargetmipsmipsel, defaultSpellingIndexToSemanticSpelling, matchRulesForMips16 }, // AT_Mips16
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkMipsLongCallAppertainsTo, defaultDiagnoseLangOpts, isTargetmipsmipselmips64mips64el, MipsLongCallAttrSpellingMap, matchRulesForMipsLongCall }, // AT_MipsLongCall
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkMipsShortCallAppertainsTo, defaultDiagnoseLangOpts, isTargetmipsmipselmips64mips64el, MipsShortCallAttrSpellingMap, matchRulesForMipsShortCall }, // AT_MipsShortCall
+ { 1, 0, 0, 0, 0, 0, 1, 0, checkModeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Mode
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNSConsumedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNSConsumed }, // AT_NSConsumed
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNSConsumesSelfAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNSConsumesSelf }, // AT_NSConsumesSelf
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NSReturnsAutoreleased
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NSReturnsNotRetained
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NSReturnsRetained
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNakedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNaked }, // AT_Naked
+ { 1, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NeonPolyVectorType
+ { 1, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NeonVectorType
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkNoAliasAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NoAlias
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNoCommonAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoCommon }, // AT_NoCommon
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNoDebugAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoDebug }, // AT_NoDebug
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NoDeref
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNoDestroyAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoDestroy }, // AT_NoDestroy
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNoDuplicateAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoDuplicate }, // AT_NoDuplicate
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNoEscapeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoEscape }, // AT_NoEscape
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNoInlineAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoInline }, // AT_NoInline
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNoInstrumentFunctionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoInstrumentFunction }, // AT_NoInstrumentFunction
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkNoMicroMipsAppertainsTo, defaultDiagnoseLangOpts, isTargetmipsmipsel, defaultSpellingIndexToSemanticSpelling, matchRulesForNoMicroMips }, // AT_NoMicroMips
+ { 0, 0, 0, 1, 0, 0, 1, 1, checkNoMips16AppertainsTo, defaultDiagnoseLangOpts, isTargetmipsmipsel, defaultSpellingIndexToSemanticSpelling, matchRulesForNoMips16 }, // AT_NoMips16
+ { 0, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NoReturn
+ { 0, 15, 0, 0, 0, 0, 0, 1, checkNoSanitizeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoSanitize }, // AT_NoSanitize
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNoSanitizeSpecificAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoSanitizeSpecific }, // AT_NoSanitizeSpecific
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNoSpeculativeLoadHardeningAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoSpeculativeLoadHardening }, // AT_NoSpeculativeLoadHardening
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNoSplitStackAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoSplitStack }, // AT_NoSplitStack
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNoStackProtectorAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoStackProtector }, // AT_NoStackProtector
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNoThreadSafetyAnalysisAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoThreadSafetyAnalysis }, // AT_NoThreadSafetyAnalysis
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkNoThrowAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNoThrow }, // AT_NoThrow
+ { 0, 15, 0, 0, 0, 0, 1, 0, checkNonNullAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_NonNull
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkNotTailCalledAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForNotTailCalled }, // AT_NotTailCalled
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOSConsumedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOSConsumed }, // AT_OSConsumed
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkOSConsumesThisAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OSConsumesThis
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOSReturnsNotRetainedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOSReturnsNotRetained }, // AT_OSReturnsNotRetained
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOSReturnsRetainedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOSReturnsRetained }, // AT_OSReturnsRetained
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOSReturnsRetainedOnNonZeroAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOSReturnsRetainedOnNonZero }, // AT_OSReturnsRetainedOnNonZero
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOSReturnsRetainedOnZeroAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOSReturnsRetainedOnZero }, // AT_OSReturnsRetainedOnZero
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCBoxableAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCBoxable }, // AT_ObjCBoxable
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkObjCBridgeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCBridge }, // AT_ObjCBridge
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkObjCBridgeMutableAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCBridgeMutable }, // AT_ObjCBridgeMutable
+ { 3, 0, 1, 0, 0, 0, 0, 1, checkObjCBridgeRelatedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCBridgeRelated }, // AT_ObjCBridgeRelated
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCDesignatedInitializerAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCDesignatedInitializer }, // AT_ObjCDesignatedInitializer
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCExceptionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCException }, // AT_ObjCException
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCExplicitProtocolImplAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCExplicitProtocolImpl }, // AT_ObjCExplicitProtocolImpl
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCExternallyRetainedAppertainsTo, checkObjCAutoRefCountLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCExternallyRetained }, // AT_ObjCExternallyRetained
+ { 1, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ObjCGC
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ObjCIndependentClass
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ObjCInertUnsafeUnretained
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ObjCKindOf
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkObjCMethodFamilyAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCMethodFamily }, // AT_ObjCMethodFamily
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ObjCNSObject
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCNonLazyClassAppertainsTo, checkObjCLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCNonLazyClass }, // AT_ObjCNonLazyClass
+ { 1, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ObjCOwnership
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCPreciseLifetimeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCPreciseLifetime }, // AT_ObjCPreciseLifetime
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCRequiresPropertyDefsAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCRequiresPropertyDefs }, // AT_ObjCRequiresPropertyDefs
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCRequiresSuperAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCRequiresSuper }, // AT_ObjCRequiresSuper
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCReturnsInnerPointerAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCReturnsInnerPointer }, // AT_ObjCReturnsInnerPointer
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCRootClassAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCRootClass }, // AT_ObjCRootClass
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkObjCRuntimeNameAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCRuntimeName }, // AT_ObjCRuntimeName
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCRuntimeVisibleAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCRuntimeVisible }, // AT_ObjCRuntimeVisible
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkObjCSubclassingRestrictedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForObjCSubclassingRestricted }, // AT_ObjCSubclassingRestricted
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkOpenCLAccessAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, OpenCLAccessAttrSpellingMap, nullptr }, // AT_OpenCLAccess
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OpenCLConstantAddressSpace
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OpenCLGenericAddressSpace
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OpenCLGlobalAddressSpace
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkOpenCLIntelReqdSubGroupSizeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOpenCLIntelReqdSubGroupSize }, // AT_OpenCLIntelReqdSubGroupSize
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkOpenCLKernelAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OpenCLKernel
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OpenCLLocalAddressSpace
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOpenCLNoSVMAppertainsTo, checkOpenCLLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOpenCLNoSVM }, // AT_OpenCLNoSVM
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OpenCLPrivateAddressSpace
+ { 1, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_OpenCLUnrollHint
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOptimizeNoneAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOptimizeNone }, // AT_OptimizeNone
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkOverloadableAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForOverloadable }, // AT_Overloadable
+ { 1, 15, 0, 0, 0, 0, 0, 0, checkOwnershipAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, OwnershipAttrSpellingMap, nullptr }, // AT_Ownership
+ { 0, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Packed
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkParamTypestateAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForParamTypestate }, // AT_ParamTypestate
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Pascal
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkPassObjectSizeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForPassObjectSize }, // AT_PassObjectSize
+ { 1, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Pcs
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkPragmaClangBSSSectionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PragmaClangBSSSection
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkPragmaClangDataSectionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PragmaClangDataSection
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkPragmaClangRodataSectionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PragmaClangRodataSection
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkPragmaClangTextSectionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PragmaClangTextSection
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PreserveAll
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PreserveMost
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkPtGuardedByAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PtGuardedBy
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkPtGuardedVarAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_PtGuardedVar
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Ptr32
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Ptr64
+ { 0, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Pure
+ { 0, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_RegCall
+ { 1, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Regparm
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkReinitializesAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Reinitializes
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkReleaseCapabilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, ReleaseCapabilityAttrSpellingMap, nullptr }, // AT_ReleaseCapability
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkRenderScriptKernelAppertainsTo, checkRenderScriptLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForRenderScriptKernel }, // AT_RenderScriptKernel
+ { 3, 0, 0, 0, 0, 0, 0, 1, checkReqdWorkGroupSizeAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForReqdWorkGroupSize }, // AT_ReqdWorkGroupSize
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkRequireConstantInitAppertainsTo, checkCPlusPlusLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForRequireConstantInit }, // AT_RequireConstantInit
+ { 0, 15, 0, 0, 0, 0, 0, 0, checkRequiresCapabilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, RequiresCapabilityAttrSpellingMap, nullptr }, // AT_RequiresCapability
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkRestrictAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, RestrictAttrSpellingMap, matchRulesForRestrict }, // AT_Restrict
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkReturnTypestateAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForReturnTypestate }, // AT_ReturnTypestate
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkReturnsNonNullAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForReturnsNonNull }, // AT_ReturnsNonNull
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkReturnsTwiceAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForReturnsTwice }, // AT_ReturnsTwice
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_SPtr
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkScopedLockableAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForScopedLockable }, // AT_ScopedLockable
+ { 1, 0, 0, 0, 0, 0, 1, 1, checkSectionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, SectionAttrSpellingMap, matchRulesForSection }, // AT_Section
+ { 0, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_SelectAny
+ { 0, 2, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Sentinel
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkSetTypestateAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForSetTypestate }, // AT_SetTypestate
+ { 1, 15, 0, 0, 0, 0, 0, 0, checkSharedTrylockFunctionAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_SharedTrylockFunction
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkSpeculativeLoadHardeningAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForSpeculativeLoadHardening }, // AT_SpeculativeLoadHardening
+ { 0, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_StdCall
+ { 0, 15, 0, 0, 0, 1, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Suppress
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_SwiftCall
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkSwiftContextAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForSwiftContext }, // AT_SwiftContext
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkSwiftErrorResultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForSwiftErrorResult }, // AT_SwiftErrorResult
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkSwiftIndirectResultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForSwiftIndirectResult }, // AT_SwiftIndirectResult
+ { 0, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_SysVABI
+ { 1, 0, 0, 0, 0, 0, 1, 1, checkTLSModelAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForTLSModel }, // AT_TLSModel
+ { 1, 0, 0, 0, 0, 0, 1, 1, checkTargetAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForTarget }, // AT_Target
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkTestTypestateAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForTestTypestate }, // AT_TestTypestate
+ { 0, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_ThisCall
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkThreadAppertainsTo, checkMicrosoftExtLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Thread
+ { 0, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, checkNotCPlusPlusLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_TransparentUnion
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkTrivialABIAppertainsTo, checkCPlusPlusLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForTrivialABI }, // AT_TrivialABI
+ { 1, 15, 0, 0, 0, 0, 0, 0, checkTryAcquireCapabilityAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, TryAcquireCapabilityAttrSpellingMap, nullptr }, // AT_TryAcquireCapability
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_TypeNonNull
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_TypeNullUnspecified
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_TypeNullable
+ { 4, 0, 1, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_TypeTagForDatatype
+ { 1, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_TypeVisibility
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_UPtr
+ { 0, 1, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Unavailable
+ { 0, 0, 0, 0, 0, 0, 0, 0, checkUninitializedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Uninitialized
+ { 0, 0, 0, 0, 0, 0, 1, 0, checkUnusedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, UnusedAttrSpellingMap, nullptr }, // AT_Unused
+ { 0, 0, 0, 0, 0, 0, 1, 0, checkUsedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Used
+ { 1, 0, 0, 0, 0, 0, 0, 0, checkUuidAppertainsTo, checkMicrosoftExtBorlandLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Uuid
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkVecReturnAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForVecReturn }, // AT_VecReturn
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkVecTypeHintAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForVecTypeHint }, // AT_VecTypeHint
+ { 0, 0, 0, 0, 1, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_VectorCall
+ { 1, 0, 0, 0, 1, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_VectorSize
+ { 1, 0, 0, 0, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_Visibility
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkWarnUnusedAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForWarnUnused }, // AT_WarnUnused
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkWarnUnusedResultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, WarnUnusedResultAttrSpellingMap, matchRulesForWarnUnusedResult }, // AT_WarnUnusedResult
+ { 0, 0, 0, 0, 0, 0, 1, 1, checkWeakAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForWeak }, // AT_Weak
+ { 0, 0, 0, 0, 0, 0, 0, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_WeakImport
+ { 0, 1, 0, 0, 0, 0, 1, 1, checkWeakRefAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForWeakRef }, // AT_WeakRef
+ { 1, 0, 0, 1, 0, 0, 0, 1, checkWebAssemblyImportModuleAppertainsTo, defaultDiagnoseLangOpts, isTargetwasm32wasm64, defaultSpellingIndexToSemanticSpelling, matchRulesForWebAssemblyImportModule }, // AT_WebAssemblyImportModule
+ { 1, 0, 0, 1, 0, 0, 0, 1, checkWebAssemblyImportNameAppertainsTo, defaultDiagnoseLangOpts, isTargetwasm32wasm64, defaultSpellingIndexToSemanticSpelling, matchRulesForWebAssemblyImportName }, // AT_WebAssemblyImportName
+ { 3, 0, 0, 0, 0, 0, 0, 1, checkWorkGroupSizeHintAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForWorkGroupSizeHint }, // AT_WorkGroupSizeHint
+ { 0, 0, 0, 1, 0, 0, 1, 0, defaultAppertainsTo, defaultDiagnoseLangOpts, isTargetx86x86_64, defaultSpellingIndexToSemanticSpelling, nullptr }, // AT_X86ForceAlignArgPointer
+ { 0, 0, 0, 0, 0, 0, 0, 1, checkXRayInstrumentAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, XRayInstrumentAttrSpellingMap, matchRulesForXRayInstrument }, // AT_XRayInstrument
+ { 1, 0, 0, 0, 0, 0, 0, 1, checkXRayLogArgsAppertainsTo, defaultDiagnoseLangOpts, defaultTargetRequirements, defaultSpellingIndexToSemanticSpelling, matchRulesForXRayLogArgs } // AT_XRayLogArgs
+};
+
+static bool checkAttributeMatchRuleAppliesTo(const Decl *D, attr::SubjectMatchRule rule) {
+ switch (rule) {
+ case attr::SubjectMatchRule_block:
+ return isa<BlockDecl>(D);
+ case attr::SubjectMatchRule_enum:
+ return isa<EnumDecl>(D);
+ case attr::SubjectMatchRule_enum_constant:
+ return isa<EnumConstantDecl>(D);
+ case attr::SubjectMatchRule_field:
+ return isa<FieldDecl>(D);
+ case attr::SubjectMatchRule_function:
+ return isa<FunctionDecl>(D);
+ case attr::SubjectMatchRule_function_is_member:
+ return isa<CXXMethodDecl>(D);
+ case attr::SubjectMatchRule_namespace:
+ return isa<NamespaceDecl>(D);
+ case attr::SubjectMatchRule_objc_category:
+ return isa<ObjCCategoryDecl>(D);
+ case attr::SubjectMatchRule_objc_interface:
+ return isa<ObjCInterfaceDecl>(D);
+ case attr::SubjectMatchRule_objc_method:
+ return isa<ObjCMethodDecl>(D);
+ case attr::SubjectMatchRule_objc_method_is_instance:
+ return isObjCInstanceMethod(D);
+ case attr::SubjectMatchRule_objc_property:
+ return isa<ObjCPropertyDecl>(D);
+ case attr::SubjectMatchRule_objc_protocol:
+ return isa<ObjCProtocolDecl>(D);
+ case attr::SubjectMatchRule_record:
+ return isa<RecordDecl>(D) || isa<CXXRecordDecl>(D);
+ case attr::SubjectMatchRule_record_not_is_union:
+ return isStruct(D);
+ case attr::SubjectMatchRule_hasType_abstract:
+ assert(false && "Abstract matcher rule isn't allowed");
+ return false;
+ case attr::SubjectMatchRule_hasType_functionType:
+ return isFunctionLike(D);
+ case attr::SubjectMatchRule_type_alias:
+ return isa<TypedefNameDecl>(D);
+ case attr::SubjectMatchRule_variable:
+ return isa<VarDecl>(D);
+ case attr::SubjectMatchRule_variable_is_thread_local:
+ return isTLSVar(D);
+ case attr::SubjectMatchRule_variable_is_global:
+ return isGlobalVar(D);
+ case attr::SubjectMatchRule_variable_is_parameter:
+ return isa<ParmVarDecl>(D);
+ case attr::SubjectMatchRule_variable_not_is_parameter:
+ return isNonParmVar(D);
+ }
+ llvm_unreachable("Invalid match rule");
+return false;
+}
+
diff --git a/clang-r353983e/include/clang/Sema/AttrParsedAttrKinds.inc b/clang-r353983e/include/clang/Sema/AttrParsedAttrKinds.inc
new file mode 100644
index 00000000..9ed00115
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/AttrParsedAttrKinds.inc
@@ -0,0 +1,4288 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|* *|
+|* Attribute name matcher *|
+|* *|
+|* Automatically generated file, do not edit! *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+static ParsedAttr::Kind getAttrKind(StringRef Name, ParsedAttr::Syntax Syntax) {
+ if (ParsedAttr::AS_GNU == Syntax) {
+ switch (Name.size()) {
+ default: break;
+ case 3: // 3 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "ar", 2) != 0)
+ break;
+ return ParsedAttr::AT_MipsLongCall; // "far"
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+1, "ot", 2) != 0)
+ break;
+ return ParsedAttr::AT_Hot; // "hot"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "cs", 2) != 0)
+ break;
+ return ParsedAttr::AT_Pcs; // "pcs"
+ }
+ break;
+ case 4: // 7 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "old", 3) != 0)
+ break;
+ return ParsedAttr::AT_Cold; // "cold"
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+1, "ost", 3) != 0)
+ break;
+ return ParsedAttr::AT_CUDAHost; // "host"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+1, "ode", 3) != 0)
+ break;
+ return ParsedAttr::AT_Mode; // "mode"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "ear", 3) != 0)
+ break;
+ return ParsedAttr::AT_MipsShortCall; // "near"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "ure", 3) != 0)
+ break;
+ return ParsedAttr::AT_Pure; // "pure"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+1, "sed", 3) != 0)
+ break;
+ return ParsedAttr::AT_Used; // "used"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+1, "eak", 3) != 0)
+ break;
+ return ParsedAttr::AT_Weak; // "weak"
+ }
+ break;
+ case 5: // 6 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "lias", 4) != 0)
+ break;
+ return ParsedAttr::AT_Alias; // "alias"
+ case 'c': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+2, "ecl", 3) != 0)
+ break;
+ return ParsedAttr::AT_CDecl; // "cdecl"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+2, "nst", 3) != 0)
+ break;
+ return ParsedAttr::AT_Const; // "const"
+ }
+ break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+1, "func", 4) != 0)
+ break;
+ return ParsedAttr::AT_IFunc; // "ifunc"
+ case 'n': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "ked", 3) != 0)
+ break;
+ return ParsedAttr::AT_Naked; // "naked"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+2, "svm", 3) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLNoSVM; // "nosvm"
+ }
+ break;
+ }
+ break;
+ case 6: // 15 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+1, "locks", 5) != 0)
+ break;
+ return ParsedAttr::AT_Blocks; // "blocks"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "ommon", 5) != 0)
+ break;
+ return ParsedAttr::AT_Common; // "common"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+1, "evice", 5) != 0)
+ break;
+ return ParsedAttr::AT_CUDADevice; // "device"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "ormat", 5) != 0)
+ break;
+ return ParsedAttr::AT_Format; // "format"
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "lobal", 5) != 0)
+ break;
+ return ParsedAttr::AT_CUDAGlobal; // "global"
+ case 'k': // 1 string to match.
+ if (memcmp(Name.data()+1, "ernel", 5) != 0)
+ break;
+ return ParsedAttr::AT_RenderScriptKernel; // "kernel"
+ case 'm': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "lloc", 4) != 0)
+ break;
+ return ParsedAttr::AT_Restrict; // "malloc"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+2, "ps16", 4) != 0)
+ break;
+ return ParsedAttr::AT_Mips16; // "mips16"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_abi", 4) != 0)
+ break;
+ return ParsedAttr::AT_MSABI; // "ms_abi"
+ }
+ break;
+ case 'p': // 2 strings to match.
+ if (Name[1] != 'a')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+3, "ked", 3) != 0)
+ break;
+ return ParsedAttr::AT_Packed; // "packed"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+3, "cal", 3) != 0)
+ break;
+ return ParsedAttr::AT_Pascal; // "pascal"
+ }
+ break;
+ case 's': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+2, "ared", 4) != 0)
+ break;
+ return ParsedAttr::AT_CUDAShared; // "shared"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+2, "gnal", 4) != 0)
+ break;
+ return ParsedAttr::AT_AVRSignal; // "signal"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "arget", 5) != 0)
+ break;
+ return ParsedAttr::AT_Target; // "target"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+1, "nused", 5) != 0)
+ break;
+ return ParsedAttr::AT_Unused; // "unused"
+ }
+ break;
+ case 7: // 19 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+1, "_const", 6) != 0)
+ break;
+ return ParsedAttr::AT_Const; // "__const"
+ case 'a': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+2, "i_tag", 5) != 0)
+ break;
+ return ParsedAttr::AT_AbiTag; // "abi_tag"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+2, "igned", 5) != 0)
+ break;
+ return ParsedAttr::AT_Aligned; // "aligned"
+ }
+ break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+1, "ounded", 6) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "bounded"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "leanup", 6) != 0)
+ break;
+ return ParsedAttr::AT_Cleanup; // "cleanup"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "latten", 6) != 0)
+ break;
+ return ParsedAttr::AT_Flatten; // "flatten"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+1, "insize", 6) != 0)
+ break;
+ return ParsedAttr::AT_MinSize; // "minsize"
+ case 'n': // 5 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'o': // 4 strings to match.
+ switch (Name[2]) {
+ default: break;
+ case 'd': // 2 strings to match.
+ if (Name[3] != 'e')
+ break;
+ switch (Name[4]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+5, "ug", 2) != 0)
+ break;
+ return ParsedAttr::AT_NoDebug; // "nodebug"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+5, "ef", 2) != 0)
+ break;
+ return ParsedAttr::AT_NoDeref; // "noderef"
+ }
+ break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+3, "null", 4) != 0)
+ break;
+ return ParsedAttr::AT_NonNull; // "nonnull"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+3, "hrow", 4) != 0)
+ break;
+ return ParsedAttr::AT_NoThrow; // "nothrow"
+ }
+ break;
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+2, "_weak", 5) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "nv_weak"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+2, "jc_gc", 5) != 0)
+ break;
+ return ParsedAttr::AT_ObjCGC; // "objc_gc"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+2, "tnone", 5) != 0)
+ break;
+ return ParsedAttr::AT_OptimizeNone; // "optnone"
+ }
+ break;
+ case 'r': // 2 strings to match.
+ if (memcmp(Name.data()+1, "eg", 2) != 0)
+ break;
+ switch (Name[3]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+4, "all", 3) != 0)
+ break;
+ return ParsedAttr::AT_RegCall; // "regcall"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+4, "arm", 3) != 0)
+ break;
+ return ParsedAttr::AT_Regparm; // "regparm"
+ }
+ break;
+ case 's': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+2, "ction", 5) != 0)
+ break;
+ return ParsedAttr::AT_Section; // "section"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+2, "dcall", 5) != 0)
+ break;
+ return ParsedAttr::AT_StdCall; // "stdcall"
+ }
+ break;
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+1, "eakref", 6) != 0)
+ break;
+ return ParsedAttr::AT_WeakRef; // "weakref"
+ }
+ break;
+ case 8: // 16 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'N': // 1 string to match.
+ if (memcmp(Name.data()+1, "SObject", 7) != 0)
+ break;
+ return ParsedAttr::AT_ObjCNSObject; // "NSObject"
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "nnotate", 7) != 0)
+ break;
+ return ParsedAttr::AT_Annotate; // "annotate"
+ case 'c': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "llback", 6) != 0)
+ break;
+ return ParsedAttr::AT_Callback; // "callback"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+2, "nstant", 6) != 0)
+ break;
+ return ParsedAttr::AT_CUDAConstant; // "constant"
+ }
+ break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "astcall", 7) != 0)
+ break;
+ return ParsedAttr::AT_FastCall; // "fastcall"
+ case 'i': // 2 strings to match.
+ if (Name[1] != 'b')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+3, "ction", 5) != 0)
+ break;
+ return ParsedAttr::AT_IBAction; // "ibaction"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+3, "utlet", 5) != 0)
+ break;
+ return ParsedAttr::AT_IBOutlet; // "iboutlet"
+ }
+ break;
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+1, "ockable", 7) != 0)
+ break;
+ return ParsedAttr::AT_Lockable; // "lockable"
+ case 'n': // 5 strings to match.
+ if (Name[1] != 'o')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+3, "ommon", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoCommon; // "nocommon"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+3, "scape", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoEscape; // "noescape"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+3, "nline", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoInline; // "noinline"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+3, "ips16", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoMips16; // "nomips16"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+3, "eturn", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoReturn; // "noreturn"
+ }
+ break;
+ case 's': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+2, "ntinel", 6) != 0)
+ break;
+ return ParsedAttr::AT_Sentinel; // "sentinel"
+ case 'y': // 1 string to match.
+ if (memcmp(Name.data()+2, "sv_abi", 6) != 0)
+ break;
+ return ParsedAttr::AT_SysVABI; // "sysv_abi"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "hiscall", 7) != 0)
+ break;
+ return ParsedAttr::AT_ThisCall; // "thiscall"
+ }
+ break;
+ case 9: // 13 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'd': // 2 strings to match.
+ if (memcmp(Name.data()+1, "ll", 2) != 0)
+ break;
+ switch (Name[3]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+4, "xport", 5) != 0)
+ break;
+ return ParsedAttr::AT_DLLExport; // "dllexport"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+4, "mport", 5) != 0)
+ break;
+ return ParsedAttr::AT_DLLImport; // "dllimport"
+ }
+ break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "nable_if", 8) != 0)
+ break;
+ return ParsedAttr::AT_EnableIf; // "enable_if"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "lag_enum", 8) != 0)
+ break;
+ return ParsedAttr::AT_FlagEnum; // "flag_enum"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+1, "nterrupt", 8) != 0)
+ break;
+ return ParsedAttr::AT_Interrupt; // "interrupt"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+1, "ong_call", 8) != 0)
+ break;
+ return ParsedAttr::AT_MipsLongCall; // "long_call"
+ case 'm': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "y_alias", 7) != 0)
+ break;
+ return ParsedAttr::AT_MayAlias; // "may_alias"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+2, "cromips", 7) != 0)
+ break;
+ return ParsedAttr::AT_MicroMips; // "micromips"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_struct", 7) != 0)
+ break;
+ return ParsedAttr::AT_MSStruct; // "ms_struct"
+ }
+ break;
+ case 's': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+2, "lectany", 7) != 0)
+ break;
+ return ParsedAttr::AT_SelectAny; // "selectany"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+2, "iftcall", 7) != 0)
+ break;
+ return ParsedAttr::AT_SwiftCall; // "swiftcall"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "ls_model", 8) != 0)
+ break;
+ return ParsedAttr::AT_TLSModel; // "tls_model"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+1, "ecreturn", 8) != 0)
+ break;
+ return ParsedAttr::AT_VecReturn; // "vecreturn"
+ }
+ break;
+ case 10: // 15 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+2, "loc_size", 8) != 0)
+ break;
+ return ParsedAttr::AT_AllocSize; // "alloc_size"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+2, "tificial", 8) != 0)
+ break;
+ return ParsedAttr::AT_Artificial; // "artificial"
+ }
+ break;
+ case 'c': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "pability", 8) != 0)
+ break;
+ return ParsedAttr::AT_Capability; // "capability"
+ case 'o': // 2 strings to match.
+ if (Name[2] != 'n')
+ break;
+ switch (Name[3]) {
+ default: break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+4, "umable", 6) != 0)
+ break;
+ return ParsedAttr::AT_Consumable; // "consumable"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+4, "ergent", 6) != 0)
+ break;
+ return ParsedAttr::AT_Convergent; // "convergent"
+ }
+ break;
+ }
+ break;
+ case 'd': // 2 strings to match.
+ if (Name[1] != 'e')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+3, "recated", 7) != 0)
+ break;
+ return ParsedAttr::AT_Deprecated; // "deprecated"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+3, "tructor", 7) != 0)
+ break;
+ return ParsedAttr::AT_Destructor; // "destructor"
+ }
+ break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "ormat_arg", 9) != 0)
+ break;
+ return ParsedAttr::AT_FormatArg; // "format_arg"
+ case 'g': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+2, "u_inline", 8) != 0)
+ break;
+ return ParsedAttr::AT_GNUInline; // "gnu_inline"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+2, "arded_by", 8) != 0)
+ break;
+ return ParsedAttr::AT_GuardedBy; // "guarded_by"
+ }
+ break;
+ case 'n': // 2 strings to match.
+ if (Name[1] != 'o')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+3, "destroy", 7) != 0)
+ break;
+ return ParsedAttr::AT_NoDestroy; // "no_destroy"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+3, "f_check", 7) != 0)
+ break;
+ return ParsedAttr::AT_AnyX86NoCfCheck; // "nocf_check"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "hort_call", 9) != 0)
+ break;
+ return ParsedAttr::AT_MipsShortCall; // "short_call"
+ case 'v': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+2, "ctorcall", 8) != 0)
+ break;
+ return ParsedAttr::AT_VectorCall; // "vectorcall"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+2, "sibility", 8) != 0)
+ break;
+ return ParsedAttr::AT_Visibility; // "visibility"
+ }
+ break;
+ }
+ break;
+ case 11: // 18 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ if (Name[1] != 'l')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+3, "gn_value", 8) != 0)
+ break;
+ return ParsedAttr::AT_AlignValue; // "align_value"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+3, "oc_align", 8) != 0)
+ break;
+ return ParsedAttr::AT_AllocAlign; // "alloc_align"
+ }
+ break;
+ case 'c': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+2, "_consumed", 9) != 0)
+ break;
+ return ParsedAttr::AT_CFConsumed; // "cf_consumed"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+2, "nstructor", 9) != 0)
+ break;
+ return ParsedAttr::AT_Constructor; // "constructor"
+ }
+ break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+1, "iagnose_if", 10) != 0)
+ break;
+ return ParsedAttr::AT_DiagnoseIf; // "diagnose_if"
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "uarded_var", 10) != 0)
+ break;
+ return ParsedAttr::AT_GuardedVar; // "guarded_var"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+1, "mport_name", 10) != 0)
+ break;
+ return ParsedAttr::AT_WebAssemblyImportName; // "import_name"
+ case 'n': // 4 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'o': // 3 strings to match.
+ switch (Name[2]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+3, "sanitize", 8) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitize; // "no_sanitize"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+3, "uplicate", 8) != 0)
+ break;
+ return ParsedAttr::AT_NoDuplicate; // "noduplicate"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+3, "icromips", 8) != 0)
+ break;
+ return ParsedAttr::AT_NoMicroMips; // "nomicromips"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_consumed", 9) != 0)
+ break;
+ return ParsedAttr::AT_NSConsumed; // "ns_consumed"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+2, "jc_bridge", 9) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridge; // "objc_bridge"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_consumed", 9) != 0)
+ break;
+ return ParsedAttr::AT_OSConsumed; // "os_consumed"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "rivial_abi", 10) != 0)
+ break;
+ return ParsedAttr::AT_TrivialABI; // "trivial_abi"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+1, "navailable", 10) != 0)
+ break;
+ return ParsedAttr::AT_Unavailable; // "unavailable"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+1, "ector_size", 10) != 0)
+ break;
+ return ParsedAttr::AT_VectorSize; // "vector_size"
+ case 'w': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "rn_unused", 9) != 0)
+ break;
+ return ParsedAttr::AT_WarnUnused; // "warn_unused"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+2, "ak_import", 9) != 0)
+ break;
+ return ParsedAttr::AT_WeakImport; // "weak_import"
+ }
+ break;
+ }
+ break;
+ case 12: // 6 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "vailability", 11) != 0)
+ break;
+ return ParsedAttr::AT_Availability; // "availability"
+ case 'c': // 2 strings to match.
+ if (memcmp(Name.data()+1, "pu_", 3) != 0)
+ break;
+ switch (Name[4]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+5, "ispatch", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUDispatch; // "cpu_dispatch"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+5, "pecific", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUSpecific; // "cpu_specific"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+2, "jc_boxable", 10) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBoxable; // "objc_boxable"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+2, "erloadable", 10) != 0)
+ break;
+ return ParsedAttr::AT_Overloadable; // "overloadable"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "reserve_all", 11) != 0)
+ break;
+ return ParsedAttr::AT_PreserveAll; // "preserve_all"
+ }
+ break;
+ case 13: // 17 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+2, "dress_space", 11) != 0)
+ break;
+ return ParsedAttr::AT_AddressSpace; // "address_space"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+2, "ways_inline", 11) != 0)
+ break;
+ return ParsedAttr::AT_AlwaysInline; // "always_inline"
+ }
+ break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "allable_when", 12) != 0)
+ break;
+ return ParsedAttr::AT_CallableWhen; // "callable_when"
+ case 'i': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+2, "port_module", 11) != 0)
+ break;
+ return ParsedAttr::AT_WebAssemblyImportModule; // "import_module"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+2, "it_priority", 11) != 0)
+ break;
+ return ParsedAttr::AT_InitPriority; // "init_priority"
+ }
+ break;
+ case 'l': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "unch_bounds", 11) != 0)
+ break;
+ return ParsedAttr::AT_CUDALaunchBounds; // "launch_bounds"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+2, "fetimebound", 11) != 0)
+ break;
+ return ParsedAttr::AT_LifetimeBound; // "lifetimebound"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+2, "ck_returned", 11) != 0)
+ break;
+ return ParsedAttr::AT_LockReturned; // "lock_returned"
+ }
+ break;
+ case 'p': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+2, "eserve_most", 11) != 0)
+ break;
+ return ParsedAttr::AT_PreserveMost; // "preserve_most"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+2, "_guarded_by", 11) != 0)
+ break;
+ return ParsedAttr::AT_PtGuardedBy; // "pt_guarded_by"
+ }
+ break;
+ case 'r': // 2 strings to match.
+ if (Name[1] != 'e')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+3, "nitializes", 10) != 0)
+ break;
+ return ParsedAttr::AT_Reinitializes; // "reinitializes"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+3, "urns_twice", 10) != 0)
+ break;
+ return ParsedAttr::AT_ReturnsTwice; // "returns_twice"
+ }
+ break;
+ case 's': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+2, "t_typestate", 11) != 0)
+ break;
+ return ParsedAttr::AT_SetTypestate; // "set_typestate"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+2, "ift_context", 11) != 0)
+ break;
+ return ParsedAttr::AT_SwiftContext; // "swift_context"
+ }
+ break;
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+1, "ninitialized", 12) != 0)
+ break;
+ return ParsedAttr::AT_Uninitialized; // "uninitialized"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+1, "ec_type_hint", 12) != 0)
+ break;
+ return ParsedAttr::AT_VecTypeHint; // "vec_type_hint"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+1, "ray_log_args", 12) != 0)
+ break;
+ return ParsedAttr::AT_XRayLogArgs; // "xray_log_args"
+ }
+ break;
+ case 14: // 13 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+2, "quired_after", 12) != 0)
+ break;
+ return ParsedAttr::AT_AcquiredAfter; // "acquired_after"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+2, "ways_destroy", 12) != 0)
+ break;
+ return ParsedAttr::AT_AlwaysDestroy; // "always_destroy"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "sume_aligned", 12) != 0)
+ break;
+ return ParsedAttr::AT_AssumeAligned; // "assume_aligned"
+ }
+ break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "udart_builtin", 13) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "cudart_builtin"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+1, "evice_builtin", 13) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "device_builtin"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "ortify_stdlib", 13) != 0)
+ break;
+ return ParsedAttr::AT_FortifyStdLib; // "fortify_stdlib"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+1, "ntel_ocl_bicc", 13) != 0)
+ break;
+ return ParsedAttr::AT_IntelOclBicc; // "intel_ocl_bicc"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+1, "ocks_excluded", 13) != 0)
+ break;
+ return ParsedAttr::AT_LocksExcluded; // "locks_excluded"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "o_split_stack", 13) != 0)
+ break;
+ return ParsedAttr::AT_NoSplitStack; // "no_split_stack"
+ case 'o': // 2 strings to match.
+ if (memcmp(Name.data()+1, "bjc_", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+6, "xception", 8) != 0)
+ break;
+ return ParsedAttr::AT_ObjCException; // "objc_exception"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+6, "wnership", 8) != 0)
+ break;
+ return ParsedAttr::AT_ObjCOwnership; // "objc_ownership"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "t_guarded_var", 13) != 0)
+ break;
+ return ParsedAttr::AT_PtGuardedVar; // "pt_guarded_var"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "est_typestate", 13) != 0)
+ break;
+ return ParsedAttr::AT_TestTypestate; // "test_typestate"
+ }
+ break;
+ case 15: // 13 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+2, "quired_before", 13) != 0)
+ break;
+ return ParsedAttr::AT_AcquiredBefore; // "acquired_before"
+ case 'm': // 2 strings to match.
+ if (memcmp(Name.data()+2, "dgpu_num_", 9) != 0)
+ break;
+ switch (Name[11]) {
+ default: break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+12, "gpr", 3) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUNumSGPR; // "amdgpu_num_sgpr"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+12, "gpr", 3) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUNumVGPR; // "amdgpu_num_vgpr"
+ }
+ break;
+ }
+ break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "xt_vector_type", 14) != 0)
+ break;
+ return ParsedAttr::AT_ExtVectorType; // "ext_vector_type"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "ot_tail_called", 14) != 0)
+ break;
+ return ParsedAttr::AT_NotTailCalled; // "not_tail_called"
+ case 'o': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+2, "jc_root_class", 13) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRootClass; // "objc_root_class"
+ case 'w': // 2 strings to match.
+ if (memcmp(Name.data()+2, "nership_", 8) != 0)
+ break;
+ switch (Name[10]) {
+ default: break;
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+11, "olds", 4) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "ownership_holds"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+11, "akes", 4) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "ownership_takes"
+ }
+ break;
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "aram_typestate", 14) != 0)
+ break;
+ return ParsedAttr::AT_ParamTypestate; // "param_typestate"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "eturns_nonnull", 14) != 0)
+ break;
+ return ParsedAttr::AT_ReturnsNonNull; // "returns_nonnull"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "coped_lockable", 14) != 0)
+ break;
+ return ParsedAttr::AT_ScopedLockable; // "scoped_lockable"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "ype_visibility", 14) != 0)
+ break;
+ return ParsedAttr::AT_TypeVisibility; // "type_visibility"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+1, "nlock_function", 14) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "unlock_function"
+ }
+ break;
+ case 16: // 7 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+1, "nternal_linkage", 15) != 0)
+ break;
+ return ParsedAttr::AT_InternalLinkage; // "internal_linkage"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+1, "in_vector_width", 15) != 0)
+ break;
+ return ParsedAttr::AT_MinVectorWidth; // "min_vector_width"
+ case 'n': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+2, "on_vector_type", 14) != 0)
+ break;
+ return ParsedAttr::AT_NeonVectorType; // "neon_vector_type"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_consumes_self", 14) != 0)
+ break;
+ return ParsedAttr::AT_NSConsumesSelf; // "ns_consumes_self"
+ }
+ break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "s_consumes_this", 15) != 0)
+ break;
+ return ParsedAttr::AT_OSConsumesThis; // "os_consumes_this"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "ass_object_size", 15) != 0)
+ break;
+ return ParsedAttr::AT_PassObjectSize; // "pass_object_size"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "eturn_typestate", 15) != 0)
+ break;
+ return ParsedAttr::AT_ReturnTypestate; // "return_typestate"
+ }
+ break;
+ case 17: // 6 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+2, "alyzer_noreturn", 15) != 0)
+ break;
+ return ParsedAttr::AT_AnalyzerNoReturn; // "analyzer_noreturn"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "sert_capability", 15) != 0)
+ break;
+ return ParsedAttr::AT_AssertCapability; // "assert_capability"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+2, "jc_runtime_name", 15) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRuntimeName; // "objc_runtime_name"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+2, "nership_returns", 15) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "ownership_returns"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "hared_capability", 16) != 0)
+ break;
+ return ParsedAttr::AT_Capability; // "shared_capability"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "ransparent_union", 16) != 0)
+ break;
+ return ParsedAttr::AT_TransparentUnion; // "transparent_union"
+ }
+ break;
+ case 18: // 16 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+2, "rch64_vector_pcs", 16) != 0)
+ break;
+ return ParsedAttr::AT_AArch64VectorPcs; // "aarch64_vector_pcs"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+2, "quire_capability", 16) != 0)
+ break;
+ return ParsedAttr::AT_AcquireCapability; // "acquire_capability"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "sert_shared_lock", 16) != 0)
+ break;
+ return ParsedAttr::AT_AssertSharedLock; // "assert_shared_lock"
+ }
+ break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "arries_dependency", 17) != 0)
+ break;
+ return ParsedAttr::AT_CarriesDependency; // "carries_dependency"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+1, "isable_tail_calls", 17) != 0)
+ break;
+ return ParsedAttr::AT_DisableTailCalls; // "disable_tail_calls"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "num_extensibility", 17) != 0)
+ break;
+ return ParsedAttr::AT_EnumExtensibility; // "enum_extensibility"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+1, "boutletcollection", 17) != 0)
+ break;
+ return ParsedAttr::AT_IBOutletCollection; // "iboutletcollection"
+ case 'n': // 3 strings to match.
+ if (memcmp(Name.data()+1, "o_s", 3) != 0)
+ break;
+ switch (Name[4]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ if (memcmp(Name.data()+5, "nitize_", 7) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+13, "emory", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "no_sanitize_memory"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+13, "hread", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "no_sanitize_thread"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+5, "ack_protector", 13) != 0)
+ break;
+ return ParsedAttr::AT_NoStackProtector; // "no_stack_protector"
+ }
+ break;
+ case 'o': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 2 strings to match.
+ if (memcmp(Name.data()+2, "jc_", 3) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+6, "ethod_family", 12) != 0)
+ break;
+ return ParsedAttr::AT_ObjCMethodFamily; // "objc_method_family"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+6, "onlazy_class", 12) != 0)
+ break;
+ return ParsedAttr::AT_ObjCNonLazyClass; // "objc_nonlazy_class"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+2, "encl_unroll_hint", 16) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLUnrollHint; // "opencl_unroll_hint"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "elease_capability", 17) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "release_capability"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "wift_error_result", 17) != 0)
+ break;
+ return ParsedAttr::AT_SwiftErrorResult; // "swift_error_result"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+1, "arn_unused_result", 17) != 0)
+ break;
+ return ParsedAttr::AT_WarnUnusedResult; // "warn_unused_result"
+ }
+ break;
+ case 19: // 11 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "mdgpu_waves_per_eu", 18) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUWavesPerEU; // "amdgpu_waves_per_eu"
+ case 'c': // 3 strings to match.
+ if (memcmp(Name.data()+1, "f_", 2) != 0)
+ break;
+ switch (Name[3]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+4, "udited_transfer", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFAuditedTransfer; // "cf_audited_transfer"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+4, "eturns_retained", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFReturnsRetained; // "cf_returns_retained"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+4, "nknown_transfer", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFUnknownTransfer; // "cf_unknown_transfer"
+ }
+ break;
+ case 'n': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+2, "_sanitize_address", 17) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "no_sanitize_address"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_returns_retained", 17) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsRetained; // "ns_returns_retained"
+ }
+ break;
+ case 'o': // 4 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 3 strings to match.
+ if (memcmp(Name.data()+2, "jc_", 3) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'b': // 2 strings to match.
+ if (memcmp(Name.data()+6, "ridge_", 6) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+13, "utable", 6) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridgeMutable; // "objc_bridge_mutable"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+13, "elated", 6) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridgeRelated; // "objc_bridge_related"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+6, "equires_super", 13) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRequiresSuper; // "objc_requires_super"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_returns_retained", 17) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetained; // "os_returns_retained"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "equires_capability", 18) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "requires_capability"
+ }
+ break;
+ case 20: // 5 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "eon_polyvector_type", 19) != 0)
+ break;
+ return ParsedAttr::AT_NeonPolyVectorType; // "neon_polyvector_type"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "bjc_runtime_visible", 19) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRuntimeVisible; // "objc_runtime_visible"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "eqd_work_group_size", 19) != 0)
+ break;
+ return ParsedAttr::AT_ReqdWorkGroupSize; // "reqd_work_group_size"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "hared_lock_function", 19) != 0)
+ break;
+ return ParsedAttr::AT_AcquireCapability; // "shared_lock_function"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+1, "ork_group_size_hint", 19) != 0)
+ break;
+ return ParsedAttr::AT_WorkGroupSizeHint; // "work_group_size_hint"
+ }
+ break;
+ case 21: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "ssert_exclusive_lock", 20) != 0)
+ break;
+ return ParsedAttr::AT_AssertExclusiveLock; // "assert_exclusive_lock"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+1, "to_visibility_public", 20) != 0)
+ break;
+ return ParsedAttr::AT_LTOVisibilityPublic; // "lto_visibility_public"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "bjc_precise_lifetime", 20) != 0)
+ break;
+ return ParsedAttr::AT_ObjCPreciseLifetime; // "objc_precise_lifetime"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "ointer_with_type_tag", 20) != 0)
+ break;
+ return ParsedAttr::AT_ArgumentWithTypeTag; // "pointer_with_type_tag"
+ case 's': // 2 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+2, "ared_locks_required", 19) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "shared_locks_required"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+2, "ift_indirect_result", 19) != 0)
+ break;
+ return ParsedAttr::AT_SwiftIndirectResult; // "swift_indirect_result"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "ype_tag_for_datatype", 20) != 0)
+ break;
+ return ParsedAttr::AT_TypeTagForDatatype; // "type_tag_for_datatype"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+1, "ray_never_instrument", 20) != 0)
+ break;
+ return ParsedAttr::AT_XRayInstrument; // "xray_never_instrument"
+ }
+ break;
+ case 22: // 6 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "rgument_with_type_tag", 21) != 0)
+ break;
+ return ParsedAttr::AT_ArgumentWithTypeTag; // "argument_with_type_tag"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "xternal_source_symbol", 21) != 0)
+ break;
+ return ParsedAttr::AT_ExternalSourceSymbol; // "external_source_symbol"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "o_instrument_function", 21) != 0)
+ break;
+ return ParsedAttr::AT_NoInstrumentFunction; // "no_instrument_function"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "bjc_independent_class", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCIndependentClass; // "objc_independent_class"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "ry_acquire_capability", 21) != 0)
+ break;
+ return ParsedAttr::AT_TryAcquireCapability; // "try_acquire_capability"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+1, "ray_always_instrument", 21) != 0)
+ break;
+ return ParsedAttr::AT_XRayInstrument; // "xray_always_instrument"
+ }
+ break;
+ case 23: // 7 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "f_returns_not_retained", 22) != 0)
+ break;
+ return ParsedAttr::AT_CFReturnsNotRetained; // "cf_returns_not_retained"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "xclusive_lock_function", 22) != 0)
+ break;
+ return ParsedAttr::AT_AcquireCapability; // "exclusive_lock_function"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+1, "orce_align_arg_pointer", 22) != 0)
+ break;
+ return ParsedAttr::AT_X86ForceAlignArgPointer; // "force_align_arg_pointer"
+ case 'n': // 2 strings to match.
+ if (memcmp(Name.data()+1, "s_returns_", 10) != 0)
+ break;
+ switch (Name[11]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+12, "utoreleased", 11) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsAutoreleased; // "ns_returns_autoreleased"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+12, "ot_retained", 11) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsNotRetained; // "ns_returns_not_retained"
+ }
+ break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "s_returns_not_retained", 22) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsNotRetained; // "os_returns_not_retained"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "hared_trylock_function", 22) != 0)
+ break;
+ return ParsedAttr::AT_SharedTrylockFunction; // "shared_trylock_function"
+ }
+ break;
+ case 24: // 3 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "ssert_shared_capability", 23) != 0)
+ break;
+ return ParsedAttr::AT_AssertCapability; // "assert_shared_capability"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "xclusive_locks_required", 23) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "exclusive_locks_required"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "bjc_externally_retained", 23) != 0)
+ break;
+ return ParsedAttr::AT_ObjCExternallyRetained; // "objc_externally_retained"
+ }
+ break;
+ case 25: // 5 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "cquire_shared_capability", 24) != 0)
+ break;
+ return ParsedAttr::AT_AcquireCapability; // "acquire_shared_capability"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+1, "ntel_reqd_sub_group_size", 24) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLIntelReqdSubGroupSize; // "intel_reqd_sub_group_size"
+ case 'n': // 2 strings to match.
+ if (memcmp(Name.data()+1, "o_", 2) != 0)
+ break;
+ switch (Name[3]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+4, "aller_saved_registers", 21) != 0)
+ break;
+ return ParsedAttr::AT_AnyX86NoCallerSavedRegisters; // "no_caller_saved_registers"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+4, "hread_safety_analysis", 21) != 0)
+ break;
+ return ParsedAttr::AT_NoThreadSafetyAnalysis; // "no_thread_safety_analysis"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "elease_shared_capability", 24) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "release_shared_capability"
+ }
+ break;
+ case 26: // 7 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "onsumable_auto_cast_state", 25) != 0)
+ break;
+ return ParsedAttr::AT_ConsumableAutoCast; // "consumable_auto_cast_state"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "xclusive_trylock_function", 25) != 0)
+ break;
+ return ParsedAttr::AT_ExclusiveTrylockFunction; // "exclusive_trylock_function"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "o_address_safety_analysis", 25) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "no_address_safety_analysis"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "bjc_returns_inner_pointer", 25) != 0)
+ break;
+ return ParsedAttr::AT_ObjCReturnsInnerPointer; // "objc_returns_inner_pointer"
+ case 'r': // 2 strings to match.
+ if (Name[1] != 'e')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+3, "ease_generic_capability", 23) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "release_generic_capability"
+ case 'q': // 1 string to match.
+ if (memcmp(Name.data()+3, "uires_shared_capability", 23) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "requires_shared_capability"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "peculative_load_hardening", 25) != 0)
+ break;
+ return ParsedAttr::AT_SpeculativeLoadHardening; // "speculative_load_hardening"
+ }
+ break;
+ case 27: // 6 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "mdgpu_flat_work_group_size", 26) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUFlatWorkGroupSize; // "amdgpu_flat_work_group_size"
+ case 'd': // 2 strings to match.
+ if (memcmp(Name.data()+1, "evice_builtin_", 14) != 0)
+ break;
+ switch (Name[15]) {
+ default: break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+16, "urface_type", 11) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "device_builtin_surface_type"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+16, "exture_type", 11) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "device_builtin_texture_type"
+ }
+ break;
+ case 'o': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'b': // 2 strings to match.
+ if (memcmp(Name.data()+2, "jc_", 3) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+6, "esignated_initializer", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCDesignatedInitializer; // "objc_designated_initializer"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+6, "ubclassing_restricted", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCSubclassingRestricted; // "objc_subclassing_restricted"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "_returns_retained_on_zero", 25) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetainedOnZero; // "os_returns_retained_on_zero"
+ }
+ break;
+ }
+ break;
+ case 28: // 1 string to match.
+ if (memcmp(Name.data()+0, "consumable_set_state_on_read", 28) != 0)
+ break;
+ return ParsedAttr::AT_ConsumableSetOnRead; // "consumable_set_state_on_read"
+ case 29: // 2 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "o_speculative_load_hardening", 28) != 0)
+ break;
+ return ParsedAttr::AT_NoSpeculativeLoadHardening; // "no_speculative_load_hardening"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+1, "ry_acquire_shared_capability", 28) != 0)
+ break;
+ return ParsedAttr::AT_TryAcquireCapability; // "try_acquire_shared_capability"
+ }
+ break;
+ case 31: // 2 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "s_returns_retained_on_non_zero", 30) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetainedOnNonZero; // "os_returns_retained_on_non_zero"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "equire_constant_initialization", 30) != 0)
+ break;
+ return ParsedAttr::AT_RequireConstantInit; // "require_constant_initialization"
+ }
+ break;
+ case 34: // 1 string to match.
+ if (memcmp(Name.data()+0, "objc_requires_property_definitions", 34) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRequiresPropertyDefs; // "objc_requires_property_definitions"
+ case 35: // 2 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+1, "xclude_from_explicit_instantiation", 34) != 0)
+ break;
+ return ParsedAttr::AT_ExcludeFromExplicitInstantiation; // "exclude_from_explicit_instantiation"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+1, "bjc_arc_weak_reference_unavailable", 34) != 0)
+ break;
+ return ParsedAttr::AT_ArcWeakrefUnavailable; // "objc_arc_weak_reference_unavailable"
+ }
+ break;
+ case 46: // 1 string to match.
+ if (memcmp(Name.data()+0, "objc_protocol_requires_explicit_implementation", 46) != 0)
+ break;
+ return ParsedAttr::AT_ObjCExplicitProtocolImpl; // "objc_protocol_requires_explicit_implementation"
+ }
+ } else if (ParsedAttr::AS_Declspec == Syntax) {
+ switch (Name.size()) {
+ default: break;
+ case 4: // 1 string to match.
+ if (memcmp(Name.data()+0, "uuid", 4) != 0)
+ break;
+ return ParsedAttr::AT_Uuid; // "uuid"
+ case 5: // 2 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "lign", 4) != 0)
+ break;
+ return ParsedAttr::AT_Aligned; // "align"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+1, "aked", 4) != 0)
+ break;
+ return ParsedAttr::AT_Naked; // "naked"
+ }
+ break;
+ case 6: // 1 string to match.
+ if (memcmp(Name.data()+0, "thread", 6) != 0)
+ break;
+ return ParsedAttr::AT_Thread; // "thread"
+ case 7: // 2 strings to match.
+ if (memcmp(Name.data()+0, "no", 2) != 0)
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+3, "lias", 4) != 0)
+ break;
+ return ParsedAttr::AT_NoAlias; // "noalias"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+3, "hrow", 4) != 0)
+ break;
+ return ParsedAttr::AT_NoThrow; // "nothrow"
+ }
+ break;
+ case 8: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+1, "_host__", 7) != 0)
+ break;
+ return ParsedAttr::AT_CUDAHost; // "__host__"
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "llocate", 7) != 0)
+ break;
+ return ParsedAttr::AT_Section; // "allocate"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "ode_seg", 7) != 0)
+ break;
+ return ParsedAttr::AT_CodeSeg; // "code_seg"
+ case 'n': // 3 strings to match.
+ if (Name[1] != 'o')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+3, "nline", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoInline; // "noinline"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+3, "eturn", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoReturn; // "noreturn"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+3, "table", 5) != 0)
+ break;
+ return ParsedAttr::AT_MSNoVTable; // "novtable"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "roperty", 7) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "property"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "estrict", 7) != 0)
+ break;
+ return ParsedAttr::AT_Restrict; // "restrict"
+ }
+ break;
+ case 9: // 3 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'd': // 2 strings to match.
+ if (memcmp(Name.data()+1, "ll", 2) != 0)
+ break;
+ switch (Name[3]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+4, "xport", 5) != 0)
+ break;
+ return ParsedAttr::AT_DLLExport; // "dllexport"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+4, "mport", 5) != 0)
+ break;
+ return ParsedAttr::AT_DLLImport; // "dllimport"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+1, "electany", 8) != 0)
+ break;
+ return ParsedAttr::AT_SelectAny; // "selectany"
+ }
+ break;
+ case 10: // 4 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 3 strings to match.
+ if (Name[1] != '_')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+3, "evice__", 7) != 0)
+ break;
+ return ParsedAttr::AT_CUDADevice; // "__device__"
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+3, "lobal__", 7) != 0)
+ break;
+ return ParsedAttr::AT_CUDAGlobal; // "__global__"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+3, "hared__", 7) != 0)
+ break;
+ return ParsedAttr::AT_CUDAShared; // "__shared__"
+ }
+ break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+1, "eprecated", 9) != 0)
+ break;
+ return ParsedAttr::AT_Deprecated; // "deprecated"
+ }
+ break;
+ case 11: // 1 string to match.
+ if (memcmp(Name.data()+0, "empty_bases", 11) != 0)
+ break;
+ return ParsedAttr::AT_EmptyBases; // "empty_bases"
+ case 12: // 3 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+1, "_constant__", 11) != 0)
+ break;
+ return ParsedAttr::AT_CUDAConstant; // "__constant__"
+ case 'c': // 2 strings to match.
+ if (memcmp(Name.data()+1, "pu_", 3) != 0)
+ break;
+ switch (Name[4]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+5, "ispatch", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUDispatch; // "cpu_dispatch"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+5, "pecific", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUSpecific; // "cpu_specific"
+ }
+ break;
+ }
+ break;
+ case 14: // 1 string to match.
+ if (memcmp(Name.data()+0, "layout_version", 14) != 0)
+ break;
+ return ParsedAttr::AT_LayoutVersion; // "layout_version"
+ case 17: // 1 string to match.
+ if (memcmp(Name.data()+0, "__launch_bounds__", 17) != 0)
+ break;
+ return ParsedAttr::AT_CUDALaunchBounds; // "__launch_bounds__"
+ case 18: // 2 strings to match.
+ if (memcmp(Name.data()+0, "__", 2) != 0)
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+3, "udart_builtin__", 15) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "__cudart_builtin__"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+3, "evice_builtin__", 15) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "__device_builtin__"
+ }
+ break;
+ case 31: // 2 strings to match.
+ if (memcmp(Name.data()+0, "__device_builtin_", 17) != 0)
+ break;
+ switch (Name[17]) {
+ default: break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+18, "urface_type__", 13) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "__device_builtin_surface_type__"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+18, "exture_type__", 13) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "__device_builtin_texture_type__"
+ }
+ break;
+ }
+ } else if (ParsedAttr::AS_Microsoft == Syntax) {
+ switch (Name.size()) {
+ default: break;
+ case 4: // 1 string to match.
+ if (memcmp(Name.data()+0, "uuid", 4) != 0)
+ break;
+ return ParsedAttr::AT_Uuid; // "uuid"
+ }
+ } else if (ParsedAttr::AS_CXX11 == Syntax) {
+ switch (Name.size()) {
+ default: break;
+ case 8: // 3 strings to match.
+ if (memcmp(Name.data()+0, "gnu::", 5) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+6, "ar", 2) != 0)
+ break;
+ return ParsedAttr::AT_MipsLongCall; // "gnu::far"
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+6, "ot", 2) != 0)
+ break;
+ return ParsedAttr::AT_Hot; // "gnu::hot"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+6, "cs", 2) != 0)
+ break;
+ return ParsedAttr::AT_Pcs; // "gnu::pcs"
+ }
+ break;
+ case 9: // 6 strings to match.
+ if (memcmp(Name.data()+0, "gnu::", 5) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+6, "old", 3) != 0)
+ break;
+ return ParsedAttr::AT_Cold; // "gnu::cold"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+6, "ode", 3) != 0)
+ break;
+ return ParsedAttr::AT_Mode; // "gnu::mode"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+6, "ear", 3) != 0)
+ break;
+ return ParsedAttr::AT_MipsShortCall; // "gnu::near"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+6, "ure", 3) != 0)
+ break;
+ return ParsedAttr::AT_Pure; // "gnu::pure"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+6, "sed", 3) != 0)
+ break;
+ return ParsedAttr::AT_Used; // "gnu::used"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+6, "eak", 3) != 0)
+ break;
+ return ParsedAttr::AT_Weak; // "gnu::weak"
+ }
+ break;
+ case 10: // 6 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":noreturn", 9) != 0)
+ break;
+ return ParsedAttr::AT_CXX11NoReturn; // "::noreturn"
+ case 'g': // 5 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+6, "lias", 4) != 0)
+ break;
+ return ParsedAttr::AT_Alias; // "gnu::alias"
+ case 'c': // 2 strings to match.
+ switch (Name[6]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+7, "ecl", 3) != 0)
+ break;
+ return ParsedAttr::AT_CDecl; // "gnu::cdecl"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+7, "nst", 3) != 0)
+ break;
+ return ParsedAttr::AT_Const; // "gnu::const"
+ }
+ break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+6, "func", 4) != 0)
+ break;
+ return ParsedAttr::AT_IFunc; // "gnu::ifunc"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+6, "aked", 4) != 0)
+ break;
+ return ParsedAttr::AT_Naked; // "gnu::naked"
+ }
+ break;
+ }
+ break;
+ case 11: // 10 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":nodiscard", 10) != 0)
+ break;
+ return ParsedAttr::AT_WarnUnusedResult; // "::nodiscard"
+ case 'g': // 9 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+6, "ommon", 5) != 0)
+ break;
+ return ParsedAttr::AT_Common; // "gnu::common"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+6, "ormat", 5) != 0)
+ break;
+ return ParsedAttr::AT_Format; // "gnu::format"
+ case 'm': // 3 strings to match.
+ switch (Name[6]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+7, "lloc", 4) != 0)
+ break;
+ return ParsedAttr::AT_Restrict; // "gnu::malloc"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+7, "ps16", 4) != 0)
+ break;
+ return ParsedAttr::AT_Mips16; // "gnu::mips16"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+7, "_abi", 4) != 0)
+ break;
+ return ParsedAttr::AT_MSABI; // "gnu::ms_abi"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+6, "acked", 5) != 0)
+ break;
+ return ParsedAttr::AT_Packed; // "gnu::packed"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+6, "ignal", 5) != 0)
+ break;
+ return ParsedAttr::AT_AVRSignal; // "gnu::signal"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+6, "arget", 5) != 0)
+ break;
+ return ParsedAttr::AT_Target; // "gnu::target"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+6, "nused", 5) != 0)
+ break;
+ return ParsedAttr::AT_Unused; // "gnu::unused"
+ }
+ break;
+ }
+ break;
+ case 12: // 14 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":deprecated", 11) != 0)
+ break;
+ return ParsedAttr::AT_Deprecated; // "::deprecated"
+ case 'g': // 13 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+6, "_const", 6) != 0)
+ break;
+ return ParsedAttr::AT_Const; // "gnu::__const"
+ case 'a': // 2 strings to match.
+ switch (Name[6]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+7, "i_tag", 5) != 0)
+ break;
+ return ParsedAttr::AT_AbiTag; // "gnu::abi_tag"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+7, "igned", 5) != 0)
+ break;
+ return ParsedAttr::AT_Aligned; // "gnu::aligned"
+ }
+ break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+6, "leanup", 6) != 0)
+ break;
+ return ParsedAttr::AT_Cleanup; // "gnu::cleanup"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+6, "latten", 6) != 0)
+ break;
+ return ParsedAttr::AT_Flatten; // "gnu::flatten"
+ case 'n': // 3 strings to match.
+ if (Name[6] != 'o')
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+8, "ebug", 4) != 0)
+ break;
+ return ParsedAttr::AT_NoDebug; // "gnu::nodebug"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "null", 4) != 0)
+ break;
+ return ParsedAttr::AT_NonNull; // "gnu::nonnull"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "hrow", 4) != 0)
+ break;
+ return ParsedAttr::AT_NoThrow; // "gnu::nothrow"
+ }
+ break;
+ case 'r': // 2 strings to match.
+ if (memcmp(Name.data()+6, "eg", 2) != 0)
+ break;
+ switch (Name[8]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+9, "all", 3) != 0)
+ break;
+ return ParsedAttr::AT_RegCall; // "gnu::regcall"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+9, "arm", 3) != 0)
+ break;
+ return ParsedAttr::AT_Regparm; // "gnu::regparm"
+ }
+ break;
+ case 's': // 2 strings to match.
+ switch (Name[6]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+7, "ction", 5) != 0)
+ break;
+ return ParsedAttr::AT_Section; // "gnu::section"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+7, "dcall", 5) != 0)
+ break;
+ return ParsedAttr::AT_StdCall; // "gnu::stdcall"
+ }
+ break;
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+6, "eakref", 6) != 0)
+ break;
+ return ParsedAttr::AT_WeakRef; // "gnu::weakref"
+ }
+ break;
+ }
+ break;
+ case 13: // 12 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":fallthrough", 12) != 0)
+ break;
+ return ParsedAttr::AT_FallThrough; // "::fallthrough"
+ case 'c': // 2 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+8, "locks", 5) != 0)
+ break;
+ return ParsedAttr::AT_Blocks; // "clang::blocks"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "ascal", 5) != 0)
+ break;
+ return ParsedAttr::AT_Pascal; // "clang::pascal"
+ }
+ break;
+ case 'g': // 9 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'n': // 8 strings to match.
+ if (memcmp(Name.data()+2, "u::", 3) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+6, "astcall", 7) != 0)
+ break;
+ return ParsedAttr::AT_FastCall; // "gnu::fastcall"
+ case 'n': // 4 strings to match.
+ if (Name[6] != 'o')
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "ommon", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoCommon; // "gnu::nocommon"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "nline", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoInline; // "gnu::noinline"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+8, "ips16", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoMips16; // "gnu::nomips16"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+8, "eturn", 5) != 0)
+ break;
+ return ParsedAttr::AT_NoReturn; // "gnu::noreturn"
+ }
+ break;
+ case 's': // 2 strings to match.
+ switch (Name[6]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+7, "ntinel", 6) != 0)
+ break;
+ return ParsedAttr::AT_Sentinel; // "gnu::sentinel"
+ case 'y': // 1 string to match.
+ if (memcmp(Name.data()+7, "sv_abi", 6) != 0)
+ break;
+ return ParsedAttr::AT_SysVABI; // "gnu::sysv_abi"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+6, "hiscall", 7) != 0)
+ break;
+ return ParsedAttr::AT_ThisCall; // "gnu::thiscall"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "l::suppress", 11) != 0)
+ break;
+ return ParsedAttr::AT_Suppress; // "gsl::suppress"
+ }
+ break;
+ }
+ break;
+ case 14: // 14 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":maybe_unused", 13) != 0)
+ break;
+ return ParsedAttr::AT_Unused; // "::maybe_unused"
+ case 'c': // 4 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+8, "insize", 6) != 0)
+ break;
+ return ParsedAttr::AT_MinSize; // "clang::minsize"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "oderef", 6) != 0)
+ break;
+ return ParsedAttr::AT_NoDeref; // "clang::noderef"
+ case 'o': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_gc", 5) != 0)
+ break;
+ return ParsedAttr::AT_ObjCGC; // "clang::objc_gc"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+9, "tnone", 5) != 0)
+ break;
+ return ParsedAttr::AT_OptimizeNone; // "clang::optnone"
+ }
+ break;
+ }
+ break;
+ case 'g': // 9 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'd': // 2 strings to match.
+ if (memcmp(Name.data()+6, "ll", 2) != 0)
+ break;
+ switch (Name[8]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+9, "xport", 5) != 0)
+ break;
+ return ParsedAttr::AT_DLLExport; // "gnu::dllexport"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+9, "mport", 5) != 0)
+ break;
+ return ParsedAttr::AT_DLLImport; // "gnu::dllimport"
+ }
+ break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+6, "nterrupt", 8) != 0)
+ break;
+ return ParsedAttr::AT_Interrupt; // "gnu::interrupt"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+6, "ong_call", 8) != 0)
+ break;
+ return ParsedAttr::AT_MipsLongCall; // "gnu::long_call"
+ case 'm': // 3 strings to match.
+ switch (Name[6]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+7, "y_alias", 7) != 0)
+ break;
+ return ParsedAttr::AT_MayAlias; // "gnu::may_alias"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+7, "cromips", 7) != 0)
+ break;
+ return ParsedAttr::AT_MicroMips; // "gnu::micromips"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+7, "_struct", 7) != 0)
+ break;
+ return ParsedAttr::AT_MSStruct; // "gnu::ms_struct"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+6, "electany", 8) != 0)
+ break;
+ return ParsedAttr::AT_SelectAny; // "gnu::selectany"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+6, "ls_model", 8) != 0)
+ break;
+ return ParsedAttr::AT_TLSModel; // "gnu::tls_model"
+ }
+ break;
+ }
+ break;
+ case 15: // 15 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 6 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'N': // 1 string to match.
+ if (memcmp(Name.data()+8, "SObject", 7) != 0)
+ break;
+ return ParsedAttr::AT_ObjCNSObject; // "clang::NSObject"
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "nnotate", 7) != 0)
+ break;
+ return ParsedAttr::AT_Annotate; // "clang::annotate"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "allback", 7) != 0)
+ break;
+ return ParsedAttr::AT_Callback; // "clang::callback"
+ case 'i': // 2 strings to match.
+ if (Name[8] != 'b')
+ break;
+ switch (Name[9]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+10, "ction", 5) != 0)
+ break;
+ return ParsedAttr::AT_IBAction; // "clang::ibaction"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+10, "utlet", 5) != 0)
+ break;
+ return ParsedAttr::AT_IBOutlet; // "clang::iboutlet"
+ }
+ break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "oescape", 7) != 0)
+ break;
+ return ParsedAttr::AT_NoEscape; // "clang::noescape"
+ }
+ break;
+ case 'g': // 9 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ switch (Name[6]) {
+ default: break;
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+7, "loc_size", 8) != 0)
+ break;
+ return ParsedAttr::AT_AllocSize; // "gnu::alloc_size"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+7, "tificial", 8) != 0)
+ break;
+ return ParsedAttr::AT_Artificial; // "gnu::artificial"
+ }
+ break;
+ case 'd': // 2 strings to match.
+ if (Name[6] != 'e')
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "recated", 7) != 0)
+ break;
+ return ParsedAttr::AT_Deprecated; // "gnu::deprecated"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "tructor", 7) != 0)
+ break;
+ return ParsedAttr::AT_Destructor; // "gnu::destructor"
+ }
+ break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+6, "ormat_arg", 9) != 0)
+ break;
+ return ParsedAttr::AT_FormatArg; // "gnu::format_arg"
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+6, "nu_inline", 9) != 0)
+ break;
+ return ParsedAttr::AT_GNUInline; // "gnu::gnu_inline"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+6, "ocf_check", 9) != 0)
+ break;
+ return ParsedAttr::AT_AnyX86NoCfCheck; // "gnu::nocf_check"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+6, "hort_call", 9) != 0)
+ break;
+ return ParsedAttr::AT_MipsShortCall; // "gnu::short_call"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+6, "isibility", 9) != 0)
+ break;
+ return ParsedAttr::AT_Visibility; // "gnu::visibility"
+ }
+ break;
+ }
+ break;
+ case 16: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 3 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+8, "lag_enum", 8) != 0)
+ break;
+ return ParsedAttr::AT_FlagEnum; // "clang::flag_enum"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "wiftcall", 8) != 0)
+ break;
+ return ParsedAttr::AT_SwiftCall; // "clang::swiftcall"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+8, "ecreturn", 8) != 0)
+ break;
+ return ParsedAttr::AT_VecReturn; // "clang::vecreturn"
+ }
+ break;
+ case 'g': // 5 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+6, "lloc_align", 10) != 0)
+ break;
+ return ParsedAttr::AT_AllocAlign; // "gnu::alloc_align"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+6, "onstructor", 10) != 0)
+ break;
+ return ParsedAttr::AT_Constructor; // "gnu::constructor"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+6, "omicromips", 10) != 0)
+ break;
+ return ParsedAttr::AT_NoMicroMips; // "gnu::nomicromips"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+6, "ector_size", 10) != 0)
+ break;
+ return ParsedAttr::AT_VectorSize; // "gnu::vector_size"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+6, "arn_unused", 10) != 0)
+ break;
+ return ParsedAttr::AT_WarnUnused; // "gnu::warn_unused"
+ }
+ break;
+ }
+ break;
+ case 17: // 5 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 3 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+9, "pability", 8) != 0)
+ break;
+ return ParsedAttr::AT_Capability; // "clang::capability"
+ case 'o': // 2 strings to match.
+ if (Name[9] != 'n')
+ break;
+ switch (Name[10]) {
+ default: break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+11, "umable", 6) != 0)
+ break;
+ return ParsedAttr::AT_Consumable; // "clang::consumable"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+11, "ergent", 6) != 0)
+ break;
+ return ParsedAttr::AT_Convergent; // "clang::convergent"
+ }
+ break;
+ }
+ break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "o_destroy", 9) != 0)
+ break;
+ return ParsedAttr::AT_NoDestroy; // "clang::no_destroy"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+8, "ectorcall", 9) != 0)
+ break;
+ return ParsedAttr::AT_VectorCall; // "clang::vectorcall"
+ }
+ break;
+ case 18: // 15 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 12 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "f_consumed", 10) != 0)
+ break;
+ return ParsedAttr::AT_CFConsumed; // "clang::cf_consumed"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+8, "allthrough", 10) != 0)
+ break;
+ return ParsedAttr::AT_FallThrough; // "clang::fallthrough"
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+8, "uarded_var", 10) != 0)
+ break;
+ return ParsedAttr::AT_GuardedVar; // "clang::guarded_var"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "mport_name", 10) != 0)
+ break;
+ return ParsedAttr::AT_WebAssemblyImportName; // "clang::import_name"
+ case 'n': // 3 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'o': // 2 strings to match.
+ switch (Name[9]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+10, "sanitize", 8) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitize; // "clang::no_sanitize"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+10, "uplicate", 8) != 0)
+ break;
+ return ParsedAttr::AT_NoDuplicate; // "clang::noduplicate"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_consumed", 9) != 0)
+ break;
+ return ParsedAttr::AT_NSConsumed; // "clang::ns_consumed"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_bridge", 9) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridge; // "clang::objc_bridge"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_consumed", 9) != 0)
+ break;
+ return ParsedAttr::AT_OSConsumed; // "clang::os_consumed"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "rivial_abi", 10) != 0)
+ break;
+ return ParsedAttr::AT_TrivialABI; // "clang::trivial_abi"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+8, "navailable", 10) != 0)
+ break;
+ return ParsedAttr::AT_Unavailable; // "clang::unavailable"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+8, "eak_import", 10) != 0)
+ break;
+ return ParsedAttr::AT_WeakImport; // "clang::weak_import"
+ }
+ break;
+ case 'g': // 3 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+6, "lways_inline", 12) != 0)
+ break;
+ return ParsedAttr::AT_AlwaysInline; // "gnu::always_inline"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+6, "nit_priority", 12) != 0)
+ break;
+ return ParsedAttr::AT_InitPriority; // "gnu::init_priority"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+6, "eturns_twice", 12) != 0)
+ break;
+ return ParsedAttr::AT_ReturnsTwice; // "gnu::returns_twice"
+ }
+ break;
+ }
+ break;
+ case 19: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 6 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "vailability", 11) != 0)
+ break;
+ return ParsedAttr::AT_Availability; // "clang::availability"
+ case 'c': // 2 strings to match.
+ if (memcmp(Name.data()+8, "pu_", 3) != 0)
+ break;
+ switch (Name[11]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+12, "ispatch", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUDispatch; // "clang::cpu_dispatch"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+12, "pecific", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUSpecific; // "clang::cpu_specific"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_boxable", 10) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBoxable; // "clang::objc_boxable"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+9, "erloadable", 10) != 0)
+ break;
+ return ParsedAttr::AT_Overloadable; // "clang::overloadable"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "reserve_all", 11) != 0)
+ break;
+ return ParsedAttr::AT_PreserveAll; // "clang::preserve_all"
+ }
+ break;
+ case 'g': // 2 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+6, "ssume_aligned", 13) != 0)
+ break;
+ return ParsedAttr::AT_AssumeAligned; // "gnu::assume_aligned"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+6, "o_split_stack", 13) != 0)
+ break;
+ return ParsedAttr::AT_NoSplitStack; // "gnu::no_split_stack"
+ }
+ break;
+ }
+ break;
+ case 20: // 12 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":carries_dependency", 19) != 0)
+ break;
+ return ParsedAttr::AT_CarriesDependency; // "::carries_dependency"
+ case 'c': // 10 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "ddress_space", 12) != 0)
+ break;
+ return ParsedAttr::AT_AddressSpace; // "clang::address_space"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "allable_when", 12) != 0)
+ break;
+ return ParsedAttr::AT_CallableWhen; // "clang::callable_when"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "mport_module", 12) != 0)
+ break;
+ return ParsedAttr::AT_WebAssemblyImportModule; // "clang::import_module"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+8, "ifetimebound", 12) != 0)
+ break;
+ return ParsedAttr::AT_LifetimeBound; // "clang::lifetimebound"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "reserve_most", 12) != 0)
+ break;
+ return ParsedAttr::AT_PreserveMost; // "clang::preserve_most"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+8, "einitializes", 12) != 0)
+ break;
+ return ParsedAttr::AT_Reinitializes; // "clang::reinitializes"
+ case 's': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+9, "t_typestate", 11) != 0)
+ break;
+ return ParsedAttr::AT_SetTypestate; // "clang::set_typestate"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+9, "ift_context", 11) != 0)
+ break;
+ return ParsedAttr::AT_SwiftContext; // "clang::swift_context"
+ }
+ break;
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+8, "ninitialized", 12) != 0)
+ break;
+ return ParsedAttr::AT_Uninitialized; // "clang::uninitialized"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+8, "ray_log_args", 12) != 0)
+ break;
+ return ParsedAttr::AT_XRayLogArgs; // "clang::xray_log_args"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "nu::returns_nonnull", 19) != 0)
+ break;
+ return ParsedAttr::AT_ReturnsNonNull; // "gnu::returns_nonnull"
+ }
+ break;
+ case 21: // 7 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "lways_destroy", 13) != 0)
+ break;
+ return ParsedAttr::AT_AlwaysDestroy; // "clang::always_destroy"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+8, "ortify_stdlib", 13) != 0)
+ break;
+ return ParsedAttr::AT_FortifyStdLib; // "clang::fortify_stdlib"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "ntel_ocl_bicc", 13) != 0)
+ break;
+ return ParsedAttr::AT_IntelOclBicc; // "clang::intel_ocl_bicc"
+ case 'o': // 2 strings to match.
+ if (memcmp(Name.data()+8, "bjc_", 4) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+13, "xception", 8) != 0)
+ break;
+ return ParsedAttr::AT_ObjCException; // "clang::objc_exception"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+13, "wnership", 8) != 0)
+ break;
+ return ParsedAttr::AT_ObjCOwnership; // "clang::objc_ownership"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "t_guarded_var", 13) != 0)
+ break;
+ return ParsedAttr::AT_PtGuardedVar; // "clang::pt_guarded_var"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "est_typestate", 13) != 0)
+ break;
+ return ParsedAttr::AT_TestTypestate; // "clang::test_typestate"
+ }
+ break;
+ case 22: // 11 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 10 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ if (memcmp(Name.data()+8, "mdgpu_num_", 10) != 0)
+ break;
+ switch (Name[18]) {
+ default: break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+19, "gpr", 3) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUNumSGPR; // "clang::amdgpu_num_sgpr"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+19, "gpr", 3) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUNumVGPR; // "clang::amdgpu_num_vgpr"
+ }
+ break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "ot_tail_called", 14) != 0)
+ break;
+ return ParsedAttr::AT_NotTailCalled; // "clang::not_tail_called"
+ case 'o': // 3 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_root_class", 13) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRootClass; // "clang::objc_root_class"
+ case 'w': // 2 strings to match.
+ if (memcmp(Name.data()+9, "nership_", 8) != 0)
+ break;
+ switch (Name[17]) {
+ default: break;
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+18, "olds", 4) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "clang::ownership_holds"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+18, "akes", 4) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "clang::ownership_takes"
+ }
+ break;
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "aram_typestate", 14) != 0)
+ break;
+ return ParsedAttr::AT_ParamTypestate; // "clang::param_typestate"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "coped_lockable", 14) != 0)
+ break;
+ return ParsedAttr::AT_ScopedLockable; // "clang::scoped_lockable"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "ype_visibility", 14) != 0)
+ break;
+ return ParsedAttr::AT_TypeVisibility; // "clang::type_visibility"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+8, "nlock_function", 14) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "clang::unlock_function"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "nu::transparent_union", 21) != 0)
+ break;
+ return ParsedAttr::AT_TransparentUnion; // "gnu::transparent_union"
+ }
+ break;
+ case 23: // 9 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 7 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "nternal_linkage", 15) != 0)
+ break;
+ return ParsedAttr::AT_InternalLinkage; // "clang::internal_linkage"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+8, "in_vector_width", 15) != 0)
+ break;
+ return ParsedAttr::AT_MinVectorWidth; // "clang::min_vector_width"
+ case 'n': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+9, "on_vector_type", 14) != 0)
+ break;
+ return ParsedAttr::AT_NeonVectorType; // "clang::neon_vector_type"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_consumes_self", 14) != 0)
+ break;
+ return ParsedAttr::AT_NSConsumesSelf; // "clang::ns_consumes_self"
+ }
+ break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "s_consumes_this", 15) != 0)
+ break;
+ return ParsedAttr::AT_OSConsumesThis; // "clang::os_consumes_this"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "ass_object_size", 15) != 0)
+ break;
+ return ParsedAttr::AT_PassObjectSize; // "clang::pass_object_size"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+8, "eturn_typestate", 15) != 0)
+ break;
+ return ParsedAttr::AT_ReturnTypestate; // "clang::return_typestate"
+ }
+ break;
+ case 'g': // 2 strings to match.
+ if (memcmp(Name.data()+1, "nu::", 4) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+6, "o_sanitize_thread", 17) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "gnu::no_sanitize_thread"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+6, "arn_unused_result", 17) != 0)
+ break;
+ return ParsedAttr::AT_WarnUnusedResult; // "gnu::warn_unused_result"
+ }
+ break;
+ }
+ break;
+ case 24: // 5 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 4 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "ssert_capability", 16) != 0)
+ break;
+ return ParsedAttr::AT_AssertCapability; // "clang::assert_capability"
+ case 'o': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_runtime_name", 15) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRuntimeName; // "clang::objc_runtime_name"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+9, "nership_returns", 15) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "clang::ownership_returns"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "hared_capability", 16) != 0)
+ break;
+ return ParsedAttr::AT_Capability; // "clang::shared_capability"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "nu::no_sanitize_address", 23) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "gnu::no_sanitize_address"
+ }
+ break;
+ case 25: // 12 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+9, "rch64_vector_pcs", 16) != 0)
+ break;
+ return ParsedAttr::AT_AArch64VectorPcs; // "clang::aarch64_vector_pcs"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+9, "quire_capability", 16) != 0)
+ break;
+ return ParsedAttr::AT_AcquireCapability; // "clang::acquire_capability"
+ }
+ break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+8, "isable_tail_calls", 17) != 0)
+ break;
+ return ParsedAttr::AT_DisableTailCalls; // "clang::disable_tail_calls"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+8, "num_extensibility", 17) != 0)
+ break;
+ return ParsedAttr::AT_EnumExtensibility; // "clang::enum_extensibility"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "boutletcollection", 17) != 0)
+ break;
+ return ParsedAttr::AT_IBOutletCollection; // "clang::iboutletcollection"
+ case 'n': // 2 strings to match.
+ if (memcmp(Name.data()+8, "o_s", 3) != 0)
+ break;
+ switch (Name[11]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+12, "nitize_memory", 13) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "clang::no_sanitize_memory"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+12, "ack_protector", 13) != 0)
+ break;
+ return ParsedAttr::AT_NoStackProtector; // "clang::no_stack_protector"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ if (memcmp(Name.data()+8, "bjc_", 4) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+13, "ethod_family", 12) != 0)
+ break;
+ return ParsedAttr::AT_ObjCMethodFamily; // "clang::objc_method_family"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+13, "onlazy_class", 12) != 0)
+ break;
+ return ParsedAttr::AT_ObjCNonLazyClass; // "clang::objc_nonlazy_class"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+8, "elease_capability", 17) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "clang::release_capability"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "wift_error_result", 17) != 0)
+ break;
+ return ParsedAttr::AT_SwiftErrorResult; // "clang::swift_error_result"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+8, "arn_unused_result", 17) != 0)
+ break;
+ return ParsedAttr::AT_WarnUnusedResult; // "clang::warn_unused_result"
+ }
+ break;
+ case 26: // 10 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "mdgpu_waves_per_eu", 18) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUWavesPerEU; // "clang::amdgpu_waves_per_eu"
+ case 'c': // 3 strings to match.
+ if (memcmp(Name.data()+8, "f_", 2) != 0)
+ break;
+ switch (Name[10]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+11, "udited_transfer", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFAuditedTransfer; // "clang::cf_audited_transfer"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+11, "eturns_retained", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFReturnsRetained; // "clang::cf_returns_retained"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+11, "nknown_transfer", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFUnknownTransfer; // "clang::cf_unknown_transfer"
+ }
+ break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "s_returns_retained", 18) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsRetained; // "clang::ns_returns_retained"
+ case 'o': // 4 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 3 strings to match.
+ if (memcmp(Name.data()+9, "jc_", 3) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'b': // 2 strings to match.
+ if (memcmp(Name.data()+13, "ridge_", 6) != 0)
+ break;
+ switch (Name[19]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+20, "utable", 6) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridgeMutable; // "clang::objc_bridge_mutable"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+20, "elated", 6) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridgeRelated; // "clang::objc_bridge_related"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+13, "equires_super", 13) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRequiresSuper; // "clang::objc_requires_super"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_returns_retained", 17) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetained; // "clang::os_returns_retained"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+8, "equires_capability", 18) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "clang::requires_capability"
+ }
+ break;
+ case 27: // 3 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 2 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "eon_polyvector_type", 19) != 0)
+ break;
+ return ParsedAttr::AT_NeonPolyVectorType; // "clang::neon_polyvector_type"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_runtime_visible", 19) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRuntimeVisible; // "clang::objc_runtime_visible"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "nu::no_instrument_function", 26) != 0)
+ break;
+ return ParsedAttr::AT_NoInstrumentFunction; // "gnu::no_instrument_function"
+ }
+ break;
+ case 28: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 7 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+8, "to_visibility_public", 20) != 0)
+ break;
+ return ParsedAttr::AT_LTOVisibilityPublic; // "clang::lto_visibility_public"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_precise_lifetime", 20) != 0)
+ break;
+ return ParsedAttr::AT_ObjCPreciseLifetime; // "clang::objc_precise_lifetime"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "ointer_with_type_tag", 20) != 0)
+ break;
+ return ParsedAttr::AT_ArgumentWithTypeTag; // "clang::pointer_with_type_tag"
+ case 's': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+9, "ared_locks_required", 19) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "clang::shared_locks_required"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+9, "ift_indirect_result", 19) != 0)
+ break;
+ return ParsedAttr::AT_SwiftIndirectResult; // "clang::swift_indirect_result"
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "ype_tag_for_datatype", 20) != 0)
+ break;
+ return ParsedAttr::AT_TypeTagForDatatype; // "clang::type_tag_for_datatype"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+8, "ray_never_instrument", 20) != 0)
+ break;
+ return ParsedAttr::AT_XRayInstrument; // "clang::xray_never_instrument"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "nu::force_align_arg_pointer", 27) != 0)
+ break;
+ return ParsedAttr::AT_X86ForceAlignArgPointer; // "gnu::force_align_arg_pointer"
+ }
+ break;
+ case 29: // 5 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "rgument_with_type_tag", 21) != 0)
+ break;
+ return ParsedAttr::AT_ArgumentWithTypeTag; // "clang::argument_with_type_tag"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+8, "xternal_source_symbol", 21) != 0)
+ break;
+ return ParsedAttr::AT_ExternalSourceSymbol; // "clang::external_source_symbol"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_independent_class", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCIndependentClass; // "clang::objc_independent_class"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "ry_acquire_capability", 21) != 0)
+ break;
+ return ParsedAttr::AT_TryAcquireCapability; // "clang::try_acquire_capability"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+8, "ray_always_instrument", 21) != 0)
+ break;
+ return ParsedAttr::AT_XRayInstrument; // "clang::xray_always_instrument"
+ }
+ break;
+ case 30: // 5 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 4 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "f_returns_not_retained", 22) != 0)
+ break;
+ return ParsedAttr::AT_CFReturnsNotRetained; // "clang::cf_returns_not_retained"
+ case 'n': // 2 strings to match.
+ if (memcmp(Name.data()+8, "s_returns_", 10) != 0)
+ break;
+ switch (Name[18]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+19, "utoreleased", 11) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsAutoreleased; // "clang::ns_returns_autoreleased"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+19, "ot_retained", 11) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsNotRetained; // "clang::ns_returns_not_retained"
+ }
+ break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "s_returns_not_retained", 22) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsNotRetained; // "clang::os_returns_not_retained"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "nu::no_caller_saved_registers", 29) != 0)
+ break;
+ return ParsedAttr::AT_AnyX86NoCallerSavedRegisters; // "gnu::no_caller_saved_registers"
+ }
+ break;
+ case 31: // 4 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case 'c': // 3 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "ssert_shared_capability", 23) != 0)
+ break;
+ return ParsedAttr::AT_AssertCapability; // "clang::assert_shared_capability"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+8, "xclusive_locks_required", 23) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "clang::exclusive_locks_required"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_externally_retained", 23) != 0)
+ break;
+ return ParsedAttr::AT_ObjCExternallyRetained; // "clang::objc_externally_retained"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "nu::no_address_safety_analysis", 30) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "gnu::no_address_safety_analysis"
+ }
+ break;
+ case 32: // 3 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "cquire_shared_capability", 24) != 0)
+ break;
+ return ParsedAttr::AT_AcquireCapability; // "clang::acquire_shared_capability"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "o_thread_safety_analysis", 24) != 0)
+ break;
+ return ParsedAttr::AT_NoThreadSafetyAnalysis; // "clang::no_thread_safety_analysis"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+8, "elease_shared_capability", 24) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "clang::release_shared_capability"
+ }
+ break;
+ case 33: // 5 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "onsumable_auto_cast_state", 25) != 0)
+ break;
+ return ParsedAttr::AT_ConsumableAutoCast; // "clang::consumable_auto_cast_state"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_returns_inner_pointer", 25) != 0)
+ break;
+ return ParsedAttr::AT_ObjCReturnsInnerPointer; // "clang::objc_returns_inner_pointer"
+ case 'r': // 2 strings to match.
+ if (Name[8] != 'e')
+ break;
+ switch (Name[9]) {
+ default: break;
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+10, "ease_generic_capability", 23) != 0)
+ break;
+ return ParsedAttr::AT_ReleaseCapability; // "clang::release_generic_capability"
+ case 'q': // 1 string to match.
+ if (memcmp(Name.data()+10, "uires_shared_capability", 23) != 0)
+ break;
+ return ParsedAttr::AT_RequiresCapability; // "clang::requires_shared_capability"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "peculative_load_hardening", 25) != 0)
+ break;
+ return ParsedAttr::AT_SpeculativeLoadHardening; // "clang::speculative_load_hardening"
+ }
+ break;
+ case 34: // 4 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "mdgpu_flat_work_group_size", 26) != 0)
+ break;
+ return ParsedAttr::AT_AMDGPUFlatWorkGroupSize; // "clang::amdgpu_flat_work_group_size"
+ case 'o': // 3 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 2 strings to match.
+ if (memcmp(Name.data()+9, "jc_", 3) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+13, "esignated_initializer", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCDesignatedInitializer; // "clang::objc_designated_initializer"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+13, "ubclassing_restricted", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCSubclassingRestricted; // "clang::objc_subclassing_restricted"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_returns_retained_on_zero", 25) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetainedOnZero; // "clang::os_returns_retained_on_zero"
+ }
+ break;
+ }
+ break;
+ case 35: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::consumable_set_state_on_read", 35) != 0)
+ break;
+ return ParsedAttr::AT_ConsumableSetOnRead; // "clang::consumable_set_state_on_read"
+ case 36: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "o_speculative_load_hardening", 28) != 0)
+ break;
+ return ParsedAttr::AT_NoSpeculativeLoadHardening; // "clang::no_speculative_load_hardening"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "ry_acquire_shared_capability", 28) != 0)
+ break;
+ return ParsedAttr::AT_TryAcquireCapability; // "clang::try_acquire_shared_capability"
+ }
+ break;
+ case 38: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "s_returns_retained_on_non_zero", 30) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetainedOnNonZero; // "clang::os_returns_retained_on_non_zero"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+8, "equire_constant_initialization", 30) != 0)
+ break;
+ return ParsedAttr::AT_RequireConstantInit; // "clang::require_constant_initialization"
+ }
+ break;
+ case 41: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::objc_requires_property_definitions", 41) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRequiresPropertyDefs; // "clang::objc_requires_property_definitions"
+ case 42: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+8, "xclude_from_explicit_instantiation", 34) != 0)
+ break;
+ return ParsedAttr::AT_ExcludeFromExplicitInstantiation; // "clang::exclude_from_explicit_instantiation"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_arc_weak_reference_unavailable", 34) != 0)
+ break;
+ return ParsedAttr::AT_ArcWeakrefUnavailable; // "clang::objc_arc_weak_reference_unavailable"
+ }
+ break;
+ case 53: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::objc_protocol_requires_explicit_implementation", 53) != 0)
+ break;
+ return ParsedAttr::AT_ObjCExplicitProtocolImpl; // "clang::objc_protocol_requires_explicit_implementation"
+ }
+ } else if (ParsedAttr::AS_C2x == Syntax) {
+ switch (Name.size()) {
+ default: break;
+ case 11: // 1 string to match.
+ if (memcmp(Name.data()+0, "::nodiscard", 11) != 0)
+ break;
+ return ParsedAttr::AT_WarnUnusedResult; // "::nodiscard"
+ case 12: // 1 string to match.
+ if (memcmp(Name.data()+0, "::deprecated", 12) != 0)
+ break;
+ return ParsedAttr::AT_Deprecated; // "::deprecated"
+ case 13: // 3 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":fallthrough", 12) != 0)
+ break;
+ return ParsedAttr::AT_FallThrough; // "::fallthrough"
+ case 'c': // 2 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+8, "locks", 5) != 0)
+ break;
+ return ParsedAttr::AT_Blocks; // "clang::blocks"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "ascal", 5) != 0)
+ break;
+ return ParsedAttr::AT_Pascal; // "clang::pascal"
+ }
+ break;
+ }
+ break;
+ case 14: // 5 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case ':': // 1 string to match.
+ if (memcmp(Name.data()+1, ":maybe_unused", 13) != 0)
+ break;
+ return ParsedAttr::AT_Unused; // "::maybe_unused"
+ case 'c': // 4 strings to match.
+ if (memcmp(Name.data()+1, "lang::", 6) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+8, "insize", 6) != 0)
+ break;
+ return ParsedAttr::AT_MinSize; // "clang::minsize"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "oderef", 6) != 0)
+ break;
+ return ParsedAttr::AT_NoDeref; // "clang::noderef"
+ case 'o': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_gc", 5) != 0)
+ break;
+ return ParsedAttr::AT_ObjCGC; // "clang::objc_gc"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+9, "tnone", 5) != 0)
+ break;
+ return ParsedAttr::AT_OptimizeNone; // "clang::optnone"
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case 15: // 6 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'N': // 1 string to match.
+ if (memcmp(Name.data()+8, "SObject", 7) != 0)
+ break;
+ return ParsedAttr::AT_ObjCNSObject; // "clang::NSObject"
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "nnotate", 7) != 0)
+ break;
+ return ParsedAttr::AT_Annotate; // "clang::annotate"
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "allback", 7) != 0)
+ break;
+ return ParsedAttr::AT_Callback; // "clang::callback"
+ case 'i': // 2 strings to match.
+ if (Name[8] != 'b')
+ break;
+ switch (Name[9]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+10, "ction", 5) != 0)
+ break;
+ return ParsedAttr::AT_IBAction; // "clang::ibaction"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+10, "utlet", 5) != 0)
+ break;
+ return ParsedAttr::AT_IBOutlet; // "clang::iboutlet"
+ }
+ break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "oescape", 7) != 0)
+ break;
+ return ParsedAttr::AT_NoEscape; // "clang::noescape"
+ }
+ break;
+ case 16: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+8, "lag_enum", 8) != 0)
+ break;
+ return ParsedAttr::AT_FlagEnum; // "clang::flag_enum"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "wiftcall", 8) != 0)
+ break;
+ return ParsedAttr::AT_SwiftCall; // "clang::swiftcall"
+ }
+ break;
+ case 17: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "onvergent", 9) != 0)
+ break;
+ return ParsedAttr::AT_Convergent; // "clang::convergent"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+8, "ectorcall", 9) != 0)
+ break;
+ return ParsedAttr::AT_VectorCall; // "clang::vectorcall"
+ }
+ break;
+ case 18: // 9 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "f_consumed", 10) != 0)
+ break;
+ return ParsedAttr::AT_CFConsumed; // "clang::cf_consumed"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "mport_name", 10) != 0)
+ break;
+ return ParsedAttr::AT_WebAssemblyImportName; // "clang::import_name"
+ case 'n': // 3 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'o': // 2 strings to match.
+ switch (Name[9]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+10, "sanitize", 8) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitize; // "clang::no_sanitize"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+10, "uplicate", 8) != 0)
+ break;
+ return ParsedAttr::AT_NoDuplicate; // "clang::noduplicate"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_consumed", 9) != 0)
+ break;
+ return ParsedAttr::AT_NSConsumed; // "clang::ns_consumed"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_bridge", 9) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridge; // "clang::objc_bridge"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_consumed", 9) != 0)
+ break;
+ return ParsedAttr::AT_OSConsumed; // "clang::os_consumed"
+ }
+ break;
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+8, "navailable", 10) != 0)
+ break;
+ return ParsedAttr::AT_Unavailable; // "clang::unavailable"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+8, "eak_import", 10) != 0)
+ break;
+ return ParsedAttr::AT_WeakImport; // "clang::weak_import"
+ }
+ break;
+ case 19: // 6 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "vailability", 11) != 0)
+ break;
+ return ParsedAttr::AT_Availability; // "clang::availability"
+ case 'c': // 2 strings to match.
+ if (memcmp(Name.data()+8, "pu_", 3) != 0)
+ break;
+ switch (Name[11]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+12, "ispatch", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUDispatch; // "clang::cpu_dispatch"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+12, "pecific", 7) != 0)
+ break;
+ return ParsedAttr::AT_CPUSpecific; // "clang::cpu_specific"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_boxable", 10) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBoxable; // "clang::objc_boxable"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+9, "erloadable", 10) != 0)
+ break;
+ return ParsedAttr::AT_Overloadable; // "clang::overloadable"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "reserve_all", 11) != 0)
+ break;
+ return ParsedAttr::AT_PreserveAll; // "clang::preserve_all"
+ }
+ break;
+ case 20: // 5 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "ddress_space", 12) != 0)
+ break;
+ return ParsedAttr::AT_AddressSpace; // "clang::address_space"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "mport_module", 12) != 0)
+ break;
+ return ParsedAttr::AT_WebAssemblyImportModule; // "clang::import_module"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "reserve_most", 12) != 0)
+ break;
+ return ParsedAttr::AT_PreserveMost; // "clang::preserve_most"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "wift_context", 12) != 0)
+ break;
+ return ParsedAttr::AT_SwiftContext; // "clang::swift_context"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+8, "ray_log_args", 12) != 0)
+ break;
+ return ParsedAttr::AT_XRayLogArgs; // "clang::xray_log_args"
+ }
+ break;
+ case 21: // 3 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+8, "ortify_stdlib", 13) != 0)
+ break;
+ return ParsedAttr::AT_FortifyStdLib; // "clang::fortify_stdlib"
+ case 'o': // 2 strings to match.
+ if (memcmp(Name.data()+8, "bjc_", 4) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+13, "xception", 8) != 0)
+ break;
+ return ParsedAttr::AT_ObjCException; // "clang::objc_exception"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+13, "wnership", 8) != 0)
+ break;
+ return ParsedAttr::AT_ObjCOwnership; // "clang::objc_ownership"
+ }
+ break;
+ }
+ break;
+ case 22: // 5 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "ot_tail_called", 14) != 0)
+ break;
+ return ParsedAttr::AT_NotTailCalled; // "clang::not_tail_called"
+ case 'o': // 3 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_root_class", 13) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRootClass; // "clang::objc_root_class"
+ case 'w': // 2 strings to match.
+ if (memcmp(Name.data()+9, "nership_", 8) != 0)
+ break;
+ switch (Name[17]) {
+ default: break;
+ case 'h': // 1 string to match.
+ if (memcmp(Name.data()+18, "olds", 4) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "clang::ownership_holds"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+18, "akes", 4) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "clang::ownership_takes"
+ }
+ break;
+ }
+ break;
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "ype_visibility", 14) != 0)
+ break;
+ return ParsedAttr::AT_TypeVisibility; // "clang::type_visibility"
+ }
+ break;
+ case 23: // 6 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "nternal_linkage", 15) != 0)
+ break;
+ return ParsedAttr::AT_InternalLinkage; // "clang::internal_linkage"
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+8, "in_vector_width", 15) != 0)
+ break;
+ return ParsedAttr::AT_MinVectorWidth; // "clang::min_vector_width"
+ case 'n': // 2 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+9, "on_vector_type", 14) != 0)
+ break;
+ return ParsedAttr::AT_NeonVectorType; // "clang::neon_vector_type"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_consumes_self", 14) != 0)
+ break;
+ return ParsedAttr::AT_NSConsumesSelf; // "clang::ns_consumes_self"
+ }
+ break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "s_consumes_this", 15) != 0)
+ break;
+ return ParsedAttr::AT_OSConsumesThis; // "clang::os_consumes_this"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "ass_object_size", 15) != 0)
+ break;
+ return ParsedAttr::AT_PassObjectSize; // "clang::pass_object_size"
+ }
+ break;
+ case 24: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::o", 8) != 0)
+ break;
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 1 string to match.
+ if (memcmp(Name.data()+9, "jc_runtime_name", 15) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRuntimeName; // "clang::objc_runtime_name"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+9, "nership_returns", 15) != 0)
+ break;
+ return ParsedAttr::AT_Ownership; // "clang::ownership_returns"
+ }
+ break;
+ case 25: // 9 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "arch64_vector_pcs", 17) != 0)
+ break;
+ return ParsedAttr::AT_AArch64VectorPcs; // "clang::aarch64_vector_pcs"
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+8, "isable_tail_calls", 17) != 0)
+ break;
+ return ParsedAttr::AT_DisableTailCalls; // "clang::disable_tail_calls"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+8, "num_extensibility", 17) != 0)
+ break;
+ return ParsedAttr::AT_EnumExtensibility; // "clang::enum_extensibility"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+8, "boutletcollection", 17) != 0)
+ break;
+ return ParsedAttr::AT_IBOutletCollection; // "clang::iboutletcollection"
+ case 'n': // 2 strings to match.
+ if (memcmp(Name.data()+8, "o_s", 3) != 0)
+ break;
+ switch (Name[11]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+12, "nitize_memory", 13) != 0)
+ break;
+ return ParsedAttr::AT_NoSanitizeSpecific; // "clang::no_sanitize_memory"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+12, "ack_protector", 13) != 0)
+ break;
+ return ParsedAttr::AT_NoStackProtector; // "clang::no_stack_protector"
+ }
+ break;
+ case 'o': // 2 strings to match.
+ if (memcmp(Name.data()+8, "bjc_", 4) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+13, "ethod_family", 12) != 0)
+ break;
+ return ParsedAttr::AT_ObjCMethodFamily; // "clang::objc_method_family"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+13, "onlazy_class", 12) != 0)
+ break;
+ return ParsedAttr::AT_ObjCNonLazyClass; // "clang::objc_nonlazy_class"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "wift_error_result", 17) != 0)
+ break;
+ return ParsedAttr::AT_SwiftErrorResult; // "clang::swift_error_result"
+ }
+ break;
+ case 26: // 8 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 3 strings to match.
+ if (memcmp(Name.data()+8, "f_", 2) != 0)
+ break;
+ switch (Name[10]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+11, "udited_transfer", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFAuditedTransfer; // "clang::cf_audited_transfer"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+11, "eturns_retained", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFReturnsRetained; // "clang::cf_returns_retained"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+11, "nknown_transfer", 15) != 0)
+ break;
+ return ParsedAttr::AT_CFUnknownTransfer; // "clang::cf_unknown_transfer"
+ }
+ break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "s_returns_retained", 18) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsRetained; // "clang::ns_returns_retained"
+ case 'o': // 4 strings to match.
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 3 strings to match.
+ if (memcmp(Name.data()+9, "jc_", 3) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'b': // 2 strings to match.
+ if (memcmp(Name.data()+13, "ridge_", 6) != 0)
+ break;
+ switch (Name[19]) {
+ default: break;
+ case 'm': // 1 string to match.
+ if (memcmp(Name.data()+20, "utable", 6) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridgeMutable; // "clang::objc_bridge_mutable"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+20, "elated", 6) != 0)
+ break;
+ return ParsedAttr::AT_ObjCBridgeRelated; // "clang::objc_bridge_related"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+13, "equires_super", 13) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRequiresSuper; // "clang::objc_requires_super"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_returns_retained", 17) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetained; // "clang::os_returns_retained"
+ }
+ break;
+ }
+ break;
+ case 27: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+8, "eon_polyvector_type", 19) != 0)
+ break;
+ return ParsedAttr::AT_NeonPolyVectorType; // "clang::neon_polyvector_type"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_runtime_visible", 19) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRuntimeVisible; // "clang::objc_runtime_visible"
+ }
+ break;
+ case 28: // 6 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+8, "to_visibility_public", 20) != 0)
+ break;
+ return ParsedAttr::AT_LTOVisibilityPublic; // "clang::lto_visibility_public"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_precise_lifetime", 20) != 0)
+ break;
+ return ParsedAttr::AT_ObjCPreciseLifetime; // "clang::objc_precise_lifetime"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+8, "ointer_with_type_tag", 20) != 0)
+ break;
+ return ParsedAttr::AT_ArgumentWithTypeTag; // "clang::pointer_with_type_tag"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "wift_indirect_result", 20) != 0)
+ break;
+ return ParsedAttr::AT_SwiftIndirectResult; // "clang::swift_indirect_result"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+8, "ype_tag_for_datatype", 20) != 0)
+ break;
+ return ParsedAttr::AT_TypeTagForDatatype; // "clang::type_tag_for_datatype"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+8, "ray_never_instrument", 20) != 0)
+ break;
+ return ParsedAttr::AT_XRayInstrument; // "clang::xray_never_instrument"
+ }
+ break;
+ case 29: // 4 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+8, "rgument_with_type_tag", 21) != 0)
+ break;
+ return ParsedAttr::AT_ArgumentWithTypeTag; // "clang::argument_with_type_tag"
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+8, "xternal_source_symbol", 21) != 0)
+ break;
+ return ParsedAttr::AT_ExternalSourceSymbol; // "clang::external_source_symbol"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_independent_class", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCIndependentClass; // "clang::objc_independent_class"
+ case 'x': // 1 string to match.
+ if (memcmp(Name.data()+8, "ray_always_instrument", 21) != 0)
+ break;
+ return ParsedAttr::AT_XRayInstrument; // "clang::xray_always_instrument"
+ }
+ break;
+ case 30: // 4 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+8, "f_returns_not_retained", 22) != 0)
+ break;
+ return ParsedAttr::AT_CFReturnsNotRetained; // "clang::cf_returns_not_retained"
+ case 'n': // 2 strings to match.
+ if (memcmp(Name.data()+8, "s_returns_", 10) != 0)
+ break;
+ switch (Name[18]) {
+ default: break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+19, "utoreleased", 11) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsAutoreleased; // "clang::ns_returns_autoreleased"
+ case 'n': // 1 string to match.
+ if (memcmp(Name.data()+19, "ot_retained", 11) != 0)
+ break;
+ return ParsedAttr::AT_NSReturnsNotRetained; // "clang::ns_returns_not_retained"
+ }
+ break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "s_returns_not_retained", 22) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsNotRetained; // "clang::os_returns_not_retained"
+ }
+ break;
+ case 31: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::objc_externally_retained", 31) != 0)
+ break;
+ return ParsedAttr::AT_ObjCExternallyRetained; // "clang::objc_externally_retained"
+ case 32: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::no_thread_safety_analysis", 32) != 0)
+ break;
+ return ParsedAttr::AT_NoThreadSafetyAnalysis; // "clang::no_thread_safety_analysis"
+ case 33: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_returns_inner_pointer", 25) != 0)
+ break;
+ return ParsedAttr::AT_ObjCReturnsInnerPointer; // "clang::objc_returns_inner_pointer"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+8, "peculative_load_hardening", 25) != 0)
+ break;
+ return ParsedAttr::AT_SpeculativeLoadHardening; // "clang::speculative_load_hardening"
+ }
+ break;
+ case 34: // 3 strings to match.
+ if (memcmp(Name.data()+0, "clang::o", 8) != 0)
+ break;
+ switch (Name[8]) {
+ default: break;
+ case 'b': // 2 strings to match.
+ if (memcmp(Name.data()+9, "jc_", 3) != 0)
+ break;
+ switch (Name[12]) {
+ default: break;
+ case 'd': // 1 string to match.
+ if (memcmp(Name.data()+13, "esignated_initializer", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCDesignatedInitializer; // "clang::objc_designated_initializer"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+13, "ubclassing_restricted", 21) != 0)
+ break;
+ return ParsedAttr::AT_ObjCSubclassingRestricted; // "clang::objc_subclassing_restricted"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+9, "_returns_retained_on_zero", 25) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetainedOnZero; // "clang::os_returns_retained_on_zero"
+ }
+ break;
+ case 36: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::no_speculative_load_hardening", 36) != 0)
+ break;
+ return ParsedAttr::AT_NoSpeculativeLoadHardening; // "clang::no_speculative_load_hardening"
+ case 38: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::os_returns_retained_on_non_zero", 38) != 0)
+ break;
+ return ParsedAttr::AT_OSReturnsRetainedOnNonZero; // "clang::os_returns_retained_on_non_zero"
+ case 41: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::objc_requires_property_definitions", 41) != 0)
+ break;
+ return ParsedAttr::AT_ObjCRequiresPropertyDefs; // "clang::objc_requires_property_definitions"
+ case 42: // 2 strings to match.
+ if (memcmp(Name.data()+0, "clang::", 7) != 0)
+ break;
+ switch (Name[7]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+8, "xclude_from_explicit_instantiation", 34) != 0)
+ break;
+ return ParsedAttr::AT_ExcludeFromExplicitInstantiation; // "clang::exclude_from_explicit_instantiation"
+ case 'o': // 1 string to match.
+ if (memcmp(Name.data()+8, "bjc_arc_weak_reference_unavailable", 34) != 0)
+ break;
+ return ParsedAttr::AT_ArcWeakrefUnavailable; // "clang::objc_arc_weak_reference_unavailable"
+ }
+ break;
+ case 53: // 1 string to match.
+ if (memcmp(Name.data()+0, "clang::objc_protocol_requires_explicit_implementation", 53) != 0)
+ break;
+ return ParsedAttr::AT_ObjCExplicitProtocolImpl; // "clang::objc_protocol_requires_explicit_implementation"
+ }
+ } else if (ParsedAttr::AS_Keyword == Syntax || ParsedAttr::AS_ContextSensitiveKeyword == Syntax) {
+ switch (Name.size()) {
+ default: break;
+ case 5: // 2 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+1, "_w64", 4) != 0)
+ break;
+ return ParsedAttr::IgnoredAttribute; // "__w64"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+1, "ocal", 4) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLLocalAddressSpace; // "local"
+ }
+ break;
+ case 6: // 5 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 3 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case '_': // 2 strings to match.
+ switch (Name[2]) {
+ default: break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+3, "ptr", 3) != 0)
+ break;
+ return ParsedAttr::AT_SPtr; // "__sptr"
+ case 'u': // 1 string to match.
+ if (memcmp(Name.data()+3, "ptr", 3) != 0)
+ break;
+ return ParsedAttr::AT_UPtr; // "__uptr"
+ }
+ break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+2, "decl", 4) != 0)
+ break;
+ return ParsedAttr::AT_CDecl; // "_cdecl"
+ }
+ break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "lobal", 5) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLGlobalAddressSpace; // "global"
+ case 'k': // 1 string to match.
+ if (memcmp(Name.data()+1, "ernel", 5) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLKernel; // "kernel"
+ }
+ break;
+ case 7: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 5 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case '_': // 4 strings to match.
+ switch (Name[2]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+3, "decl", 4) != 0)
+ break;
+ return ParsedAttr::AT_CDecl; // "__cdecl"
+ case 'l': // 1 string to match.
+ if (memcmp(Name.data()+3, "ocal", 4) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLLocalAddressSpace; // "__local"
+ case 'p': // 2 strings to match.
+ if (memcmp(Name.data()+3, "tr", 2) != 0)
+ break;
+ switch (Name[5]) {
+ default: break;
+ case '3': // 1 string to match.
+ if (Name[6] != '2')
+ break;
+ return ParsedAttr::AT_Ptr32; // "__ptr32"
+ case '6': // 1 string to match.
+ if (Name[6] != '4')
+ break;
+ return ParsedAttr::AT_Ptr64; // "__ptr64"
+ }
+ break;
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+2, "ascal", 5) != 0)
+ break;
+ return ParsedAttr::AT_Pascal; // "_pascal"
+ }
+ break;
+ case 'a': // 1 string to match.
+ if (memcmp(Name.data()+1, "lignas", 6) != 0)
+ break;
+ return ParsedAttr::AT_Aligned; // "alignas"
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+1, "eneric", 6) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLGenericAddressSpace; // "generic"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+1, "rivate", 6) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLPrivateAddressSpace; // "private"
+ }
+ break;
+ case 8: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 7 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'A': // 1 string to match.
+ if (memcmp(Name.data()+2, "lignas", 6) != 0)
+ break;
+ return ParsedAttr::AT_Aligned; // "_Alignas"
+ case 'N': // 1 string to match.
+ if (memcmp(Name.data()+2, "onnull", 6) != 0)
+ break;
+ return ParsedAttr::AT_TypeNonNull; // "_Nonnull"
+ case '_': // 4 strings to match.
+ switch (Name[2]) {
+ default: break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+3, "lobal", 5) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLGlobalAddressSpace; // "__global"
+ case 'k': // 2 strings to match.
+ switch (Name[3]) {
+ default: break;
+ case 'e': // 1 string to match.
+ if (memcmp(Name.data()+4, "rnel", 4) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLKernel; // "__kernel"
+ case 'i': // 1 string to match.
+ if (memcmp(Name.data()+4, "ndof", 4) != 0)
+ break;
+ return ParsedAttr::AT_ObjCKindOf; // "__kindof"
+ }
+ break;
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+3, "ascal", 5) != 0)
+ break;
+ return ParsedAttr::AT_Pascal; // "__pascal"
+ }
+ break;
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+2, "tdcall", 6) != 0)
+ break;
+ return ParsedAttr::AT_StdCall; // "_stdcall"
+ }
+ break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+1, "onstant", 7) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLConstantAddressSpace; // "constant"
+ }
+ break;
+ case 9: // 8 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 7 strings to match.
+ switch (Name[1]) {
+ default: break;
+ case 'N': // 1 string to match.
+ if (memcmp(Name.data()+2, "ullable", 7) != 0)
+ break;
+ return ParsedAttr::AT_TypeNullable; // "_Nullable"
+ case '_': // 4 strings to match.
+ switch (Name[2]) {
+ default: break;
+ case 'g': // 1 string to match.
+ if (memcmp(Name.data()+3, "eneric", 6) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLGenericAddressSpace; // "__generic"
+ case 'p': // 1 string to match.
+ if (memcmp(Name.data()+3, "rivate", 6) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLPrivateAddressSpace; // "__private"
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+3, "egcall", 6) != 0)
+ break;
+ return ParsedAttr::AT_RegCall; // "__regcall"
+ case 's': // 1 string to match.
+ if (memcmp(Name.data()+3, "tdcall", 6) != 0)
+ break;
+ return ParsedAttr::AT_StdCall; // "__stdcall"
+ }
+ break;
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+2, "astcall", 7) != 0)
+ break;
+ return ParsedAttr::AT_FastCall; // "_fastcall"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+2, "hiscall", 7) != 0)
+ break;
+ return ParsedAttr::AT_ThisCall; // "_thiscall"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "ead_only", 8) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLAccess; // "read_only"
+ }
+ break;
+ case 10: // 5 strings to match.
+ switch (Name[0]) {
+ default: break;
+ case '_': // 3 strings to match.
+ if (Name[1] != '_')
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'c': // 1 string to match.
+ if (memcmp(Name.data()+3, "onstant", 7) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLConstantAddressSpace; // "__constant"
+ case 'f': // 1 string to match.
+ if (memcmp(Name.data()+3, "astcall", 7) != 0)
+ break;
+ return ParsedAttr::AT_FastCall; // "__fastcall"
+ case 't': // 1 string to match.
+ if (memcmp(Name.data()+3, "hiscall", 7) != 0)
+ break;
+ return ParsedAttr::AT_ThisCall; // "__thiscall"
+ }
+ break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+1, "ead_write", 9) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLAccess; // "read_write"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+1, "rite_only", 9) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLAccess; // "write_only"
+ }
+ break;
+ case 11: // 2 strings to match.
+ if (Name[0] != '_')
+ break;
+ switch (Name[1]) {
+ default: break;
+ case '_': // 1 string to match.
+ if (memcmp(Name.data()+2, "read_only", 9) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLAccess; // "__read_only"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+2, "ectorcall", 9) != 0)
+ break;
+ return ParsedAttr::AT_VectorCall; // "_vectorcall"
+ }
+ break;
+ case 12: // 3 strings to match.
+ if (memcmp(Name.data()+0, "__", 2) != 0)
+ break;
+ switch (Name[2]) {
+ default: break;
+ case 'r': // 1 string to match.
+ if (memcmp(Name.data()+3, "ead_write", 9) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLAccess; // "__read_write"
+ case 'v': // 1 string to match.
+ if (memcmp(Name.data()+3, "ectorcall", 9) != 0)
+ break;
+ return ParsedAttr::AT_VectorCall; // "__vectorcall"
+ case 'w': // 1 string to match.
+ if (memcmp(Name.data()+3, "rite_only", 9) != 0)
+ break;
+ return ParsedAttr::AT_OpenCLAccess; // "__write_only"
+ }
+ break;
+ case 13: // 1 string to match.
+ if (memcmp(Name.data()+0, "__forceinline", 13) != 0)
+ break;
+ return ParsedAttr::AT_AlwaysInline; // "__forceinline"
+ case 17: // 1 string to match.
+ if (memcmp(Name.data()+0, "_Null_unspecified", 17) != 0)
+ break;
+ return ParsedAttr::AT_TypeNullUnspecified; // "_Null_unspecified"
+ case 19: // 1 string to match.
+ if (memcmp(Name.data()+0, "__unsafe_unretained", 19) != 0)
+ break;
+ return ParsedAttr::AT_ObjCInertUnsafeUnretained; // "__unsafe_unretained"
+ case 20: // 1 string to match.
+ if (memcmp(Name.data()+0, "__single_inheritance", 20) != 0)
+ break;
+ return ParsedAttr::AT_MSInheritance; // "__single_inheritance"
+ case 21: // 1 string to match.
+ if (memcmp(Name.data()+0, "__virtual_inheritance", 21) != 0)
+ break;
+ return ParsedAttr::AT_MSInheritance; // "__virtual_inheritance"
+ case 22: // 1 string to match.
+ if (memcmp(Name.data()+0, "__multiple_inheritance", 22) != 0)
+ break;
+ return ParsedAttr::AT_MSInheritance; // "__multiple_inheritance"
+ case 25: // 1 string to match.
+ if (memcmp(Name.data()+0, "__unspecified_inheritance", 25) != 0)
+ break;
+ return ParsedAttr::AT_MSInheritance; // "__unspecified_inheritance"
+ }
+ } else if (ParsedAttr::AS_Pragma == Syntax) {
+ switch (Name.size()) {
+ default: break;
+ case 4: // 1 string to match.
+ if (memcmp(Name.data()+0, "loop", 4) != 0)
+ break;
+ return ParsedAttr::AT_LoopHint; // "loop"
+ case 6: // 1 string to match.
+ if (memcmp(Name.data()+0, "unroll", 6) != 0)
+ break;
+ return ParsedAttr::AT_LoopHint; // "unroll"
+ case 8: // 1 string to match.
+ if (memcmp(Name.data()+0, "nounroll", 8) != 0)
+ break;
+ return ParsedAttr::AT_LoopHint; // "nounroll"
+ case 14: // 1 string to match.
+ if (memcmp(Name.data()+0, "unroll_and_jam", 14) != 0)
+ break;
+ return ParsedAttr::AT_LoopHint; // "unroll_and_jam"
+ case 16: // 1 string to match.
+ if (memcmp(Name.data()+0, "nounroll_and_jam", 16) != 0)
+ break;
+ return ParsedAttr::AT_LoopHint; // "nounroll_and_jam"
+ }
+ }
+ return ParsedAttr::UnknownAttribute;
+}
diff --git a/clang-r353983e/include/clang/Sema/AttrParsedAttrList.inc b/clang-r353983e/include/clang/Sema/AttrParsedAttrList.inc
new file mode 100644
index 00000000..d4f3fd2c
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/AttrParsedAttrList.inc
@@ -0,0 +1,276 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|* *|
+|* List of all attributes that Clang recognizes *|
+|* *|
+|* Automatically generated file, do not edit! *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef PARSED_ATTR
+#define PARSED_ATTR(NAME) NAME
+#endif
+
+PARSED_ATTR(AArch64VectorPcs)
+PARSED_ATTR(AMDGPUFlatWorkGroupSize)
+PARSED_ATTR(AMDGPUNumSGPR)
+PARSED_ATTR(AMDGPUNumVGPR)
+PARSED_ATTR(AMDGPUWavesPerEU)
+PARSED_ATTR(Interrupt)
+PARSED_ATTR(AVRSignal)
+PARSED_ATTR(AbiTag)
+PARSED_ATTR(AcquireCapability)
+PARSED_ATTR(AcquiredAfter)
+PARSED_ATTR(AcquiredBefore)
+PARSED_ATTR(AddressSpace)
+PARSED_ATTR(Alias)
+PARSED_ATTR(AlignValue)
+PARSED_ATTR(Aligned)
+PARSED_ATTR(AllocAlign)
+PARSED_ATTR(AllocSize)
+PARSED_ATTR(AlwaysDestroy)
+PARSED_ATTR(AlwaysInline)
+PARSED_ATTR(AnalyzerNoReturn)
+PARSED_ATTR(Annotate)
+PARSED_ATTR(AnyX86NoCallerSavedRegisters)
+PARSED_ATTR(AnyX86NoCfCheck)
+PARSED_ATTR(ArcWeakrefUnavailable)
+PARSED_ATTR(ArgumentWithTypeTag)
+PARSED_ATTR(Artificial)
+PARSED_ATTR(AssertCapability)
+PARSED_ATTR(AssertExclusiveLock)
+PARSED_ATTR(AssertSharedLock)
+PARSED_ATTR(AssumeAligned)
+PARSED_ATTR(Availability)
+PARSED_ATTR(Blocks)
+PARSED_ATTR(CDecl)
+PARSED_ATTR(CFAuditedTransfer)
+PARSED_ATTR(CFConsumed)
+PARSED_ATTR(CFReturnsNotRetained)
+PARSED_ATTR(CFReturnsRetained)
+PARSED_ATTR(CFUnknownTransfer)
+PARSED_ATTR(CPUDispatch)
+PARSED_ATTR(CPUSpecific)
+PARSED_ATTR(CUDAConstant)
+PARSED_ATTR(CUDADevice)
+PARSED_ATTR(CUDAGlobal)
+PARSED_ATTR(CUDAHost)
+PARSED_ATTR(CUDAInvalidTarget)
+PARSED_ATTR(CUDALaunchBounds)
+PARSED_ATTR(CUDAShared)
+PARSED_ATTR(CXX11NoReturn)
+PARSED_ATTR(CallableWhen)
+PARSED_ATTR(Callback)
+PARSED_ATTR(Capability)
+PARSED_ATTR(CarriesDependency)
+PARSED_ATTR(Cleanup)
+PARSED_ATTR(CodeSeg)
+PARSED_ATTR(Cold)
+PARSED_ATTR(Common)
+PARSED_ATTR(Const)
+PARSED_ATTR(Constructor)
+PARSED_ATTR(Consumable)
+PARSED_ATTR(ConsumableAutoCast)
+PARSED_ATTR(ConsumableSetOnRead)
+PARSED_ATTR(Convergent)
+PARSED_ATTR(DLLExport)
+PARSED_ATTR(DLLExportStaticLocal)
+PARSED_ATTR(DLLImport)
+PARSED_ATTR(DLLImportStaticLocal)
+PARSED_ATTR(Deprecated)
+PARSED_ATTR(Destructor)
+PARSED_ATTR(DiagnoseIf)
+PARSED_ATTR(DisableTailCalls)
+PARSED_ATTR(EmptyBases)
+PARSED_ATTR(EnableIf)
+PARSED_ATTR(EnumExtensibility)
+PARSED_ATTR(ExcludeFromExplicitInstantiation)
+PARSED_ATTR(ExclusiveTrylockFunction)
+PARSED_ATTR(ExtVectorType)
+PARSED_ATTR(ExternalSourceSymbol)
+PARSED_ATTR(FallThrough)
+PARSED_ATTR(FastCall)
+PARSED_ATTR(FlagEnum)
+PARSED_ATTR(Flatten)
+PARSED_ATTR(Format)
+PARSED_ATTR(FormatArg)
+PARSED_ATTR(FortifyStdLib)
+PARSED_ATTR(GNUInline)
+PARSED_ATTR(GuardedBy)
+PARSED_ATTR(GuardedVar)
+PARSED_ATTR(Hot)
+PARSED_ATTR(IBAction)
+PARSED_ATTR(IBOutlet)
+PARSED_ATTR(IBOutletCollection)
+PARSED_ATTR(IFunc)
+PARSED_ATTR(InitPriority)
+PARSED_ATTR(IntelOclBicc)
+PARSED_ATTR(InternalLinkage)
+PARSED_ATTR(LTOVisibilityPublic)
+PARSED_ATTR(LayoutVersion)
+PARSED_ATTR(LifetimeBound)
+PARSED_ATTR(LockReturned)
+PARSED_ATTR(Lockable)
+PARSED_ATTR(LocksExcluded)
+PARSED_ATTR(LoopHint)
+PARSED_ATTR(MSABI)
+PARSED_ATTR(MSInheritance)
+PARSED_ATTR(MSNoVTable)
+PARSED_ATTR(MSStruct)
+PARSED_ATTR(MayAlias)
+PARSED_ATTR(MicroMips)
+PARSED_ATTR(MinSize)
+PARSED_ATTR(MinVectorWidth)
+PARSED_ATTR(Mips16)
+PARSED_ATTR(MipsLongCall)
+PARSED_ATTR(MipsShortCall)
+PARSED_ATTR(Mode)
+PARSED_ATTR(NSConsumed)
+PARSED_ATTR(NSConsumesSelf)
+PARSED_ATTR(NSReturnsAutoreleased)
+PARSED_ATTR(NSReturnsNotRetained)
+PARSED_ATTR(NSReturnsRetained)
+PARSED_ATTR(Naked)
+PARSED_ATTR(NeonPolyVectorType)
+PARSED_ATTR(NeonVectorType)
+PARSED_ATTR(NoAlias)
+PARSED_ATTR(NoCommon)
+PARSED_ATTR(NoDebug)
+PARSED_ATTR(NoDeref)
+PARSED_ATTR(NoDestroy)
+PARSED_ATTR(NoDuplicate)
+PARSED_ATTR(NoEscape)
+PARSED_ATTR(NoInline)
+PARSED_ATTR(NoInstrumentFunction)
+PARSED_ATTR(NoMicroMips)
+PARSED_ATTR(NoMips16)
+PARSED_ATTR(NoReturn)
+PARSED_ATTR(NoSanitize)
+PARSED_ATTR(NoSanitizeSpecific)
+PARSED_ATTR(NoSpeculativeLoadHardening)
+PARSED_ATTR(NoSplitStack)
+PARSED_ATTR(NoStackProtector)
+PARSED_ATTR(NoThreadSafetyAnalysis)
+PARSED_ATTR(NoThrow)
+PARSED_ATTR(NonNull)
+PARSED_ATTR(NotTailCalled)
+PARSED_ATTR(OSConsumed)
+PARSED_ATTR(OSConsumesThis)
+PARSED_ATTR(OSReturnsNotRetained)
+PARSED_ATTR(OSReturnsRetained)
+PARSED_ATTR(OSReturnsRetainedOnNonZero)
+PARSED_ATTR(OSReturnsRetainedOnZero)
+PARSED_ATTR(ObjCBoxable)
+PARSED_ATTR(ObjCBridge)
+PARSED_ATTR(ObjCBridgeMutable)
+PARSED_ATTR(ObjCBridgeRelated)
+PARSED_ATTR(ObjCDesignatedInitializer)
+PARSED_ATTR(ObjCException)
+PARSED_ATTR(ObjCExplicitProtocolImpl)
+PARSED_ATTR(ObjCExternallyRetained)
+PARSED_ATTR(ObjCGC)
+PARSED_ATTR(ObjCIndependentClass)
+PARSED_ATTR(ObjCInertUnsafeUnretained)
+PARSED_ATTR(ObjCKindOf)
+PARSED_ATTR(ObjCMethodFamily)
+PARSED_ATTR(ObjCNSObject)
+PARSED_ATTR(ObjCNonLazyClass)
+PARSED_ATTR(ObjCOwnership)
+PARSED_ATTR(ObjCPreciseLifetime)
+PARSED_ATTR(ObjCRequiresPropertyDefs)
+PARSED_ATTR(ObjCRequiresSuper)
+PARSED_ATTR(ObjCReturnsInnerPointer)
+PARSED_ATTR(ObjCRootClass)
+PARSED_ATTR(ObjCRuntimeName)
+PARSED_ATTR(ObjCRuntimeVisible)
+PARSED_ATTR(ObjCSubclassingRestricted)
+PARSED_ATTR(OpenCLAccess)
+PARSED_ATTR(OpenCLConstantAddressSpace)
+PARSED_ATTR(OpenCLGenericAddressSpace)
+PARSED_ATTR(OpenCLGlobalAddressSpace)
+PARSED_ATTR(OpenCLIntelReqdSubGroupSize)
+PARSED_ATTR(OpenCLKernel)
+PARSED_ATTR(OpenCLLocalAddressSpace)
+PARSED_ATTR(OpenCLNoSVM)
+PARSED_ATTR(OpenCLPrivateAddressSpace)
+PARSED_ATTR(OpenCLUnrollHint)
+PARSED_ATTR(OptimizeNone)
+PARSED_ATTR(Overloadable)
+PARSED_ATTR(Ownership)
+PARSED_ATTR(Packed)
+PARSED_ATTR(ParamTypestate)
+PARSED_ATTR(Pascal)
+PARSED_ATTR(PassObjectSize)
+PARSED_ATTR(Pcs)
+PARSED_ATTR(PragmaClangBSSSection)
+PARSED_ATTR(PragmaClangDataSection)
+PARSED_ATTR(PragmaClangRodataSection)
+PARSED_ATTR(PragmaClangTextSection)
+PARSED_ATTR(PreserveAll)
+PARSED_ATTR(PreserveMost)
+PARSED_ATTR(PtGuardedBy)
+PARSED_ATTR(PtGuardedVar)
+PARSED_ATTR(Ptr32)
+PARSED_ATTR(Ptr64)
+PARSED_ATTR(Pure)
+PARSED_ATTR(RegCall)
+PARSED_ATTR(Regparm)
+PARSED_ATTR(Reinitializes)
+PARSED_ATTR(ReleaseCapability)
+PARSED_ATTR(RenderScriptKernel)
+PARSED_ATTR(ReqdWorkGroupSize)
+PARSED_ATTR(RequireConstantInit)
+PARSED_ATTR(RequiresCapability)
+PARSED_ATTR(Restrict)
+PARSED_ATTR(ReturnTypestate)
+PARSED_ATTR(ReturnsNonNull)
+PARSED_ATTR(ReturnsTwice)
+PARSED_ATTR(SPtr)
+PARSED_ATTR(ScopedLockable)
+PARSED_ATTR(Section)
+PARSED_ATTR(SelectAny)
+PARSED_ATTR(Sentinel)
+PARSED_ATTR(SetTypestate)
+PARSED_ATTR(SharedTrylockFunction)
+PARSED_ATTR(SpeculativeLoadHardening)
+PARSED_ATTR(StdCall)
+PARSED_ATTR(Suppress)
+PARSED_ATTR(SwiftCall)
+PARSED_ATTR(SwiftContext)
+PARSED_ATTR(SwiftErrorResult)
+PARSED_ATTR(SwiftIndirectResult)
+PARSED_ATTR(SysVABI)
+PARSED_ATTR(TLSModel)
+PARSED_ATTR(Target)
+PARSED_ATTR(TestTypestate)
+PARSED_ATTR(ThisCall)
+PARSED_ATTR(Thread)
+PARSED_ATTR(TransparentUnion)
+PARSED_ATTR(TrivialABI)
+PARSED_ATTR(TryAcquireCapability)
+PARSED_ATTR(TypeNonNull)
+PARSED_ATTR(TypeNullUnspecified)
+PARSED_ATTR(TypeNullable)
+PARSED_ATTR(TypeTagForDatatype)
+PARSED_ATTR(TypeVisibility)
+PARSED_ATTR(UPtr)
+PARSED_ATTR(Unavailable)
+PARSED_ATTR(Uninitialized)
+PARSED_ATTR(Unused)
+PARSED_ATTR(Used)
+PARSED_ATTR(Uuid)
+PARSED_ATTR(VecReturn)
+PARSED_ATTR(VecTypeHint)
+PARSED_ATTR(VectorCall)
+PARSED_ATTR(VectorSize)
+PARSED_ATTR(Visibility)
+PARSED_ATTR(WarnUnused)
+PARSED_ATTR(WarnUnusedResult)
+PARSED_ATTR(Weak)
+PARSED_ATTR(WeakImport)
+PARSED_ATTR(WeakRef)
+PARSED_ATTR(WebAssemblyImportModule)
+PARSED_ATTR(WebAssemblyImportName)
+PARSED_ATTR(WorkGroupSizeHint)
+PARSED_ATTR(X86ForceAlignArgPointer)
+PARSED_ATTR(XRayInstrument)
+PARSED_ATTR(XRayLogArgs)
diff --git a/clang-r353983e/include/clang/Sema/AttrSpellingListIndex.inc b/clang-r353983e/include/clang/Sema/AttrSpellingListIndex.inc
new file mode 100644
index 00000000..9056388c
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/AttrSpellingListIndex.inc
@@ -0,0 +1,2123 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|* *|
+|* Code to translate different attribute spellings into internal identifiers *|
+|* *|
+|* Automatically generated file, do not edit! *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+ switch (AttrKind) {
+ case AT_AArch64VectorPcs: {
+ if (Name == "aarch64_vector_pcs" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "aarch64_vector_pcs" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "aarch64_vector_pcs" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_AMDGPUFlatWorkGroupSize: {
+ if (Name == "amdgpu_flat_work_group_size" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "amdgpu_flat_work_group_size" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_AMDGPUNumSGPR: {
+ if (Name == "amdgpu_num_sgpr" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "amdgpu_num_sgpr" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_AMDGPUNumVGPR: {
+ if (Name == "amdgpu_num_vgpr" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "amdgpu_num_vgpr" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_AMDGPUWavesPerEU: {
+ if (Name == "amdgpu_waves_per_eu" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "amdgpu_waves_per_eu" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Interrupt: {
+ if (Name == "interrupt" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "interrupt" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AVRSignal: {
+ if (Name == "signal" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "signal" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AbiTag: {
+ if (Name == "abi_tag" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "abi_tag" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AcquireCapability: {
+ if (Name == "acquire_capability" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "acquire_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "acquire_shared_capability" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "acquire_shared_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 3;
+ if (Name == "exclusive_lock_function" && SyntaxUsed == 0 && Scope == "")
+ return 4;
+ if (Name == "shared_lock_function" && SyntaxUsed == 0 && Scope == "")
+ return 5;
+ break;
+ }
+ case AT_AcquiredAfter: {
+ if (Name == "acquired_after" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_AcquiredBefore: {
+ if (Name == "acquired_before" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_AddressSpace: {
+ if (Name == "address_space" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "address_space" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "address_space" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Alias: {
+ if (Name == "alias" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "alias" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AlignValue: {
+ if (Name == "align_value" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_Aligned: {
+ if (Name == "aligned" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "aligned" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "align" && SyntaxUsed == 3 && Scope == "")
+ return 2;
+ if (Name == "alignas" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ if (Name == "_Alignas" && SyntaxUsed == 5 && Scope == "")
+ return 4;
+ break;
+ }
+ case AT_AllocAlign: {
+ if (Name == "alloc_align" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "alloc_align" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AllocSize: {
+ if (Name == "alloc_size" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "alloc_size" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AlwaysDestroy: {
+ if (Name == "always_destroy" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "always_destroy" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_AlwaysInline: {
+ if (Name == "always_inline" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "always_inline" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "__forceinline" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ break;
+ }
+ case AT_AnalyzerNoReturn: {
+ if (Name == "analyzer_noreturn" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_Annotate: {
+ if (Name == "annotate" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "annotate" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "annotate" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_AnyX86NoCallerSavedRegisters: {
+ if (Name == "no_caller_saved_registers" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_caller_saved_registers" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AnyX86NoCfCheck: {
+ if (Name == "nocf_check" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "nocf_check" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_ArcWeakrefUnavailable: {
+ if (Name == "objc_arc_weak_reference_unavailable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_arc_weak_reference_unavailable" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_arc_weak_reference_unavailable" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ArgumentWithTypeTag: {
+ if (Name == "argument_with_type_tag" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "argument_with_type_tag" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "argument_with_type_tag" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ if (Name == "pointer_with_type_tag" && SyntaxUsed == 0 && Scope == "")
+ return 3;
+ if (Name == "pointer_with_type_tag" && SyntaxUsed == 1 && Scope == "clang")
+ return 4;
+ if (Name == "pointer_with_type_tag" && SyntaxUsed == 2 && Scope == "clang")
+ return 5;
+ break;
+ }
+ case AT_Artificial: {
+ if (Name == "artificial" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "artificial" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_AssertCapability: {
+ if (Name == "assert_capability" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "assert_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "assert_shared_capability" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "assert_shared_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 3;
+ break;
+ }
+ case AT_AssertExclusiveLock: {
+ if (Name == "assert_exclusive_lock" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_AssertSharedLock: {
+ if (Name == "assert_shared_lock" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_AssumeAligned: {
+ if (Name == "assume_aligned" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "assume_aligned" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Availability: {
+ if (Name == "availability" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "availability" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "availability" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Blocks: {
+ if (Name == "blocks" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "blocks" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "blocks" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_CDecl: {
+ if (Name == "cdecl" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cdecl" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "__cdecl" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ if (Name == "_cdecl" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_CFAuditedTransfer: {
+ if (Name == "cf_audited_transfer" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cf_audited_transfer" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "cf_audited_transfer" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_CFConsumed: {
+ if (Name == "cf_consumed" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cf_consumed" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "cf_consumed" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_CFReturnsNotRetained: {
+ if (Name == "cf_returns_not_retained" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cf_returns_not_retained" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "cf_returns_not_retained" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_CFReturnsRetained: {
+ if (Name == "cf_returns_retained" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cf_returns_retained" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "cf_returns_retained" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_CFUnknownTransfer: {
+ if (Name == "cf_unknown_transfer" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cf_unknown_transfer" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "cf_unknown_transfer" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_CPUDispatch: {
+ if (Name == "cpu_dispatch" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cpu_dispatch" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "cpu_dispatch" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ if (Name == "cpu_dispatch" && SyntaxUsed == 3 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_CPUSpecific: {
+ if (Name == "cpu_specific" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cpu_specific" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "cpu_specific" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ if (Name == "cpu_specific" && SyntaxUsed == 3 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_CUDAConstant: {
+ if (Name == "constant" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "__constant__" && SyntaxUsed == 3 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_CUDADevice: {
+ if (Name == "device" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "__device__" && SyntaxUsed == 3 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_CUDAGlobal: {
+ if (Name == "global" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "__global__" && SyntaxUsed == 3 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_CUDAHost: {
+ if (Name == "host" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "__host__" && SyntaxUsed == 3 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_CUDAInvalidTarget: {
+ break;
+ }
+ case AT_CUDALaunchBounds: {
+ if (Name == "launch_bounds" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "__launch_bounds__" && SyntaxUsed == 3 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_CUDAShared: {
+ if (Name == "shared" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "__shared__" && SyntaxUsed == 3 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_CXX11NoReturn: {
+ if (Name == "noreturn" && SyntaxUsed == 1 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_CallableWhen: {
+ if (Name == "callable_when" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "callable_when" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Callback: {
+ if (Name == "callback" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "callback" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "callback" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Capability: {
+ if (Name == "capability" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "shared_capability" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "shared_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 3;
+ break;
+ }
+ case AT_CarriesDependency: {
+ if (Name == "carries_dependency" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "carries_dependency" && SyntaxUsed == 1 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_Cleanup: {
+ if (Name == "cleanup" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cleanup" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_CodeSeg: {
+ if (Name == "code_seg" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_Cold: {
+ if (Name == "cold" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "cold" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Common: {
+ if (Name == "common" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "common" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Const: {
+ if (Name == "const" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "const" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "__const" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "__const" && SyntaxUsed == 1 && Scope == "gnu")
+ return 3;
+ break;
+ }
+ case AT_Constructor: {
+ if (Name == "constructor" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "constructor" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Consumable: {
+ if (Name == "consumable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "consumable" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_ConsumableAutoCast: {
+ if (Name == "consumable_auto_cast_state" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "consumable_auto_cast_state" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_ConsumableSetOnRead: {
+ if (Name == "consumable_set_state_on_read" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "consumable_set_state_on_read" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Convergent: {
+ if (Name == "convergent" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "convergent" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "convergent" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_DLLExport: {
+ if (Name == "dllexport" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ if (Name == "dllexport" && SyntaxUsed == 0 && Scope == "")
+ return 1;
+ if (Name == "dllexport" && SyntaxUsed == 1 && Scope == "gnu")
+ return 2;
+ break;
+ }
+ case AT_DLLExportStaticLocal: {
+ break;
+ }
+ case AT_DLLImport: {
+ if (Name == "dllimport" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ if (Name == "dllimport" && SyntaxUsed == 0 && Scope == "")
+ return 1;
+ if (Name == "dllimport" && SyntaxUsed == 1 && Scope == "gnu")
+ return 2;
+ break;
+ }
+ case AT_DLLImportStaticLocal: {
+ break;
+ }
+ case AT_Deprecated: {
+ if (Name == "deprecated" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "deprecated" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "deprecated" && SyntaxUsed == 3 && Scope == "")
+ return 2;
+ if (Name == "deprecated" && SyntaxUsed == 1 && Scope == "")
+ return 3;
+ if (Name == "deprecated" && SyntaxUsed == 2 && Scope == "")
+ return 4;
+ break;
+ }
+ case AT_Destructor: {
+ if (Name == "destructor" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "destructor" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_DiagnoseIf: {
+ if (Name == "diagnose_if" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_DisableTailCalls: {
+ if (Name == "disable_tail_calls" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "disable_tail_calls" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "disable_tail_calls" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_EmptyBases: {
+ if (Name == "empty_bases" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_EnableIf: {
+ if (Name == "enable_if" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_EnumExtensibility: {
+ if (Name == "enum_extensibility" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "enum_extensibility" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "enum_extensibility" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ExcludeFromExplicitInstantiation: {
+ if (Name == "exclude_from_explicit_instantiation" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "exclude_from_explicit_instantiation" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "exclude_from_explicit_instantiation" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ExclusiveTrylockFunction: {
+ if (Name == "exclusive_trylock_function" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_ExtVectorType: {
+ if (Name == "ext_vector_type" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_ExternalSourceSymbol: {
+ if (Name == "external_source_symbol" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "external_source_symbol" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "external_source_symbol" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_FallThrough: {
+ if (Name == "fallthrough" && SyntaxUsed == 1 && Scope == "")
+ return 0;
+ if (Name == "fallthrough" && SyntaxUsed == 2 && Scope == "")
+ return 1;
+ if (Name == "fallthrough" && SyntaxUsed == 1 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_FastCall: {
+ if (Name == "fastcall" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "fastcall" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "__fastcall" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ if (Name == "_fastcall" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_FlagEnum: {
+ if (Name == "flag_enum" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "flag_enum" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "flag_enum" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Flatten: {
+ if (Name == "flatten" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "flatten" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Format: {
+ if (Name == "format" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "format" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_FormatArg: {
+ if (Name == "format_arg" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "format_arg" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_FortifyStdLib: {
+ if (Name == "fortify_stdlib" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "fortify_stdlib" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "fortify_stdlib" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_GNUInline: {
+ if (Name == "gnu_inline" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "gnu_inline" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_GuardedBy: {
+ if (Name == "guarded_by" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_GuardedVar: {
+ if (Name == "guarded_var" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "guarded_var" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Hot: {
+ if (Name == "hot" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "hot" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_IBAction: {
+ if (Name == "ibaction" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ibaction" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "ibaction" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_IBOutlet: {
+ if (Name == "iboutlet" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "iboutlet" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "iboutlet" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_IBOutletCollection: {
+ if (Name == "iboutletcollection" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "iboutletcollection" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "iboutletcollection" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_IFunc: {
+ if (Name == "ifunc" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ifunc" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_InitPriority: {
+ if (Name == "init_priority" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "init_priority" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_IntelOclBicc: {
+ if (Name == "intel_ocl_bicc" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "intel_ocl_bicc" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_InternalLinkage: {
+ if (Name == "internal_linkage" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "internal_linkage" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "internal_linkage" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_LTOVisibilityPublic: {
+ if (Name == "lto_visibility_public" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "lto_visibility_public" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "lto_visibility_public" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_LayoutVersion: {
+ if (Name == "layout_version" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_LifetimeBound: {
+ if (Name == "lifetimebound" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "lifetimebound" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_LockReturned: {
+ if (Name == "lock_returned" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_Lockable: {
+ if (Name == "lockable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_LocksExcluded: {
+ if (Name == "locks_excluded" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_LoopHint: {
+ if (Name == "loop" && SyntaxUsed == 6 && Scope == "clang")
+ return 0;
+ if (Name == "unroll" && SyntaxUsed == 6 && Scope == "")
+ return 1;
+ if (Name == "nounroll" && SyntaxUsed == 6 && Scope == "")
+ return 2;
+ if (Name == "unroll_and_jam" && SyntaxUsed == 6 && Scope == "")
+ return 3;
+ if (Name == "nounroll_and_jam" && SyntaxUsed == 6 && Scope == "")
+ return 4;
+ break;
+ }
+ case AT_MSABI: {
+ if (Name == "ms_abi" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ms_abi" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_MSInheritance: {
+ if (Name == "__single_inheritance" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "__multiple_inheritance" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ if (Name == "__virtual_inheritance" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ if (Name == "__unspecified_inheritance" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_MSNoVTable: {
+ if (Name == "novtable" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_MSStruct: {
+ if (Name == "ms_struct" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ms_struct" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_MayAlias: {
+ if (Name == "may_alias" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "may_alias" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_MicroMips: {
+ if (Name == "micromips" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "micromips" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_MinSize: {
+ if (Name == "minsize" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "minsize" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "minsize" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_MinVectorWidth: {
+ if (Name == "min_vector_width" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "min_vector_width" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "min_vector_width" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Mips16: {
+ if (Name == "mips16" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "mips16" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_MipsLongCall: {
+ if (Name == "long_call" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "long_call" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "far" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "far" && SyntaxUsed == 1 && Scope == "gnu")
+ return 3;
+ break;
+ }
+ case AT_MipsShortCall: {
+ if (Name == "short_call" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "short_call" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "near" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "near" && SyntaxUsed == 1 && Scope == "gnu")
+ return 3;
+ break;
+ }
+ case AT_Mode: {
+ if (Name == "mode" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "mode" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NSConsumed: {
+ if (Name == "ns_consumed" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ns_consumed" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "ns_consumed" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NSConsumesSelf: {
+ if (Name == "ns_consumes_self" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ns_consumes_self" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "ns_consumes_self" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NSReturnsAutoreleased: {
+ if (Name == "ns_returns_autoreleased" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ns_returns_autoreleased" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "ns_returns_autoreleased" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NSReturnsNotRetained: {
+ if (Name == "ns_returns_not_retained" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ns_returns_not_retained" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "ns_returns_not_retained" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NSReturnsRetained: {
+ if (Name == "ns_returns_retained" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ns_returns_retained" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "ns_returns_retained" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Naked: {
+ if (Name == "naked" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "naked" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "naked" && SyntaxUsed == 3 && Scope == "")
+ return 2;
+ break;
+ }
+ case AT_NeonPolyVectorType: {
+ if (Name == "neon_polyvector_type" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "neon_polyvector_type" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "neon_polyvector_type" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NeonVectorType: {
+ if (Name == "neon_vector_type" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "neon_vector_type" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "neon_vector_type" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoAlias: {
+ if (Name == "noalias" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_NoCommon: {
+ if (Name == "nocommon" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "nocommon" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NoDebug: {
+ if (Name == "nodebug" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "nodebug" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NoDeref: {
+ if (Name == "noderef" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "noderef" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "noderef" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoDestroy: {
+ if (Name == "no_destroy" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_destroy" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_NoDuplicate: {
+ if (Name == "noduplicate" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "noduplicate" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "noduplicate" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoEscape: {
+ if (Name == "noescape" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "noescape" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "noescape" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoInline: {
+ if (Name == "noinline" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "noinline" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "noinline" && SyntaxUsed == 3 && Scope == "")
+ return 2;
+ break;
+ }
+ case AT_NoInstrumentFunction: {
+ if (Name == "no_instrument_function" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_instrument_function" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NoMicroMips: {
+ if (Name == "nomicromips" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "nomicromips" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NoMips16: {
+ if (Name == "nomips16" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "nomips16" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NoReturn: {
+ if (Name == "noreturn" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "noreturn" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "noreturn" && SyntaxUsed == 3 && Scope == "")
+ return 2;
+ break;
+ }
+ case AT_NoSanitize: {
+ if (Name == "no_sanitize" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_sanitize" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "no_sanitize" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoSanitizeSpecific: {
+ if (Name == "no_address_safety_analysis" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_address_safety_analysis" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "no_sanitize_address" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "no_sanitize_address" && SyntaxUsed == 1 && Scope == "gnu")
+ return 3;
+ if (Name == "no_sanitize_thread" && SyntaxUsed == 0 && Scope == "")
+ return 4;
+ if (Name == "no_sanitize_thread" && SyntaxUsed == 1 && Scope == "gnu")
+ return 5;
+ if (Name == "no_sanitize_memory" && SyntaxUsed == 0 && Scope == "")
+ return 6;
+ if (Name == "no_sanitize_memory" && SyntaxUsed == 1 && Scope == "clang")
+ return 7;
+ if (Name == "no_sanitize_memory" && SyntaxUsed == 2 && Scope == "clang")
+ return 8;
+ break;
+ }
+ case AT_NoSpeculativeLoadHardening: {
+ if (Name == "no_speculative_load_hardening" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_speculative_load_hardening" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "no_speculative_load_hardening" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoSplitStack: {
+ if (Name == "no_split_stack" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_split_stack" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NoStackProtector: {
+ if (Name == "no_stack_protector" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_stack_protector" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "no_stack_protector" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoThreadSafetyAnalysis: {
+ if (Name == "no_thread_safety_analysis" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "no_thread_safety_analysis" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "no_thread_safety_analysis" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_NoThrow: {
+ if (Name == "nothrow" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "nothrow" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "nothrow" && SyntaxUsed == 3 && Scope == "")
+ return 2;
+ break;
+ }
+ case AT_NonNull: {
+ if (Name == "nonnull" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "nonnull" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_NotTailCalled: {
+ if (Name == "not_tail_called" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "not_tail_called" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "not_tail_called" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_OSConsumed: {
+ if (Name == "os_consumed" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "os_consumed" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "os_consumed" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_OSConsumesThis: {
+ if (Name == "os_consumes_this" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "os_consumes_this" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "os_consumes_this" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_OSReturnsNotRetained: {
+ if (Name == "os_returns_not_retained" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "os_returns_not_retained" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "os_returns_not_retained" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_OSReturnsRetained: {
+ if (Name == "os_returns_retained" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "os_returns_retained" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "os_returns_retained" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_OSReturnsRetainedOnNonZero: {
+ if (Name == "os_returns_retained_on_non_zero" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "os_returns_retained_on_non_zero" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "os_returns_retained_on_non_zero" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_OSReturnsRetainedOnZero: {
+ if (Name == "os_returns_retained_on_zero" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "os_returns_retained_on_zero" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "os_returns_retained_on_zero" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCBoxable: {
+ if (Name == "objc_boxable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_boxable" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_boxable" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCBridge: {
+ if (Name == "objc_bridge" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_bridge" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_bridge" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCBridgeMutable: {
+ if (Name == "objc_bridge_mutable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_bridge_mutable" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_bridge_mutable" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCBridgeRelated: {
+ if (Name == "objc_bridge_related" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_bridge_related" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_bridge_related" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCDesignatedInitializer: {
+ if (Name == "objc_designated_initializer" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_designated_initializer" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_designated_initializer" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCException: {
+ if (Name == "objc_exception" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_exception" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_exception" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCExplicitProtocolImpl: {
+ if (Name == "objc_protocol_requires_explicit_implementation" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_protocol_requires_explicit_implementation" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_protocol_requires_explicit_implementation" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCExternallyRetained: {
+ if (Name == "objc_externally_retained" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_externally_retained" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_externally_retained" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCGC: {
+ if (Name == "objc_gc" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_gc" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_gc" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCIndependentClass: {
+ if (Name == "objc_independent_class" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_independent_class" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_independent_class" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCInertUnsafeUnretained: {
+ if (Name == "__unsafe_unretained" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_ObjCKindOf: {
+ if (Name == "__kindof" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_ObjCMethodFamily: {
+ if (Name == "objc_method_family" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_method_family" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_method_family" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCNSObject: {
+ if (Name == "NSObject" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "NSObject" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "NSObject" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCNonLazyClass: {
+ if (Name == "objc_nonlazy_class" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_nonlazy_class" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_nonlazy_class" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCOwnership: {
+ if (Name == "objc_ownership" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_ownership" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_ownership" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCPreciseLifetime: {
+ if (Name == "objc_precise_lifetime" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_precise_lifetime" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_precise_lifetime" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCRequiresPropertyDefs: {
+ if (Name == "objc_requires_property_definitions" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_requires_property_definitions" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_requires_property_definitions" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCRequiresSuper: {
+ if (Name == "objc_requires_super" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_requires_super" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_requires_super" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCReturnsInnerPointer: {
+ if (Name == "objc_returns_inner_pointer" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_returns_inner_pointer" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_returns_inner_pointer" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCRootClass: {
+ if (Name == "objc_root_class" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_root_class" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_root_class" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCRuntimeName: {
+ if (Name == "objc_runtime_name" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_runtime_name" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_runtime_name" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCRuntimeVisible: {
+ if (Name == "objc_runtime_visible" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_runtime_visible" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_runtime_visible" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_ObjCSubclassingRestricted: {
+ if (Name == "objc_subclassing_restricted" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "objc_subclassing_restricted" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "objc_subclassing_restricted" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_OpenCLAccess: {
+ if (Name == "__read_only" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "read_only" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ if (Name == "__write_only" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ if (Name == "write_only" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ if (Name == "__read_write" && SyntaxUsed == 5 && Scope == "")
+ return 4;
+ if (Name == "read_write" && SyntaxUsed == 5 && Scope == "")
+ return 5;
+ break;
+ }
+ case AT_OpenCLConstantAddressSpace: {
+ if (Name == "__constant" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "constant" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_OpenCLGenericAddressSpace: {
+ if (Name == "__generic" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "generic" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_OpenCLGlobalAddressSpace: {
+ if (Name == "__global" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "global" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_OpenCLIntelReqdSubGroupSize: {
+ if (Name == "intel_reqd_sub_group_size" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_OpenCLKernel: {
+ if (Name == "__kernel" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "kernel" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_OpenCLLocalAddressSpace: {
+ if (Name == "__local" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "local" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_OpenCLNoSVM: {
+ if (Name == "nosvm" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_OpenCLPrivateAddressSpace: {
+ if (Name == "__private" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ if (Name == "private" && SyntaxUsed == 5 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_OpenCLUnrollHint: {
+ if (Name == "opencl_unroll_hint" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_OptimizeNone: {
+ if (Name == "optnone" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "optnone" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "optnone" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Overloadable: {
+ if (Name == "overloadable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "overloadable" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "overloadable" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Ownership: {
+ if (Name == "ownership_holds" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "ownership_holds" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "ownership_holds" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ if (Name == "ownership_returns" && SyntaxUsed == 0 && Scope == "")
+ return 3;
+ if (Name == "ownership_returns" && SyntaxUsed == 1 && Scope == "clang")
+ return 4;
+ if (Name == "ownership_returns" && SyntaxUsed == 2 && Scope == "clang")
+ return 5;
+ if (Name == "ownership_takes" && SyntaxUsed == 0 && Scope == "")
+ return 6;
+ if (Name == "ownership_takes" && SyntaxUsed == 1 && Scope == "clang")
+ return 7;
+ if (Name == "ownership_takes" && SyntaxUsed == 2 && Scope == "clang")
+ return 8;
+ break;
+ }
+ case AT_Packed: {
+ if (Name == "packed" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "packed" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_ParamTypestate: {
+ if (Name == "param_typestate" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "param_typestate" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Pascal: {
+ if (Name == "pascal" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "pascal" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "pascal" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ if (Name == "__pascal" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ if (Name == "_pascal" && SyntaxUsed == 5 && Scope == "")
+ return 4;
+ break;
+ }
+ case AT_PassObjectSize: {
+ if (Name == "pass_object_size" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "pass_object_size" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "pass_object_size" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Pcs: {
+ if (Name == "pcs" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "pcs" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_PragmaClangBSSSection: {
+ break;
+ }
+ case AT_PragmaClangDataSection: {
+ break;
+ }
+ case AT_PragmaClangRodataSection: {
+ break;
+ }
+ case AT_PragmaClangTextSection: {
+ break;
+ }
+ case AT_PreserveAll: {
+ if (Name == "preserve_all" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "preserve_all" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "preserve_all" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_PreserveMost: {
+ if (Name == "preserve_most" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "preserve_most" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "preserve_most" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_PtGuardedBy: {
+ if (Name == "pt_guarded_by" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_PtGuardedVar: {
+ if (Name == "pt_guarded_var" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "pt_guarded_var" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Ptr32: {
+ if (Name == "__ptr32" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_Ptr64: {
+ if (Name == "__ptr64" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_Pure: {
+ if (Name == "pure" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "pure" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_RegCall: {
+ if (Name == "regcall" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "regcall" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "__regcall" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ break;
+ }
+ case AT_Regparm: {
+ if (Name == "regparm" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "regparm" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Reinitializes: {
+ if (Name == "reinitializes" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "reinitializes" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_ReleaseCapability: {
+ if (Name == "release_capability" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "release_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "release_shared_capability" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "release_shared_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 3;
+ if (Name == "release_generic_capability" && SyntaxUsed == 0 && Scope == "")
+ return 4;
+ if (Name == "release_generic_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 5;
+ if (Name == "unlock_function" && SyntaxUsed == 0 && Scope == "")
+ return 6;
+ if (Name == "unlock_function" && SyntaxUsed == 1 && Scope == "clang")
+ return 7;
+ break;
+ }
+ case AT_RenderScriptKernel: {
+ if (Name == "kernel" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_ReqdWorkGroupSize: {
+ if (Name == "reqd_work_group_size" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_RequireConstantInit: {
+ if (Name == "require_constant_initialization" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "require_constant_initialization" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_RequiresCapability: {
+ if (Name == "requires_capability" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "requires_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "exclusive_locks_required" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "exclusive_locks_required" && SyntaxUsed == 1 && Scope == "clang")
+ return 3;
+ if (Name == "requires_shared_capability" && SyntaxUsed == 0 && Scope == "")
+ return 4;
+ if (Name == "requires_shared_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 5;
+ if (Name == "shared_locks_required" && SyntaxUsed == 0 && Scope == "")
+ return 6;
+ if (Name == "shared_locks_required" && SyntaxUsed == 1 && Scope == "clang")
+ return 7;
+ break;
+ }
+ case AT_Restrict: {
+ if (Name == "restrict" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ if (Name == "malloc" && SyntaxUsed == 0 && Scope == "")
+ return 1;
+ if (Name == "malloc" && SyntaxUsed == 1 && Scope == "gnu")
+ return 2;
+ break;
+ }
+ case AT_ReturnTypestate: {
+ if (Name == "return_typestate" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "return_typestate" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_ReturnsNonNull: {
+ if (Name == "returns_nonnull" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "returns_nonnull" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_ReturnsTwice: {
+ if (Name == "returns_twice" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "returns_twice" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_SPtr: {
+ if (Name == "__sptr" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_ScopedLockable: {
+ if (Name == "scoped_lockable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "scoped_lockable" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Section: {
+ if (Name == "section" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "section" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "allocate" && SyntaxUsed == 3 && Scope == "")
+ return 2;
+ break;
+ }
+ case AT_SelectAny: {
+ if (Name == "selectany" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ if (Name == "selectany" && SyntaxUsed == 0 && Scope == "")
+ return 1;
+ if (Name == "selectany" && SyntaxUsed == 1 && Scope == "gnu")
+ return 2;
+ break;
+ }
+ case AT_Sentinel: {
+ if (Name == "sentinel" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "sentinel" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_SetTypestate: {
+ if (Name == "set_typestate" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "set_typestate" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_SharedTrylockFunction: {
+ if (Name == "shared_trylock_function" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_SpeculativeLoadHardening: {
+ if (Name == "speculative_load_hardening" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "speculative_load_hardening" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "speculative_load_hardening" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_StdCall: {
+ if (Name == "stdcall" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "stdcall" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "__stdcall" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ if (Name == "_stdcall" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_Suppress: {
+ if (Name == "suppress" && SyntaxUsed == 1 && Scope == "gsl")
+ return 0;
+ break;
+ }
+ case AT_SwiftCall: {
+ if (Name == "swiftcall" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "swiftcall" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "swiftcall" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_SwiftContext: {
+ if (Name == "swift_context" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "swift_context" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "swift_context" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_SwiftErrorResult: {
+ if (Name == "swift_error_result" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "swift_error_result" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "swift_error_result" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_SwiftIndirectResult: {
+ if (Name == "swift_indirect_result" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "swift_indirect_result" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "swift_indirect_result" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_SysVABI: {
+ if (Name == "sysv_abi" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "sysv_abi" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_TLSModel: {
+ if (Name == "tls_model" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "tls_model" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Target: {
+ if (Name == "target" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "target" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_TestTypestate: {
+ if (Name == "test_typestate" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "test_typestate" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_ThisCall: {
+ if (Name == "thiscall" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "thiscall" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ if (Name == "__thiscall" && SyntaxUsed == 5 && Scope == "")
+ return 2;
+ if (Name == "_thiscall" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_Thread: {
+ if (Name == "thread" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_TransparentUnion: {
+ if (Name == "transparent_union" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "transparent_union" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_TrivialABI: {
+ if (Name == "trivial_abi" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "trivial_abi" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_TryAcquireCapability: {
+ if (Name == "try_acquire_capability" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "try_acquire_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "try_acquire_shared_capability" && SyntaxUsed == 0 && Scope == "")
+ return 2;
+ if (Name == "try_acquire_shared_capability" && SyntaxUsed == 1 && Scope == "clang")
+ return 3;
+ break;
+ }
+ case AT_TypeNonNull: {
+ if (Name == "_Nonnull" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_TypeNullUnspecified: {
+ if (Name == "_Null_unspecified" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_TypeNullable: {
+ if (Name == "_Nullable" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_TypeTagForDatatype: {
+ if (Name == "type_tag_for_datatype" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "type_tag_for_datatype" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "type_tag_for_datatype" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_TypeVisibility: {
+ if (Name == "type_visibility" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "type_visibility" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "type_visibility" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_UPtr: {
+ if (Name == "__uptr" && SyntaxUsed == 5 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_Unavailable: {
+ if (Name == "unavailable" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "unavailable" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "unavailable" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_Uninitialized: {
+ if (Name == "uninitialized" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "uninitialized" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_Unused: {
+ if (Name == "maybe_unused" && SyntaxUsed == 1 && Scope == "")
+ return 0;
+ if (Name == "unused" && SyntaxUsed == 0 && Scope == "")
+ return 1;
+ if (Name == "unused" && SyntaxUsed == 1 && Scope == "gnu")
+ return 2;
+ if (Name == "maybe_unused" && SyntaxUsed == 2 && Scope == "")
+ return 3;
+ break;
+ }
+ case AT_Used: {
+ if (Name == "used" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "used" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Uuid: {
+ if (Name == "uuid" && SyntaxUsed == 3 && Scope == "")
+ return 0;
+ if (Name == "uuid" && SyntaxUsed == 4 && Scope == "")
+ return 1;
+ break;
+ }
+ case AT_VecReturn: {
+ if (Name == "vecreturn" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "vecreturn" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ break;
+ }
+ case AT_VecTypeHint: {
+ if (Name == "vec_type_hint" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_VectorCall: {
+ if (Name == "vectorcall" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "vectorcall" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "vectorcall" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ if (Name == "__vectorcall" && SyntaxUsed == 5 && Scope == "")
+ return 3;
+ if (Name == "_vectorcall" && SyntaxUsed == 5 && Scope == "")
+ return 4;
+ break;
+ }
+ case AT_VectorSize: {
+ if (Name == "vector_size" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "vector_size" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_Visibility: {
+ if (Name == "visibility" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "visibility" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_WarnUnused: {
+ if (Name == "warn_unused" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "warn_unused" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_WarnUnusedResult: {
+ if (Name == "nodiscard" && SyntaxUsed == 1 && Scope == "")
+ return 0;
+ if (Name == "nodiscard" && SyntaxUsed == 2 && Scope == "")
+ return 1;
+ if (Name == "warn_unused_result" && SyntaxUsed == 1 && Scope == "clang")
+ return 2;
+ if (Name == "warn_unused_result" && SyntaxUsed == 0 && Scope == "")
+ return 3;
+ if (Name == "warn_unused_result" && SyntaxUsed == 1 && Scope == "gnu")
+ return 4;
+ break;
+ }
+ case AT_Weak: {
+ if (Name == "weak" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "weak" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_WeakImport: {
+ if (Name == "weak_import" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "weak_import" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "weak_import" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_WeakRef: {
+ if (Name == "weakref" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "weakref" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_WebAssemblyImportModule: {
+ if (Name == "import_module" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "import_module" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "import_module" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_WebAssemblyImportName: {
+ if (Name == "import_name" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "import_name" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "import_name" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ case AT_WorkGroupSizeHint: {
+ if (Name == "work_group_size_hint" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ break;
+ }
+ case AT_X86ForceAlignArgPointer: {
+ if (Name == "force_align_arg_pointer" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "force_align_arg_pointer" && SyntaxUsed == 1 && Scope == "gnu")
+ return 1;
+ break;
+ }
+ case AT_XRayInstrument: {
+ if (Name == "xray_always_instrument" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "xray_always_instrument" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "xray_always_instrument" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ if (Name == "xray_never_instrument" && SyntaxUsed == 0 && Scope == "")
+ return 3;
+ if (Name == "xray_never_instrument" && SyntaxUsed == 1 && Scope == "clang")
+ return 4;
+ if (Name == "xray_never_instrument" && SyntaxUsed == 2 && Scope == "clang")
+ return 5;
+ break;
+ }
+ case AT_XRayLogArgs: {
+ if (Name == "xray_log_args" && SyntaxUsed == 0 && Scope == "")
+ return 0;
+ if (Name == "xray_log_args" && SyntaxUsed == 1 && Scope == "clang")
+ return 1;
+ if (Name == "xray_log_args" && SyntaxUsed == 2 && Scope == "clang")
+ return 2;
+ break;
+ }
+ }
+ return 0;
diff --git a/clang-r353983e/include/clang/Sema/AttrTemplateInstantiate.inc b/clang-r353983e/include/clang/Sema/AttrTemplateInstantiate.inc
new file mode 100644
index 00000000..860b9c4f
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/AttrTemplateInstantiate.inc
@@ -0,0 +1,2143 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|* *|
+|* Template instantiation code for attributes *|
+|* *|
+|* Automatically generated file, do not edit! *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+namespace clang {
+namespace sema {
+
+Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ switch (At->getKind()) {
+ case attr::AArch64VectorPcs: {
+ const auto *A = cast<AArch64VectorPcsAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AMDGPUFlatWorkGroupSize: {
+ const auto *A = cast<AMDGPUFlatWorkGroupSizeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AMDGPUNumSGPR: {
+ const auto *A = cast<AMDGPUNumSGPRAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AMDGPUNumVGPR: {
+ const auto *A = cast<AMDGPUNumVGPRAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AMDGPUWavesPerEU: {
+ const auto *A = cast<AMDGPUWavesPerEUAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ARMInterrupt: {
+ const auto *A = cast<ARMInterruptAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AVRInterrupt: {
+ const auto *A = cast<AVRInterruptAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AVRSignal: {
+ const auto *A = cast<AVRSignalAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AbiTag: {
+ const auto *A = cast<AbiTagAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AcquireCapability: {
+ const auto *A = cast<AcquireCapabilityAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) AcquireCapabilityAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::AcquiredAfter: {
+ const auto *A = cast<AcquiredAfterAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) AcquiredAfterAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::AcquiredBefore: {
+ const auto *A = cast<AcquiredBeforeAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) AcquiredBeforeAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::AddressSpace: {
+ const auto *A = cast<AddressSpaceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Alias: {
+ const auto *A = cast<AliasAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AlignMac68k: {
+ const auto *A = cast<AlignMac68kAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AlignValue: {
+ const auto *A = cast<AlignValueAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Aligned: {
+ const auto *A = cast<AlignedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AllocAlign: {
+ const auto *A = cast<AllocAlignAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AllocSize: {
+ const auto *A = cast<AllocSizeAttr>(At);
+ return new (C) AllocSizeAttr(A->getLocation(), C, A->getElemSizeParam(), A->getNumElemsParam(), A->getSpellingListIndex());
+ }
+ case attr::AlwaysDestroy: {
+ const auto *A = cast<AlwaysDestroyAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AlwaysInline: {
+ const auto *A = cast<AlwaysInlineAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AnalyzerNoReturn: {
+ const auto *A = cast<AnalyzerNoReturnAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Annotate: {
+ const auto *A = cast<AnnotateAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AnyX86Interrupt: {
+ const auto *A = cast<AnyX86InterruptAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AnyX86NoCallerSavedRegisters: {
+ const auto *A = cast<AnyX86NoCallerSavedRegistersAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AnyX86NoCfCheck: {
+ const auto *A = cast<AnyX86NoCfCheckAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ArcWeakrefUnavailable: {
+ const auto *A = cast<ArcWeakrefUnavailableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ArgumentWithTypeTag: {
+ const auto *A = cast<ArgumentWithTypeTagAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Artificial: {
+ const auto *A = cast<ArtificialAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AsmLabel: {
+ const auto *A = cast<AsmLabelAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AssertCapability: {
+ const auto *A = cast<AssertCapabilityAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) AssertCapabilityAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::AssertExclusiveLock: {
+ const auto *A = cast<AssertExclusiveLockAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) AssertExclusiveLockAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::AssertSharedLock: {
+ const auto *A = cast<AssertSharedLockAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) AssertSharedLockAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::AssumeAligned: {
+ const auto *A = cast<AssumeAlignedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Availability: {
+ const auto *A = cast<AvailabilityAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Blocks: {
+ const auto *A = cast<BlocksAttr>(At);
+ return A->clone(C);
+ }
+ case attr::C11NoReturn: {
+ const auto *A = cast<C11NoReturnAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CDecl: {
+ const auto *A = cast<CDeclAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CFAuditedTransfer: {
+ const auto *A = cast<CFAuditedTransferAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CFConsumed: {
+ const auto *A = cast<CFConsumedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CFReturnsNotRetained: {
+ const auto *A = cast<CFReturnsNotRetainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CFReturnsRetained: {
+ const auto *A = cast<CFReturnsRetainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CFUnknownTransfer: {
+ const auto *A = cast<CFUnknownTransferAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CPUDispatch: {
+ const auto *A = cast<CPUDispatchAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CPUSpecific: {
+ const auto *A = cast<CPUSpecificAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CUDAConstant: {
+ const auto *A = cast<CUDAConstantAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CUDADevice: {
+ const auto *A = cast<CUDADeviceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CUDAGlobal: {
+ const auto *A = cast<CUDAGlobalAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CUDAHost: {
+ const auto *A = cast<CUDAHostAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CUDAInvalidTarget: {
+ const auto *A = cast<CUDAInvalidTargetAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CUDALaunchBounds: {
+ const auto *A = cast<CUDALaunchBoundsAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CUDAShared: {
+ const auto *A = cast<CUDASharedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CXX11NoReturn: {
+ const auto *A = cast<CXX11NoReturnAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CallableWhen: {
+ const auto *A = cast<CallableWhenAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Callback: {
+ const auto *A = cast<CallbackAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Capability: {
+ const auto *A = cast<CapabilityAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CapturedRecord: {
+ const auto *A = cast<CapturedRecordAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CarriesDependency: {
+ const auto *A = cast<CarriesDependencyAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Cleanup: {
+ const auto *A = cast<CleanupAttr>(At);
+ return A->clone(C);
+ }
+ case attr::CodeSeg: {
+ const auto *A = cast<CodeSegAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Cold: {
+ const auto *A = cast<ColdAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Common: {
+ const auto *A = cast<CommonAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Const: {
+ const auto *A = cast<ConstAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Constructor: {
+ const auto *A = cast<ConstructorAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Consumable: {
+ const auto *A = cast<ConsumableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ConsumableAutoCast: {
+ const auto *A = cast<ConsumableAutoCastAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ConsumableSetOnRead: {
+ const auto *A = cast<ConsumableSetOnReadAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Convergent: {
+ const auto *A = cast<ConvergentAttr>(At);
+ return A->clone(C);
+ }
+ case attr::DLLExport: {
+ const auto *A = cast<DLLExportAttr>(At);
+ return A->clone(C);
+ }
+ case attr::DLLExportStaticLocal: {
+ const auto *A = cast<DLLExportStaticLocalAttr>(At);
+ return A->clone(C);
+ }
+ case attr::DLLImport: {
+ const auto *A = cast<DLLImportAttr>(At);
+ return A->clone(C);
+ }
+ case attr::DLLImportStaticLocal: {
+ const auto *A = cast<DLLImportStaticLocalAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Deprecated: {
+ const auto *A = cast<DeprecatedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Destructor: {
+ const auto *A = cast<DestructorAttr>(At);
+ return A->clone(C);
+ }
+ case attr::DiagnoseIf: {
+ const auto *A = cast<DiagnoseIfAttr>(At);
+ Expr * tempInstCond;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getCond(), TemplateArgs);
+ tempInstCond = Result.getAs<Expr>();
+ }
+ return new (C) DiagnoseIfAttr(A->getLocation(), C, tempInstCond, A->getMessage(), A->getDiagnosticType(), A->getArgDependent(), A->getParent(), A->getSpellingListIndex());
+ }
+ case attr::DisableTailCalls: {
+ const auto *A = cast<DisableTailCallsAttr>(At);
+ return A->clone(C);
+ }
+ case attr::EmptyBases: {
+ const auto *A = cast<EmptyBasesAttr>(At);
+ return A->clone(C);
+ }
+ case attr::EnableIf: {
+ const auto *A = cast<EnableIfAttr>(At);
+ Expr * tempInstCond;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getCond(), TemplateArgs);
+ tempInstCond = Result.getAs<Expr>();
+ }
+ return new (C) EnableIfAttr(A->getLocation(), C, tempInstCond, A->getMessage(), A->getSpellingListIndex());
+ }
+ case attr::EnumExtensibility: {
+ const auto *A = cast<EnumExtensibilityAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ExcludeFromExplicitInstantiation: {
+ const auto *A = cast<ExcludeFromExplicitInstantiationAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ExclusiveTrylockFunction: {
+ const auto *A = cast<ExclusiveTrylockFunctionAttr>(At);
+ Expr * tempInstSuccessValue;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getSuccessValue(), TemplateArgs);
+ tempInstSuccessValue = Result.getAs<Expr>();
+ }
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) ExclusiveTrylockFunctionAttr(A->getLocation(), C, tempInstSuccessValue, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::ExternalSourceSymbol: {
+ const auto *A = cast<ExternalSourceSymbolAttr>(At);
+ return A->clone(C);
+ }
+ case attr::FallThrough: {
+ const auto *A = cast<FallThroughAttr>(At);
+ return A->clone(C);
+ }
+ case attr::FastCall: {
+ const auto *A = cast<FastCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Final: {
+ const auto *A = cast<FinalAttr>(At);
+ return A->clone(C);
+ }
+ case attr::FlagEnum: {
+ const auto *A = cast<FlagEnumAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Flatten: {
+ const auto *A = cast<FlattenAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Format: {
+ const auto *A = cast<FormatAttr>(At);
+ return A->clone(C);
+ }
+ case attr::FormatArg: {
+ const auto *A = cast<FormatArgAttr>(At);
+ return A->clone(C);
+ }
+ case attr::FortifyStdLib: {
+ const auto *A = cast<FortifyStdLibAttr>(At);
+ return A->clone(C);
+ }
+ case attr::GNUInline: {
+ const auto *A = cast<GNUInlineAttr>(At);
+ return A->clone(C);
+ }
+ case attr::GuardedBy: {
+ const auto *A = cast<GuardedByAttr>(At);
+ Expr * tempInstArg;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getArg(), TemplateArgs);
+ tempInstArg = Result.getAs<Expr>();
+ }
+ return new (C) GuardedByAttr(A->getLocation(), C, tempInstArg, A->getSpellingListIndex());
+ }
+ case attr::GuardedVar: {
+ const auto *A = cast<GuardedVarAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Hot: {
+ const auto *A = cast<HotAttr>(At);
+ return A->clone(C);
+ }
+ case attr::IBAction: {
+ const auto *A = cast<IBActionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::IBOutlet: {
+ const auto *A = cast<IBOutletAttr>(At);
+ return A->clone(C);
+ }
+ case attr::IBOutletCollection: {
+ const auto *A = cast<IBOutletCollectionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::IFunc: {
+ const auto *A = cast<IFuncAttr>(At);
+ return A->clone(C);
+ }
+ case attr::InitPriority: {
+ const auto *A = cast<InitPriorityAttr>(At);
+ return A->clone(C);
+ }
+ case attr::InitSeg: {
+ const auto *A = cast<InitSegAttr>(At);
+ return A->clone(C);
+ }
+ case attr::IntelOclBicc: {
+ const auto *A = cast<IntelOclBiccAttr>(At);
+ return A->clone(C);
+ }
+ case attr::InternalLinkage: {
+ const auto *A = cast<InternalLinkageAttr>(At);
+ return A->clone(C);
+ }
+ case attr::LTOVisibilityPublic: {
+ const auto *A = cast<LTOVisibilityPublicAttr>(At);
+ return A->clone(C);
+ }
+ case attr::LayoutVersion: {
+ const auto *A = cast<LayoutVersionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::LifetimeBound: {
+ const auto *A = cast<LifetimeBoundAttr>(At);
+ return A->clone(C);
+ }
+ case attr::LockReturned: {
+ const auto *A = cast<LockReturnedAttr>(At);
+ Expr * tempInstArg;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getArg(), TemplateArgs);
+ tempInstArg = Result.getAs<Expr>();
+ }
+ return new (C) LockReturnedAttr(A->getLocation(), C, tempInstArg, A->getSpellingListIndex());
+ }
+ case attr::LocksExcluded: {
+ const auto *A = cast<LocksExcludedAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) LocksExcludedAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::LoopHint: {
+ const auto *A = cast<LoopHintAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MSABI: {
+ const auto *A = cast<MSABIAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MSInheritance: {
+ const auto *A = cast<MSInheritanceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MSNoVTable: {
+ const auto *A = cast<MSNoVTableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MSP430Interrupt: {
+ const auto *A = cast<MSP430InterruptAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MSStruct: {
+ const auto *A = cast<MSStructAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MSVtorDisp: {
+ const auto *A = cast<MSVtorDispAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MaxFieldAlignment: {
+ const auto *A = cast<MaxFieldAlignmentAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MayAlias: {
+ const auto *A = cast<MayAliasAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MicroMips: {
+ const auto *A = cast<MicroMipsAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MinSize: {
+ const auto *A = cast<MinSizeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MinVectorWidth: {
+ const auto *A = cast<MinVectorWidthAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Mips16: {
+ const auto *A = cast<Mips16Attr>(At);
+ return A->clone(C);
+ }
+ case attr::MipsInterrupt: {
+ const auto *A = cast<MipsInterruptAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MipsLongCall: {
+ const auto *A = cast<MipsLongCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::MipsShortCall: {
+ const auto *A = cast<MipsShortCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Mode: {
+ const auto *A = cast<ModeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NSConsumed: {
+ const auto *A = cast<NSConsumedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NSConsumesSelf: {
+ const auto *A = cast<NSConsumesSelfAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NSReturnsAutoreleased: {
+ const auto *A = cast<NSReturnsAutoreleasedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NSReturnsNotRetained: {
+ const auto *A = cast<NSReturnsNotRetainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NSReturnsRetained: {
+ const auto *A = cast<NSReturnsRetainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Naked: {
+ const auto *A = cast<NakedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoAlias: {
+ const auto *A = cast<NoAliasAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoCommon: {
+ const auto *A = cast<NoCommonAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoDebug: {
+ const auto *A = cast<NoDebugAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoDeref: {
+ const auto *A = cast<NoDerefAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoDestroy: {
+ const auto *A = cast<NoDestroyAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoDuplicate: {
+ const auto *A = cast<NoDuplicateAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoEscape: {
+ const auto *A = cast<NoEscapeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoInline: {
+ const auto *A = cast<NoInlineAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoInstrumentFunction: {
+ const auto *A = cast<NoInstrumentFunctionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoMicroMips: {
+ const auto *A = cast<NoMicroMipsAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoMips16: {
+ const auto *A = cast<NoMips16Attr>(At);
+ return A->clone(C);
+ }
+ case attr::NoReturn: {
+ const auto *A = cast<NoReturnAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoSanitize: {
+ const auto *A = cast<NoSanitizeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoSpeculativeLoadHardening: {
+ const auto *A = cast<NoSpeculativeLoadHardeningAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoSplitStack: {
+ const auto *A = cast<NoSplitStackAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoStackProtector: {
+ const auto *A = cast<NoStackProtectorAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoThreadSafetyAnalysis: {
+ const auto *A = cast<NoThreadSafetyAnalysisAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NoThrow: {
+ const auto *A = cast<NoThrowAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NonNull: {
+ const auto *A = cast<NonNullAttr>(At);
+ return A->clone(C);
+ }
+ case attr::NotTailCalled: {
+ const auto *A = cast<NotTailCalledAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OMPCaptureKind: {
+ const auto *A = cast<OMPCaptureKindAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OMPCaptureNoInit: {
+ const auto *A = cast<OMPCaptureNoInitAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OMPDeclareSimdDecl: {
+ const auto *A = cast<OMPDeclareSimdDeclAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OMPDeclareTargetDecl: {
+ const auto *A = cast<OMPDeclareTargetDeclAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OMPReferencedVar: {
+ const auto *A = cast<OMPReferencedVarAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OMPThreadPrivateDecl: {
+ const auto *A = cast<OMPThreadPrivateDeclAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OSConsumed: {
+ const auto *A = cast<OSConsumedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OSConsumesThis: {
+ const auto *A = cast<OSConsumesThisAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OSReturnsNotRetained: {
+ const auto *A = cast<OSReturnsNotRetainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OSReturnsRetained: {
+ const auto *A = cast<OSReturnsRetainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OSReturnsRetainedOnNonZero: {
+ const auto *A = cast<OSReturnsRetainedOnNonZeroAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OSReturnsRetainedOnZero: {
+ const auto *A = cast<OSReturnsRetainedOnZeroAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCBoxable: {
+ const auto *A = cast<ObjCBoxableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCBridge: {
+ const auto *A = cast<ObjCBridgeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCBridgeMutable: {
+ const auto *A = cast<ObjCBridgeMutableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCBridgeRelated: {
+ const auto *A = cast<ObjCBridgeRelatedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCDesignatedInitializer: {
+ const auto *A = cast<ObjCDesignatedInitializerAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCException: {
+ const auto *A = cast<ObjCExceptionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCExplicitProtocolImpl: {
+ const auto *A = cast<ObjCExplicitProtocolImplAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCExternallyRetained: {
+ const auto *A = cast<ObjCExternallyRetainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCGC: {
+ const auto *A = cast<ObjCGCAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCIndependentClass: {
+ const auto *A = cast<ObjCIndependentClassAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCInertUnsafeUnretained: {
+ const auto *A = cast<ObjCInertUnsafeUnretainedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCKindOf: {
+ const auto *A = cast<ObjCKindOfAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCMethodFamily: {
+ const auto *A = cast<ObjCMethodFamilyAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCNSObject: {
+ const auto *A = cast<ObjCNSObjectAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCNonLazyClass: {
+ const auto *A = cast<ObjCNonLazyClassAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCOwnership: {
+ const auto *A = cast<ObjCOwnershipAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCPreciseLifetime: {
+ const auto *A = cast<ObjCPreciseLifetimeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCRequiresPropertyDefs: {
+ const auto *A = cast<ObjCRequiresPropertyDefsAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCRequiresSuper: {
+ const auto *A = cast<ObjCRequiresSuperAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCReturnsInnerPointer: {
+ const auto *A = cast<ObjCReturnsInnerPointerAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCRootClass: {
+ const auto *A = cast<ObjCRootClassAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCRuntimeName: {
+ const auto *A = cast<ObjCRuntimeNameAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCRuntimeVisible: {
+ const auto *A = cast<ObjCRuntimeVisibleAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ObjCSubclassingRestricted: {
+ const auto *A = cast<ObjCSubclassingRestrictedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLAccess: {
+ const auto *A = cast<OpenCLAccessAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLConstantAddressSpace: {
+ const auto *A = cast<OpenCLConstantAddressSpaceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLGenericAddressSpace: {
+ const auto *A = cast<OpenCLGenericAddressSpaceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLGlobalAddressSpace: {
+ const auto *A = cast<OpenCLGlobalAddressSpaceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLIntelReqdSubGroupSize: {
+ const auto *A = cast<OpenCLIntelReqdSubGroupSizeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLKernel: {
+ const auto *A = cast<OpenCLKernelAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLLocalAddressSpace: {
+ const auto *A = cast<OpenCLLocalAddressSpaceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLPrivateAddressSpace: {
+ const auto *A = cast<OpenCLPrivateAddressSpaceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OpenCLUnrollHint: {
+ const auto *A = cast<OpenCLUnrollHintAttr>(At);
+ return A->clone(C);
+ }
+ case attr::OptimizeNone: {
+ const auto *A = cast<OptimizeNoneAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Overloadable: {
+ const auto *A = cast<OverloadableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Override: {
+ const auto *A = cast<OverrideAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Ownership: {
+ const auto *A = cast<OwnershipAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Packed: {
+ const auto *A = cast<PackedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ParamTypestate: {
+ const auto *A = cast<ParamTypestateAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Pascal: {
+ const auto *A = cast<PascalAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PassObjectSize: {
+ const auto *A = cast<PassObjectSizeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Pcs: {
+ const auto *A = cast<PcsAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PragmaClangBSSSection: {
+ const auto *A = cast<PragmaClangBSSSectionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PragmaClangDataSection: {
+ const auto *A = cast<PragmaClangDataSectionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PragmaClangRodataSection: {
+ const auto *A = cast<PragmaClangRodataSectionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PragmaClangTextSection: {
+ const auto *A = cast<PragmaClangTextSectionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PreserveAll: {
+ const auto *A = cast<PreserveAllAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PreserveMost: {
+ const auto *A = cast<PreserveMostAttr>(At);
+ return A->clone(C);
+ }
+ case attr::PtGuardedBy: {
+ const auto *A = cast<PtGuardedByAttr>(At);
+ Expr * tempInstArg;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getArg(), TemplateArgs);
+ tempInstArg = Result.getAs<Expr>();
+ }
+ return new (C) PtGuardedByAttr(A->getLocation(), C, tempInstArg, A->getSpellingListIndex());
+ }
+ case attr::PtGuardedVar: {
+ const auto *A = cast<PtGuardedVarAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Ptr32: {
+ const auto *A = cast<Ptr32Attr>(At);
+ return A->clone(C);
+ }
+ case attr::Ptr64: {
+ const auto *A = cast<Ptr64Attr>(At);
+ return A->clone(C);
+ }
+ case attr::Pure: {
+ const auto *A = cast<PureAttr>(At);
+ return A->clone(C);
+ }
+ case attr::RISCVInterrupt: {
+ const auto *A = cast<RISCVInterruptAttr>(At);
+ return A->clone(C);
+ }
+ case attr::RegCall: {
+ const auto *A = cast<RegCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Reinitializes: {
+ const auto *A = cast<ReinitializesAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ReleaseCapability: {
+ const auto *A = cast<ReleaseCapabilityAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) ReleaseCapabilityAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::RenderScriptKernel: {
+ const auto *A = cast<RenderScriptKernelAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ReqdWorkGroupSize: {
+ const auto *A = cast<ReqdWorkGroupSizeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::RequireConstantInit: {
+ const auto *A = cast<RequireConstantInitAttr>(At);
+ return A->clone(C);
+ }
+ case attr::RequiresCapability: {
+ const auto *A = cast<RequiresCapabilityAttr>(At);
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) RequiresCapabilityAttr(A->getLocation(), C, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::Restrict: {
+ const auto *A = cast<RestrictAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ReturnTypestate: {
+ const auto *A = cast<ReturnTypestateAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ReturnsNonNull: {
+ const auto *A = cast<ReturnsNonNullAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ReturnsTwice: {
+ const auto *A = cast<ReturnsTwiceAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SPtr: {
+ const auto *A = cast<SPtrAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ScopedLockable: {
+ const auto *A = cast<ScopedLockableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Section: {
+ const auto *A = cast<SectionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SelectAny: {
+ const auto *A = cast<SelectAnyAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Sentinel: {
+ const auto *A = cast<SentinelAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SetTypestate: {
+ const auto *A = cast<SetTypestateAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SharedTrylockFunction: {
+ const auto *A = cast<SharedTrylockFunctionAttr>(At);
+ Expr * tempInstSuccessValue;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getSuccessValue(), TemplateArgs);
+ tempInstSuccessValue = Result.getAs<Expr>();
+ }
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) SharedTrylockFunctionAttr(A->getLocation(), C, tempInstSuccessValue, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::SpeculativeLoadHardening: {
+ const auto *A = cast<SpeculativeLoadHardeningAttr>(At);
+ return A->clone(C);
+ }
+ case attr::StdCall: {
+ const auto *A = cast<StdCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Suppress: {
+ const auto *A = cast<SuppressAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SwiftCall: {
+ const auto *A = cast<SwiftCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SwiftContext: {
+ const auto *A = cast<SwiftContextAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SwiftErrorResult: {
+ const auto *A = cast<SwiftErrorResultAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SwiftIndirectResult: {
+ const auto *A = cast<SwiftIndirectResultAttr>(At);
+ return A->clone(C);
+ }
+ case attr::SysVABI: {
+ const auto *A = cast<SysVABIAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TLSModel: {
+ const auto *A = cast<TLSModelAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Target: {
+ const auto *A = cast<TargetAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TestTypestate: {
+ const auto *A = cast<TestTypestateAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ThisCall: {
+ const auto *A = cast<ThisCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Thread: {
+ const auto *A = cast<ThreadAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TransparentUnion: {
+ const auto *A = cast<TransparentUnionAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TrivialABI: {
+ const auto *A = cast<TrivialABIAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TryAcquireCapability: {
+ const auto *A = cast<TryAcquireCapabilityAttr>(At);
+ Expr * tempInstSuccessValue;
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ ExprResult Result = S.SubstExpr(A->getSuccessValue(), TemplateArgs);
+ tempInstSuccessValue = Result.getAs<Expr>();
+ }
+ auto *tempInstArgs = new (C, 16) Expr *[A->args_size()];
+ {
+ EnterExpressionEvaluationContext Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);
+ Expr * *TI = tempInstArgs;
+ Expr * *I = A->args_begin();
+ Expr * *E = A->args_end();
+ for (; I != E; ++I, ++TI) {
+ ExprResult Result = S.SubstExpr(*I, TemplateArgs);
+ *TI = Result.getAs<Expr>();
+ }
+ }
+ return new (C) TryAcquireCapabilityAttr(A->getLocation(), C, tempInstSuccessValue, tempInstArgs, A->args_size(), A->getSpellingListIndex());
+ }
+ case attr::TypeNonNull: {
+ const auto *A = cast<TypeNonNullAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TypeNullUnspecified: {
+ const auto *A = cast<TypeNullUnspecifiedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TypeNullable: {
+ const auto *A = cast<TypeNullableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TypeTagForDatatype: {
+ const auto *A = cast<TypeTagForDatatypeAttr>(At);
+ return A->clone(C);
+ }
+ case attr::TypeVisibility: {
+ return nullptr;
+ }
+ case attr::UPtr: {
+ const auto *A = cast<UPtrAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Unavailable: {
+ const auto *A = cast<UnavailableAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Uninitialized: {
+ const auto *A = cast<UninitializedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Unused: {
+ const auto *A = cast<UnusedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Used: {
+ const auto *A = cast<UsedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Uuid: {
+ const auto *A = cast<UuidAttr>(At);
+ return A->clone(C);
+ }
+ case attr::VecReturn: {
+ const auto *A = cast<VecReturnAttr>(At);
+ return A->clone(C);
+ }
+ case attr::VecTypeHint: {
+ const auto *A = cast<VecTypeHintAttr>(At);
+ return A->clone(C);
+ }
+ case attr::VectorCall: {
+ const auto *A = cast<VectorCallAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Visibility: {
+ return nullptr;
+ }
+ case attr::WarnUnused: {
+ const auto *A = cast<WarnUnusedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::WarnUnusedResult: {
+ const auto *A = cast<WarnUnusedResultAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Weak: {
+ const auto *A = cast<WeakAttr>(At);
+ return A->clone(C);
+ }
+ case attr::WeakImport: {
+ const auto *A = cast<WeakImportAttr>(At);
+ return A->clone(C);
+ }
+ case attr::WeakRef: {
+ const auto *A = cast<WeakRefAttr>(At);
+ return A->clone(C);
+ }
+ case attr::WebAssemblyImportModule: {
+ const auto *A = cast<WebAssemblyImportModuleAttr>(At);
+ return A->clone(C);
+ }
+ case attr::WebAssemblyImportName: {
+ const auto *A = cast<WebAssemblyImportNameAttr>(At);
+ return A->clone(C);
+ }
+ case attr::WorkGroupSizeHint: {
+ const auto *A = cast<WorkGroupSizeHintAttr>(At);
+ return A->clone(C);
+ }
+ case attr::X86ForceAlignArgPointer: {
+ const auto *A = cast<X86ForceAlignArgPointerAttr>(At);
+ return A->clone(C);
+ }
+ case attr::XRayInstrument: {
+ const auto *A = cast<XRayInstrumentAttr>(At);
+ return A->clone(C);
+ }
+ case attr::XRayLogArgs: {
+ const auto *A = cast<XRayLogArgsAttr>(At);
+ return A->clone(C);
+ }
+ } // end switch
+ llvm_unreachable("Unknown attribute!");
+ return nullptr;
+}
+
+Attr *instantiateTemplateAttributeForDecl(const Attr *At,
+ ASTContext &C, Sema &S,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ switch (At->getKind()) {
+ case attr::AArch64VectorPcs: {
+ return nullptr;
+ }
+ case attr::AMDGPUFlatWorkGroupSize: {
+ return nullptr;
+ }
+ case attr::AMDGPUNumSGPR: {
+ return nullptr;
+ }
+ case attr::AMDGPUNumVGPR: {
+ return nullptr;
+ }
+ case attr::AMDGPUWavesPerEU: {
+ return nullptr;
+ }
+ case attr::ARMInterrupt: {
+ return nullptr;
+ }
+ case attr::AVRInterrupt: {
+ return nullptr;
+ }
+ case attr::AVRSignal: {
+ return nullptr;
+ }
+ case attr::AbiTag: {
+ const auto *A = cast<AbiTagAttr>(At);
+ return A->clone(C);
+ }
+ case attr::AcquireCapability: {
+ return nullptr;
+ }
+ case attr::AcquiredAfter: {
+ return nullptr;
+ }
+ case attr::AcquiredBefore: {
+ return nullptr;
+ }
+ case attr::AddressSpace: {
+ return nullptr;
+ }
+ case attr::Alias: {
+ return nullptr;
+ }
+ case attr::AlignMac68k: {
+ return nullptr;
+ }
+ case attr::AlignValue: {
+ return nullptr;
+ }
+ case attr::Aligned: {
+ return nullptr;
+ }
+ case attr::AllocAlign: {
+ return nullptr;
+ }
+ case attr::AllocSize: {
+ return nullptr;
+ }
+ case attr::AlwaysDestroy: {
+ return nullptr;
+ }
+ case attr::AlwaysInline: {
+ return nullptr;
+ }
+ case attr::AnalyzerNoReturn: {
+ return nullptr;
+ }
+ case attr::Annotate: {
+ return nullptr;
+ }
+ case attr::AnyX86Interrupt: {
+ return nullptr;
+ }
+ case attr::AnyX86NoCallerSavedRegisters: {
+ return nullptr;
+ }
+ case attr::AnyX86NoCfCheck: {
+ return nullptr;
+ }
+ case attr::ArcWeakrefUnavailable: {
+ return nullptr;
+ }
+ case attr::ArgumentWithTypeTag: {
+ return nullptr;
+ }
+ case attr::Artificial: {
+ return nullptr;
+ }
+ case attr::AsmLabel: {
+ return nullptr;
+ }
+ case attr::AssertCapability: {
+ return nullptr;
+ }
+ case attr::AssertExclusiveLock: {
+ return nullptr;
+ }
+ case attr::AssertSharedLock: {
+ return nullptr;
+ }
+ case attr::AssumeAligned: {
+ return nullptr;
+ }
+ case attr::Availability: {
+ return nullptr;
+ }
+ case attr::Blocks: {
+ return nullptr;
+ }
+ case attr::C11NoReturn: {
+ return nullptr;
+ }
+ case attr::CDecl: {
+ return nullptr;
+ }
+ case attr::CFAuditedTransfer: {
+ return nullptr;
+ }
+ case attr::CFConsumed: {
+ return nullptr;
+ }
+ case attr::CFReturnsNotRetained: {
+ return nullptr;
+ }
+ case attr::CFReturnsRetained: {
+ return nullptr;
+ }
+ case attr::CFUnknownTransfer: {
+ return nullptr;
+ }
+ case attr::CPUDispatch: {
+ return nullptr;
+ }
+ case attr::CPUSpecific: {
+ return nullptr;
+ }
+ case attr::CUDAConstant: {
+ return nullptr;
+ }
+ case attr::CUDADevice: {
+ return nullptr;
+ }
+ case attr::CUDAGlobal: {
+ return nullptr;
+ }
+ case attr::CUDAHost: {
+ return nullptr;
+ }
+ case attr::CUDAInvalidTarget: {
+ return nullptr;
+ }
+ case attr::CUDALaunchBounds: {
+ return nullptr;
+ }
+ case attr::CUDAShared: {
+ return nullptr;
+ }
+ case attr::CXX11NoReturn: {
+ return nullptr;
+ }
+ case attr::CallableWhen: {
+ return nullptr;
+ }
+ case attr::Callback: {
+ return nullptr;
+ }
+ case attr::Capability: {
+ return nullptr;
+ }
+ case attr::CapturedRecord: {
+ return nullptr;
+ }
+ case attr::CarriesDependency: {
+ return nullptr;
+ }
+ case attr::Cleanup: {
+ return nullptr;
+ }
+ case attr::CodeSeg: {
+ return nullptr;
+ }
+ case attr::Cold: {
+ return nullptr;
+ }
+ case attr::Common: {
+ return nullptr;
+ }
+ case attr::Const: {
+ return nullptr;
+ }
+ case attr::Constructor: {
+ return nullptr;
+ }
+ case attr::Consumable: {
+ return nullptr;
+ }
+ case attr::ConsumableAutoCast: {
+ return nullptr;
+ }
+ case attr::ConsumableSetOnRead: {
+ return nullptr;
+ }
+ case attr::Convergent: {
+ return nullptr;
+ }
+ case attr::DLLExport: {
+ return nullptr;
+ }
+ case attr::DLLExportStaticLocal: {
+ return nullptr;
+ }
+ case attr::DLLImport: {
+ return nullptr;
+ }
+ case attr::DLLImportStaticLocal: {
+ return nullptr;
+ }
+ case attr::Deprecated: {
+ const auto *A = cast<DeprecatedAttr>(At);
+ return A->clone(C);
+ }
+ case attr::Destructor: {
+ return nullptr;
+ }
+ case attr::DiagnoseIf: {
+ return nullptr;
+ }
+ case attr::DisableTailCalls: {
+ return nullptr;
+ }
+ case attr::EmptyBases: {
+ return nullptr;
+ }
+ case attr::EnableIf: {
+ return nullptr;
+ }
+ case attr::EnumExtensibility: {
+ return nullptr;
+ }
+ case attr::ExcludeFromExplicitInstantiation: {
+ const auto *A = cast<ExcludeFromExplicitInstantiationAttr>(At);
+ return A->clone(C);
+ }
+ case attr::ExclusiveTrylockFunction: {
+ return nullptr;
+ }
+ case attr::ExternalSourceSymbol: {
+ return nullptr;
+ }
+ case attr::FallThrough: {
+ return nullptr;
+ }
+ case attr::FastCall: {
+ return nullptr;
+ }
+ case attr::Final: {
+ return nullptr;
+ }
+ case attr::FlagEnum: {
+ return nullptr;
+ }
+ case attr::Flatten: {
+ return nullptr;
+ }
+ case attr::Format: {
+ return nullptr;
+ }
+ case attr::FormatArg: {
+ return nullptr;
+ }
+ case attr::FortifyStdLib: {
+ return nullptr;
+ }
+ case attr::GNUInline: {
+ return nullptr;
+ }
+ case attr::GuardedBy: {
+ return nullptr;
+ }
+ case attr::GuardedVar: {
+ return nullptr;
+ }
+ case attr::Hot: {
+ return nullptr;
+ }
+ case attr::IBAction: {
+ return nullptr;
+ }
+ case attr::IBOutlet: {
+ return nullptr;
+ }
+ case attr::IBOutletCollection: {
+ return nullptr;
+ }
+ case attr::IFunc: {
+ return nullptr;
+ }
+ case attr::InitPriority: {
+ return nullptr;
+ }
+ case attr::InitSeg: {
+ return nullptr;
+ }
+ case attr::IntelOclBicc: {
+ return nullptr;
+ }
+ case attr::InternalLinkage: {
+ return nullptr;
+ }
+ case attr::LTOVisibilityPublic: {
+ return nullptr;
+ }
+ case attr::LayoutVersion: {
+ return nullptr;
+ }
+ case attr::LifetimeBound: {
+ return nullptr;
+ }
+ case attr::LockReturned: {
+ return nullptr;
+ }
+ case attr::LocksExcluded: {
+ return nullptr;
+ }
+ case attr::LoopHint: {
+ return nullptr;
+ }
+ case attr::MSABI: {
+ return nullptr;
+ }
+ case attr::MSInheritance: {
+ return nullptr;
+ }
+ case attr::MSNoVTable: {
+ return nullptr;
+ }
+ case attr::MSP430Interrupt: {
+ return nullptr;
+ }
+ case attr::MSStruct: {
+ return nullptr;
+ }
+ case attr::MSVtorDisp: {
+ return nullptr;
+ }
+ case attr::MaxFieldAlignment: {
+ return nullptr;
+ }
+ case attr::MayAlias: {
+ return nullptr;
+ }
+ case attr::MicroMips: {
+ return nullptr;
+ }
+ case attr::MinSize: {
+ return nullptr;
+ }
+ case attr::MinVectorWidth: {
+ return nullptr;
+ }
+ case attr::Mips16: {
+ return nullptr;
+ }
+ case attr::MipsInterrupt: {
+ return nullptr;
+ }
+ case attr::MipsLongCall: {
+ return nullptr;
+ }
+ case attr::MipsShortCall: {
+ return nullptr;
+ }
+ case attr::Mode: {
+ return nullptr;
+ }
+ case attr::NSConsumed: {
+ return nullptr;
+ }
+ case attr::NSConsumesSelf: {
+ return nullptr;
+ }
+ case attr::NSReturnsAutoreleased: {
+ return nullptr;
+ }
+ case attr::NSReturnsNotRetained: {
+ return nullptr;
+ }
+ case attr::NSReturnsRetained: {
+ return nullptr;
+ }
+ case attr::Naked: {
+ return nullptr;
+ }
+ case attr::NoAlias: {
+ return nullptr;
+ }
+ case attr::NoCommon: {
+ return nullptr;
+ }
+ case attr::NoDebug: {
+ return nullptr;
+ }
+ case attr::NoDeref: {
+ return nullptr;
+ }
+ case attr::NoDestroy: {
+ return nullptr;
+ }
+ case attr::NoDuplicate: {
+ return nullptr;
+ }
+ case attr::NoEscape: {
+ return nullptr;
+ }
+ case attr::NoInline: {
+ return nullptr;
+ }
+ case attr::NoInstrumentFunction: {
+ return nullptr;
+ }
+ case attr::NoMicroMips: {
+ return nullptr;
+ }
+ case attr::NoMips16: {
+ return nullptr;
+ }
+ case attr::NoReturn: {
+ return nullptr;
+ }
+ case attr::NoSanitize: {
+ return nullptr;
+ }
+ case attr::NoSpeculativeLoadHardening: {
+ return nullptr;
+ }
+ case attr::NoSplitStack: {
+ return nullptr;
+ }
+ case attr::NoStackProtector: {
+ return nullptr;
+ }
+ case attr::NoThreadSafetyAnalysis: {
+ return nullptr;
+ }
+ case attr::NoThrow: {
+ return nullptr;
+ }
+ case attr::NonNull: {
+ return nullptr;
+ }
+ case attr::NotTailCalled: {
+ return nullptr;
+ }
+ case attr::OMPCaptureKind: {
+ return nullptr;
+ }
+ case attr::OMPCaptureNoInit: {
+ return nullptr;
+ }
+ case attr::OMPDeclareSimdDecl: {
+ return nullptr;
+ }
+ case attr::OMPDeclareTargetDecl: {
+ return nullptr;
+ }
+ case attr::OMPReferencedVar: {
+ return nullptr;
+ }
+ case attr::OMPThreadPrivateDecl: {
+ return nullptr;
+ }
+ case attr::OSConsumed: {
+ return nullptr;
+ }
+ case attr::OSConsumesThis: {
+ return nullptr;
+ }
+ case attr::OSReturnsNotRetained: {
+ return nullptr;
+ }
+ case attr::OSReturnsRetained: {
+ return nullptr;
+ }
+ case attr::OSReturnsRetainedOnNonZero: {
+ return nullptr;
+ }
+ case attr::OSReturnsRetainedOnZero: {
+ return nullptr;
+ }
+ case attr::ObjCBoxable: {
+ return nullptr;
+ }
+ case attr::ObjCBridge: {
+ return nullptr;
+ }
+ case attr::ObjCBridgeMutable: {
+ return nullptr;
+ }
+ case attr::ObjCBridgeRelated: {
+ return nullptr;
+ }
+ case attr::ObjCDesignatedInitializer: {
+ return nullptr;
+ }
+ case attr::ObjCException: {
+ return nullptr;
+ }
+ case attr::ObjCExplicitProtocolImpl: {
+ return nullptr;
+ }
+ case attr::ObjCExternallyRetained: {
+ return nullptr;
+ }
+ case attr::ObjCGC: {
+ return nullptr;
+ }
+ case attr::ObjCIndependentClass: {
+ return nullptr;
+ }
+ case attr::ObjCInertUnsafeUnretained: {
+ return nullptr;
+ }
+ case attr::ObjCKindOf: {
+ return nullptr;
+ }
+ case attr::ObjCMethodFamily: {
+ return nullptr;
+ }
+ case attr::ObjCNSObject: {
+ return nullptr;
+ }
+ case attr::ObjCNonLazyClass: {
+ return nullptr;
+ }
+ case attr::ObjCOwnership: {
+ return nullptr;
+ }
+ case attr::ObjCPreciseLifetime: {
+ return nullptr;
+ }
+ case attr::ObjCRequiresPropertyDefs: {
+ return nullptr;
+ }
+ case attr::ObjCRequiresSuper: {
+ return nullptr;
+ }
+ case attr::ObjCReturnsInnerPointer: {
+ return nullptr;
+ }
+ case attr::ObjCRootClass: {
+ return nullptr;
+ }
+ case attr::ObjCRuntimeName: {
+ return nullptr;
+ }
+ case attr::ObjCRuntimeVisible: {
+ return nullptr;
+ }
+ case attr::ObjCSubclassingRestricted: {
+ return nullptr;
+ }
+ case attr::OpenCLAccess: {
+ return nullptr;
+ }
+ case attr::OpenCLConstantAddressSpace: {
+ return nullptr;
+ }
+ case attr::OpenCLGenericAddressSpace: {
+ return nullptr;
+ }
+ case attr::OpenCLGlobalAddressSpace: {
+ return nullptr;
+ }
+ case attr::OpenCLIntelReqdSubGroupSize: {
+ return nullptr;
+ }
+ case attr::OpenCLKernel: {
+ return nullptr;
+ }
+ case attr::OpenCLLocalAddressSpace: {
+ return nullptr;
+ }
+ case attr::OpenCLPrivateAddressSpace: {
+ return nullptr;
+ }
+ case attr::OpenCLUnrollHint: {
+ return nullptr;
+ }
+ case attr::OptimizeNone: {
+ return nullptr;
+ }
+ case attr::Overloadable: {
+ return nullptr;
+ }
+ case attr::Override: {
+ return nullptr;
+ }
+ case attr::Ownership: {
+ return nullptr;
+ }
+ case attr::Packed: {
+ return nullptr;
+ }
+ case attr::ParamTypestate: {
+ return nullptr;
+ }
+ case attr::Pascal: {
+ return nullptr;
+ }
+ case attr::PassObjectSize: {
+ return nullptr;
+ }
+ case attr::Pcs: {
+ return nullptr;
+ }
+ case attr::PragmaClangBSSSection: {
+ return nullptr;
+ }
+ case attr::PragmaClangDataSection: {
+ return nullptr;
+ }
+ case attr::PragmaClangRodataSection: {
+ return nullptr;
+ }
+ case attr::PragmaClangTextSection: {
+ return nullptr;
+ }
+ case attr::PreserveAll: {
+ return nullptr;
+ }
+ case attr::PreserveMost: {
+ return nullptr;
+ }
+ case attr::PtGuardedBy: {
+ return nullptr;
+ }
+ case attr::PtGuardedVar: {
+ return nullptr;
+ }
+ case attr::Ptr32: {
+ return nullptr;
+ }
+ case attr::Ptr64: {
+ return nullptr;
+ }
+ case attr::Pure: {
+ return nullptr;
+ }
+ case attr::RISCVInterrupt: {
+ return nullptr;
+ }
+ case attr::RegCall: {
+ return nullptr;
+ }
+ case attr::Reinitializes: {
+ return nullptr;
+ }
+ case attr::ReleaseCapability: {
+ return nullptr;
+ }
+ case attr::RenderScriptKernel: {
+ return nullptr;
+ }
+ case attr::ReqdWorkGroupSize: {
+ return nullptr;
+ }
+ case attr::RequireConstantInit: {
+ return nullptr;
+ }
+ case attr::RequiresCapability: {
+ return nullptr;
+ }
+ case attr::Restrict: {
+ return nullptr;
+ }
+ case attr::ReturnTypestate: {
+ return nullptr;
+ }
+ case attr::ReturnsNonNull: {
+ return nullptr;
+ }
+ case attr::ReturnsTwice: {
+ return nullptr;
+ }
+ case attr::SPtr: {
+ return nullptr;
+ }
+ case attr::ScopedLockable: {
+ return nullptr;
+ }
+ case attr::Section: {
+ return nullptr;
+ }
+ case attr::SelectAny: {
+ return nullptr;
+ }
+ case attr::Sentinel: {
+ return nullptr;
+ }
+ case attr::SetTypestate: {
+ return nullptr;
+ }
+ case attr::SharedTrylockFunction: {
+ return nullptr;
+ }
+ case attr::SpeculativeLoadHardening: {
+ return nullptr;
+ }
+ case attr::StdCall: {
+ return nullptr;
+ }
+ case attr::Suppress: {
+ return nullptr;
+ }
+ case attr::SwiftCall: {
+ return nullptr;
+ }
+ case attr::SwiftContext: {
+ return nullptr;
+ }
+ case attr::SwiftErrorResult: {
+ return nullptr;
+ }
+ case attr::SwiftIndirectResult: {
+ return nullptr;
+ }
+ case attr::SysVABI: {
+ return nullptr;
+ }
+ case attr::TLSModel: {
+ return nullptr;
+ }
+ case attr::Target: {
+ return nullptr;
+ }
+ case attr::TestTypestate: {
+ return nullptr;
+ }
+ case attr::ThisCall: {
+ return nullptr;
+ }
+ case attr::Thread: {
+ return nullptr;
+ }
+ case attr::TransparentUnion: {
+ return nullptr;
+ }
+ case attr::TrivialABI: {
+ return nullptr;
+ }
+ case attr::TryAcquireCapability: {
+ return nullptr;
+ }
+ case attr::TypeNonNull: {
+ return nullptr;
+ }
+ case attr::TypeNullUnspecified: {
+ return nullptr;
+ }
+ case attr::TypeNullable: {
+ return nullptr;
+ }
+ case attr::TypeTagForDatatype: {
+ return nullptr;
+ }
+ case attr::TypeVisibility: {
+ return nullptr;
+ }
+ case attr::UPtr: {
+ return nullptr;
+ }
+ case attr::Unavailable: {
+ return nullptr;
+ }
+ case attr::Uninitialized: {
+ return nullptr;
+ }
+ case attr::Unused: {
+ return nullptr;
+ }
+ case attr::Used: {
+ return nullptr;
+ }
+ case attr::Uuid: {
+ return nullptr;
+ }
+ case attr::VecReturn: {
+ return nullptr;
+ }
+ case attr::VecTypeHint: {
+ return nullptr;
+ }
+ case attr::VectorCall: {
+ return nullptr;
+ }
+ case attr::Visibility: {
+ return nullptr;
+ }
+ case attr::WarnUnused: {
+ return nullptr;
+ }
+ case attr::WarnUnusedResult: {
+ return nullptr;
+ }
+ case attr::Weak: {
+ return nullptr;
+ }
+ case attr::WeakImport: {
+ return nullptr;
+ }
+ case attr::WeakRef: {
+ return nullptr;
+ }
+ case attr::WebAssemblyImportModule: {
+ return nullptr;
+ }
+ case attr::WebAssemblyImportName: {
+ return nullptr;
+ }
+ case attr::WorkGroupSizeHint: {
+ return nullptr;
+ }
+ case attr::X86ForceAlignArgPointer: {
+ return nullptr;
+ }
+ case attr::XRayInstrument: {
+ return nullptr;
+ }
+ case attr::XRayLogArgs: {
+ return nullptr;
+ }
+ } // end switch
+ llvm_unreachable("Unknown attribute!");
+ return nullptr;
+}
+
+} // end namespace sema
+} // end namespace clang
diff --git a/clang-r353983e/include/clang/Sema/CXXFieldCollector.h b/clang-r353983e/include/clang/Sema/CXXFieldCollector.h
new file mode 100644
index 00000000..f6ecd9f4
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/CXXFieldCollector.h
@@ -0,0 +1,79 @@
+//===- 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
diff --git a/clang-r353983e/include/clang/Sema/CleanupInfo.h b/clang-r353983e/include/clang/Sema/CleanupInfo.h
new file mode 100644
index 00000000..ea9df49f
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/CleanupInfo.h
@@ -0,0 +1,46 @@
+//===--- 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_CLEANUP_INFO_H
+#define LLVM_CLANG_SEMA_CLEANUP_INFO_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
diff --git a/clang-r353983e/include/clang/Sema/CodeCompleteConsumer.h b/clang-r353983e/include/clang/Sema/CodeCompleteConsumer.h
new file mode 100644
index 00000000..72ba8bf3
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/CodeCompleteConsumer.h
@@ -0,0 +1,1208 @@
+//===- 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/None.h"
+#include "llvm/ADT/Optional.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 <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,
+
+ /// 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;
+
+ /// 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::"
+ llvm::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), SelIdents(None) {}
+
+ /// Construct a new code-completion context of the given kind.
+ CodeCompletionContext(Kind CCKind, QualType T,
+ ArrayRef<IdentifierInfo *> SelIdents = None)
+ : CCKind(CCKind), SelIdents(SelIdents) {
+ if (CCKind == CCC_DotMemberAccess || CCKind == CCC_ArrowMemberAccess ||
+ CCKind == CCC_ObjCPropertyAccess || CCKind == CCC_ObjCClassMessage ||
+ CCKind == CCC_ObjCInstanceMessage)
+ BaseType = T;
+ else
+ PreferredType = T;
+ }
+
+ /// 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;
+ }
+
+ llvm::Optional<const CXXScopeSpec *> getCXXScopeSpecifier() {
+ if (ScopeSpecifier)
+ return ScopeSpecifier.getPointer();
+ return llvm::None;
+ }
+};
+
+/// Get string representation of \p Kind, useful for 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 TypedText chunk.
+ const char *getTypedText() 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;
+
+ /// 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), 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) {}
+
+ /// 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),
+ 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) {}
+
+ /// 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) {
+ 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);
+}
+
+raw_ostream &operator<<(raw_ostream &OS,
+ const CodeCompletionString &CCS);
+
+/// Abstract interface for a consumer of code-completion
+/// information.
+class CodeCompleteConsumer {
+protected:
+ const CodeCompleteOptions CodeCompleteOpts;
+
+ /// Whether the output format for the code-completion consumer is
+ /// binary.
+ bool OutputIsBinary;
+
+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.
+ CK_FunctionTemplate,
+
+ /// The "candidate" is actually a variable, expression, or block
+ /// for which we only have a function prototype.
+ CK_FunctionType
+ };
+
+ 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;
+ };
+
+ public:
+ OverloadCandidate(FunctionDecl *Function)
+ : Kind(CK_Function), Function(Function) {}
+
+ OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl)
+ : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) {}
+
+ OverloadCandidate(const FunctionType *Type)
+ : Kind(CK_FunctionType), Type(Type) {}
+
+ /// 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;
+
+ /// 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) const;
+ };
+
+ CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts,
+ bool OutputIsBinary)
+ : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary) {}
+
+ /// 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;
+ }
+
+ /// Determine whether the output of this consumer is binary.
+ bool isOutputBinary() const { return OutputIsBinary; }
+
+ /// 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) {}
+ //@}
+
+ /// 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, false), 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) 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
diff --git a/clang-r353983e/include/clang/Sema/CodeCompleteOptions.h b/clang-r353983e/include/clang/Sema/CodeCompleteOptions.h
new file mode 100644
index 00000000..a3403b01
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/CodeCompleteOptions.h
@@ -0,0 +1,55 @@
+//===---- 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
+
diff --git a/clang-r353983e/include/clang/Sema/DeclSpec.h b/clang-r353983e/include/clang/Sema/DeclSpec.h
new file mode 100644
index 00000000..babdc9d8
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/DeclSpec.h
@@ -0,0 +1,2594 @@
+//===--- 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/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/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.isValid(); }
+ /// 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 isNotEmpty() && getScopeRep() == nullptr; }
+ /// A scope specifier is present, and it refers to a real scope.
+ bool isValid() const { return isNotEmpty() && 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;
+
+ // Import type specifier width enumeration and constants.
+ typedef TypeSpecifierWidth TSW;
+ static const TSW TSW_unspecified = clang::TSW_unspecified;
+ static const TSW TSW_short = clang::TSW_short;
+ static const TSW TSW_long = clang::TSW_long;
+ static const TSW TSW_longlong = clang::TSW_longlong;
+
+ enum TSC {
+ TSC_unspecified,
+ TSC_imaginary,
+ TSC_complex
+ };
+
+ // Import type specifier sign enumeration and constants.
+ typedef TypeSpecifierSign TSS;
+ static const TSS TSS_unspecified = clang::TSS_unspecified;
+ static const TSS TSS_signed = clang::TSS_signed;
+ static const TSS TSS_unsigned = clang::TSS_unsigned;
+
+ // 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_half = clang::TST_half;
+ 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_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_decltype = clang::TST_decltype;
+ static const TST TST_decltype_auto = clang::TST_decltype_auto;
+ static const TST TST_underlyingType = clang::TST_underlyingType;
+ 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.
+ };
+
+private:
+ // storage-class-specifier
+ /*SCS*/unsigned StorageClassSpec : 3;
+ /*TSCS*/unsigned ThreadStorageClassSpec : 2;
+ unsigned SCS_extern_in_linkage_spec : 1;
+
+ // type-specifier
+ /*TSW*/unsigned TypeSpecWidth : 2;
+ /*TSC*/unsigned TypeSpecComplex : 2;
+ /*TSS*/unsigned TypeSpecSign : 2;
+ /*TST*/unsigned TypeSpecType : 6;
+ unsigned TypeAltiVecVector : 1;
+ unsigned TypeAltiVecPixel : 1;
+ unsigned TypeAltiVecBool : 1;
+ unsigned TypeSpecOwned : 1;
+ unsigned TypeSpecPipe : 1;
+ unsigned TypeSpecSat : 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_explicit_specified : 1;
+ unsigned FS_noreturn_specified : 1;
+
+ // friend-specifier
+ unsigned Friend_specified : 1;
+
+ // constexpr-specifier
+ unsigned Constexpr_specified : 1;
+
+ union {
+ UnionParsedType TypeRep;
+ Decl *DeclRep;
+ Expr *ExprRep;
+ };
+
+ // 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_forceinlineLoc;
+ SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;
+ SourceLocation TQ_pipeLoc;
+
+ WrittenBuiltinSpecs writtenBS;
+ void SaveWrittenBuiltinSpecs();
+
+ ObjCDeclSpec *ObjCQualifiers;
+
+ static bool isTypeRep(TST T) {
+ return (T == TST_typename || T == TST_typeofType ||
+ T == TST_underlyingType || T == TST_atomic);
+ }
+ static bool isExprRep(TST T) {
+ return (T == TST_typeofExpr || T == TST_decltype);
+ }
+
+ 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);
+ }
+
+ DeclSpec(AttributeFactory &attrFactory)
+ : StorageClassSpec(SCS_unspecified),
+ ThreadStorageClassSpec(TSCS_unspecified),
+ SCS_extern_in_linkage_spec(false),
+ TypeSpecWidth(TSW_unspecified),
+ TypeSpecComplex(TSC_unspecified),
+ TypeSpecSign(TSS_unspecified),
+ TypeSpecType(TST_unspecified),
+ TypeAltiVecVector(false),
+ TypeAltiVecPixel(false),
+ TypeAltiVecBool(false),
+ TypeSpecOwned(false),
+ TypeSpecPipe(false),
+ TypeSpecSat(false),
+ TypeQualifiers(TQ_unspecified),
+ FS_inline_specified(false),
+ FS_forceinline_specified(false),
+ FS_virtual_specified(false),
+ FS_explicit_specified(false),
+ FS_noreturn_specified(false),
+ Friend_specified(false),
+ Constexpr_specified(false),
+ 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
+ TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; }
+ TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; }
+ TSS getTypeSpecSign() const { return (TSS)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; }
+
+ 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;
+ }
+ 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) || TypeSpecType == TST_typename);
+ return TSTNameLoc;
+ }
+
+ SourceRange getTypeofParensRange() const { return TypeofParensRange; }
+ void setTypeofParensRange(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(DeclSpec::TSS S);
+ static const char *getSpecifierName(DeclSpec::TSC C);
+ static const char *getSpecifierName(DeclSpec::TSW W);
+ static const char *getSpecifierName(DeclSpec::SCS S);
+ static const char *getSpecifierName(DeclSpec::TSCS S);
+
+ // 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;
+ }
+
+ bool isVirtualSpecified() const { return FS_virtual_specified; }
+ SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; }
+
+ bool isExplicitSpecified() const { return FS_explicit_specified; }
+ SourceLocation getExplicitSpecLoc() const { return 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_specified = false;
+ FS_explicitLoc = 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() != DeclSpec::TSW_unspecified ||
+ getTypeSpecComplex() != DeclSpec::TSC_unspecified ||
+ getTypeSpecSign() != DeclSpec::TSS_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(TSW W, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, const PrintingPolicy &Policy);
+ bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+ bool SetTypeSpecSign(TSS 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, 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, 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 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);
+ 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(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID);
+
+ bool isFriendSpecified() const { return Friend_specified; }
+ SourceLocation getFriendSpecLoc() const { return FriendLoc; }
+
+ bool isModulePrivateSpecified() const { return ModulePrivateLoc.isValid(); }
+ SourceLocation getModulePrivateSpecLoc() const { return ModulePrivateLoc; }
+
+ bool isConstexprSpecified() const { return Constexpr_specified; }
+ SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }
+
+ void ClearConstexprSpec() {
+ Constexpr_specified = false;
+ 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(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
+ };
+
+ /// PropertyAttributeKind - list of property attributes.
+ /// Keep this list in sync with LLVM's Dwarf.h ApplePropertyAttributes.
+ enum ObjCPropertyAttributeKind {
+ DQ_PR_noattr = 0x0,
+ DQ_PR_readonly = 0x01,
+ DQ_PR_getter = 0x02,
+ DQ_PR_assign = 0x04,
+ DQ_PR_readwrite = 0x08,
+ DQ_PR_retain = 0x10,
+ DQ_PR_copy = 0x20,
+ DQ_PR_nonatomic = 0x40,
+ DQ_PR_setter = 0x80,
+ DQ_PR_atomic = 0x100,
+ DQ_PR_weak = 0x200,
+ DQ_PR_strong = 0x400,
+ DQ_PR_unsafe_unretained = 0x800,
+ DQ_PR_nullability = 0x1000,
+ DQ_PR_null_resettable = 0x2000,
+ DQ_PR_class = 0x4000
+ };
+
+ ObjCDeclSpec()
+ : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_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);
+ }
+
+ ObjCPropertyAttributeKind getPropertyAttributes() const {
+ return ObjCPropertyAttributeKind(PropertyAttributes);
+ }
+ void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) {
+ PropertyAttributes =
+ (ObjCPropertyAttributeKind)(PropertyAttributes | PRVal);
+ }
+
+ NullabilityKind getNullability() const {
+ assert(((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & DQ_PR_nullability)) &&
+ "Objective-C declspec doesn't have nullability");
+ return static_cast<NullabilityKind>(Nullability);
+ }
+
+ SourceLocation getNullabilityLoc() const {
+ assert(((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & DQ_PR_nullability)) &&
+ "Objective-C declspec doesn't have nullability");
+ return NullabilityLoc;
+ }
+
+ void setNullability(SourceLocation loc, NullabilityKind kind) {
+ assert(((getObjCDeclQualifier() & DQ_CSNullability) ||
+ (getPropertyAttributes() & DQ_PR_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 ObjCPropertyAttributeKind
+ unsigned PropertyAttributes : 15;
+
+ 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;
+
+public:
+ /// Describes the kind of unqualified-id parsed.
+ UnqualifiedIdKind Kind;
+
+ 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.
+ unsigned 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; }
+ void setKind(UnqualifiedIdKind kind) { Kind = 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;
+ }
+
+ /// 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 {
+ 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.
+ unsigned ConstQualLoc;
+
+ /// The location of the volatile-qualifier, if any.
+ unsigned VolatileQualLoc;
+
+ /// The location of the restrict-qualifier, if any.
+ unsigned RestrictQualLoc;
+
+ /// The location of the _Atomic-qualifier, if any.
+ unsigned AtomicQualLoc;
+
+ /// The location of the __unaligned-qualifier, if any.
+ unsigned 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.
+ unsigned LParenLoc;
+
+ /// When isVariadic is true, the location of the ellipsis in the source.
+ unsigned EllipsisLoc;
+
+ /// The location of the right parenthesis in the source.
+ unsigned 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.
+ unsigned RefQualifierLoc;
+
+ /// The location of the 'mutable' qualifer in a lambda-declarator, if
+ /// any.
+ unsigned MutableLoc;
+
+ /// The beginning location of the exception specification, if any.
+ unsigned ExceptionSpecLocBeg;
+
+ /// The end location of the exception specification, if any.
+ unsigned 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;
+
+ /// AtttibuteFactory 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;
+
+ /// 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 SourceLocation::getFromRawEncoding(LParenLoc);
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(EllipsisLoc);
+ }
+
+ SourceLocation getRParenLoc() const {
+ return SourceLocation::getFromRawEncoding(RParenLoc);
+ }
+
+ SourceLocation getExceptionSpecLocBeg() const {
+ return SourceLocation::getFromRawEncoding(ExceptionSpecLocBeg);
+ }
+
+ SourceLocation getExceptionSpecLocEnd() const {
+ return SourceLocation::getFromRawEncoding(ExceptionSpecLocEnd);
+ }
+
+ SourceRange getExceptionSpecRange() const {
+ return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd());
+ }
+
+ /// Retrieve the location of the ref-qualifier, if any.
+ SourceLocation getRefQualifierLoc() const {
+ return SourceLocation::getFromRawEncoding(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 SourceLocation::getFromRawEncoding(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::makeArrayRef(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 { return TrailingReturnType; }
+ };
+
+ 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;
+ // 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;
+ I.Ptr.TypeQuals = TypeQuals;
+ I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding();
+ I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding();
+ I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding();
+ I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding();
+ I.Ptr.UnalignedQualLoc = UnalignedQualLoc.getRawEncoding();
+ 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(),
+ 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 Loc) {
+ DeclaratorChunk I;
+ I.Kind = MemberPointer;
+ I.Loc = SS.getBeginLoc();
+ I.EndLoc = Loc;
+ 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::makeArrayRef(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 FunctionDefinitionKind {
+ FDK_Declaration,
+ FDK_Definition,
+ FDK_Defaulted,
+ FDK_Deleted
+};
+
+enum class DeclaratorContext {
+ FileContext, // File scope declaration.
+ PrototypeContext, // Within a function prototype.
+ ObjCResultContext, // An ObjC method result type.
+ ObjCParameterContext,// An ObjC method parameter type.
+ KNRTypeListContext, // K&R type definition list for formals.
+ TypeNameContext, // Abstract declarator for types.
+ FunctionalCastContext, // Type in a C++ functional cast expression.
+ MemberContext, // Struct/Union field.
+ BlockContext, // Declaration within a block in a function.
+ ForContext, // Declaration within first part of a for loop.
+ InitStmtContext, // Declaration within optional init stmt of if/switch.
+ ConditionContext, // Condition declaration in a C++ if/switch/while/for.
+ TemplateParamContext,// Within a template parameter list.
+ CXXNewContext, // C++ new-expression.
+ CXXCatchContext, // C++ catch exception-declaration
+ ObjCCatchContext, // Objective-C catch exception-declaration
+ BlockLiteralContext, // Block literal declarator.
+ LambdaExprContext, // Lambda-expression declarator.
+ LambdaExprParameterContext, // Lambda-expression parameter declarator.
+ ConversionIdContext, // C++ conversion-type-id.
+ TrailingReturnContext, // C++11 trailing-type-specifier.
+ TrailingReturnVarContext, // C++11 trailing-type-specifier for variable.
+ TemplateArgContext, // Any template argument (in template argument list).
+ TemplateTypeArgContext, // Template type argument (in default argument).
+ AliasDeclContext, // C++11 alias-declaration.
+ AliasTemplateContext // C++11 alias-declaration template.
+};
+
+
+/// 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;
+
+ /// Attrs - Attributes.
+ ParsedAttributes Attrs;
+
+ /// The asm label, if specified.
+ Expr *AsmLabel;
+
+#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:
+ Declarator(const DeclSpec &ds, DeclaratorContext C)
+ : DS(ds), Range(ds.getSourceRange()), Context(C),
+ InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
+ GroupingParens(false), FunctionDefinition(FDK_Declaration),
+ Redeclaration(false), Extension(false), ObjCIvar(false),
+ ObjCWeakProperty(false), InlineStorageUsed(false),
+ Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr) {}
+
+ ~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::PrototypeContext ||
+ Context == DeclaratorContext::ObjCParameterContext ||
+ Context == DeclaratorContext::ObjCResultContext ||
+ Context == DeclaratorContext::LambdaExprParameterContext);
+ }
+
+ /// 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;
+ 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::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ return false;
+
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ 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::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ return true;
+
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ 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::FileContext:
+ // FIXME: It's not clear that the proposal meant to allow file-scope
+ // structured bindings, but it does.
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ return true;
+
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::TemplateParamContext:
+ // Maybe one day...
+ return false;
+
+ // These contexts don't allow any kind of non-abstract declarator.
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ 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::FileContext)
+ return false;
+
+ // Special names can't have direct initializers.
+ if (Name.getKind() != UnqualifiedIdKind::IK_Identifier)
+ return false;
+
+ switch (Context) {
+ case DeclaratorContext::FileContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ return true;
+
+ case DeclaratorContext::ConditionContext:
+ // 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::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext: // FIXME
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TrailingReturnContext:
+ 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::FileContext:
+ case DeclaratorContext::MemberContext:
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ return true;
+
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::TypeNameContext:
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TemplateArgContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ 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::FileContext:
+ case DeclaratorContext::KNRTypeListContext:
+ case DeclaratorContext::MemberContext:
+
+ // FIXME: sizeof(...) permits an expression.
+ case DeclaratorContext::TypeNameContext:
+
+ case DeclaratorContext::FunctionalCastContext:
+ case DeclaratorContext::AliasDeclContext:
+ case DeclaratorContext::AliasTemplateContext:
+ case DeclaratorContext::PrototypeContext:
+ case DeclaratorContext::LambdaExprParameterContext:
+ case DeclaratorContext::ObjCParameterContext:
+ case DeclaratorContext::ObjCResultContext:
+ case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::CXXNewContext:
+ case DeclaratorContext::CXXCatchContext:
+ case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::BlockLiteralContext:
+ case DeclaratorContext::LambdaExprContext:
+ case DeclaratorContext::ConversionIdContext:
+ case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::TemplateTypeArgContext:
+ return false;
+
+ case DeclaratorContext::BlockContext:
+ case DeclaratorContext::ForContext:
+ case DeclaratorContext::InitStmtContext:
+ case DeclaratorContext::ConditionContext:
+ case DeclaratorContext::TemplateArgContext:
+ 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;
+ }
+
+ /// 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, SourceLocation lastLoc) {
+ Attrs.takeAllFrom(attrs);
+
+ if (!lastLoc.isInvalid())
+ SetRangeEnd(lastLoc);
+ }
+
+ const ParsedAttributes &getAttributes() const { return Attrs; }
+ ParsedAttributes &getAttributes() { return Attrs; }
+
+ /// hasAttributes - do we contain any attributes?
+ bool hasAttributes() const {
+ if (!getAttributes().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 = Val;
+ }
+
+ bool isFunctionDefinition() const {
+ return getFunctionDefinitionKind() != FDK_Declaration;
+ }
+
+ FunctionDefinitionKind getFunctionDefinitionKind() const {
+ return (FunctionDefinitionKind)FunctionDefinition;
+ }
+
+ /// Returns true if this declares a real member and not a friend.
+ bool isFirstDeclarationOfMember() {
+ return getContext() == DeclaratorContext::MemberContext &&
+ !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)
+ : D(DS, DeclaratorContext::MemberContext),
+ 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
+ };
+
+ 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; }
+
+ 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;
+ 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) {}
+
+ /// 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));
+ }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_DECLSPEC_H
diff --git a/clang-r353983e/include/clang/Sema/DelayedDiagnostic.h b/clang-r353983e/include/clang/Sema/DelayedDiagnostic.h
new file mode 100644
index 00000000..929db5df
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/DelayedDiagnostic.h
@@ -0,0 +1,337 @@
+//===- 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::StorageAllocator &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::StorageAllocator &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::makeArrayRef(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
diff --git a/clang-r353983e/include/clang/Sema/Designator.h b/clang-r353983e/include/clang/Sema/Designator.h
new file mode 100644
index 00000000..05f66115
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Designator.h
@@ -0,0 +1,209 @@
+//===--- 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:
+ DesignatorKind Kind;
+
+ struct FieldDesignatorInfo {
+ const IdentifierInfo *II;
+ unsigned DotLoc;
+ unsigned NameLoc;
+ };
+ struct ArrayDesignatorInfo {
+ Expr *Index;
+ unsigned LBracketLoc;
+ mutable unsigned RBracketLoc;
+ };
+ struct ArrayRangeDesignatorInfo {
+ Expr *Start, *End;
+ unsigned LBracketLoc, EllipsisLoc;
+ mutable unsigned 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 SourceLocation::getFromRawEncoding(FieldInfo.DotLoc);
+ }
+
+ SourceLocation getFieldLoc() const {
+ assert(isFieldDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(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 SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc);
+ else
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc);
+ }
+
+ SourceLocation getRBracketLoc() const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc);
+ else
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc);
+ }
+
+ SourceLocation getEllipsisLoc() const {
+ assert(isArrayRangeDesignator() && "Invalid accessor");
+ return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc);
+ }
+
+ static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc,
+ SourceLocation NameLoc) {
+ Designator D;
+ D.Kind = FieldDesignator;
+ D.FieldInfo.II = II;
+ D.FieldInfo.DotLoc = DotLoc.getRawEncoding();
+ D.FieldInfo.NameLoc = NameLoc.getRawEncoding();
+ return D;
+ }
+
+ static Designator getArray(Expr *Index,
+ SourceLocation LBracketLoc) {
+ Designator D;
+ D.Kind = ArrayDesignator;
+ D.ArrayInfo.Index = Index;
+ D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding();
+ D.ArrayInfo.RBracketLoc = 0;
+ return D;
+ }
+
+ static Designator getArrayRange(Expr *Start,
+ Expr *End,
+ SourceLocation LBracketLoc,
+ SourceLocation EllipsisLoc) {
+ Designator D;
+ D.Kind = ArrayRangeDesignator;
+ D.ArrayRangeInfo.Start = Start;
+ D.ArrayRangeInfo.End = End;
+ D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding();
+ D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding();
+ D.ArrayRangeInfo.RBracketLoc = 0;
+ return D;
+ }
+
+ void setRBracketLoc(SourceLocation RBracketLoc) const {
+ assert((isArrayDesignator() || isArrayRangeDesignator()) &&
+ "Invalid accessor");
+ if (isArrayDesignator())
+ ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding();
+ else
+ ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding();
+ }
+
+ /// 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
diff --git a/clang-r353983e/include/clang/Sema/ExternalSemaSource.h b/clang-r353983e/include/clang/Sema/ExternalSemaSource.h
new file mode 100644
index 00000000..88fa6f53
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/ExternalSemaSource.h
@@ -0,0 +1,233 @@
+//===--- 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 CXXDeleteExpr;
+class CXXRecordDecl;
+class DeclaratorDecl;
+class LookupResult;
+struct ObjCMethodList;
+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 {
+public:
+ ExternalSemaSource() {
+ ExternalASTSource::SemaSource = true;
+ }
+
+ ~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) {}
+
+ /// \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;
+ }
+
+ // isa/cast/dyn_cast support
+ static bool classof(const ExternalASTSource *Source) {
+ return Source->SemaSource;
+ }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/clang-r353983e/include/clang/Sema/IdentifierResolver.h b/clang-r353983e/include/clang/Sema/IdentifierResolver.h
new file mode 100644
index 00000000..7c8dc463
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/IdentifierResolver.h
@@ -0,0 +1,205 @@
+//===- 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
diff --git a/clang-r353983e/include/clang/Sema/Initialization.h b/clang-r353983e/include/clang/Sema/Initialization.h
new file mode 100644
index 00000000..8efa2e75
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Initialization.h
@@ -0,0 +1,1393 @@
+//===- 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 APValue;
+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 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.
+ unsigned 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.
+ unsigned Location;
+ };
+
+ union {
+ /// When Kind == EK_Variable, EK_Member or EK_Binding, the variable.
+ 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
+ /// low bit indicating whether the parameter is "consumed".
+ uintptr_t 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 lower bit specifies whether the base is an inherited
+ /// virtual base.
+ uintptr_t 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() = default;
+
+ /// 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) {
+ LocAndNRVO.Location = Loc.getRawEncoding();
+ 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) {
+ Capture.VarID = VarID;
+ Capture.Location = Loc.getRawEncoding();
+ }
+
+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,
+ const ParmVarDecl *Parm) {
+ return InitializeParameter(Context, Parm, Parm->getType());
+ }
+
+ /// Create the initialization entity for a parameter, but use
+ /// another type.
+ static InitializedEntity InitializeParameter(ASTContext &Context,
+ const 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
+ = (static_cast<uintptr_t>(Consumed) | reinterpret_cast<uintptr_t>(Parm));
+ 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 = (Consumed);
+ return Entity;
+ }
+
+ /// Create the initialization entity for the result of a function.
+ static InitializedEntity InitializeResult(SourceLocation ReturnLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO);
+ }
+
+ static InitializedEntity InitializeStmtExprResult(SourceLocation ReturnLoc,
+ QualType Type) {
+ return InitializedEntity(EK_StmtExprResult, ReturnLoc, Type);
+ }
+
+ static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO);
+ }
+
+ static InitializedEntity InitializeLambdaToBlock(SourceLocation BlockVarLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_LambdaToBlockConversionBlockElement,
+ BlockVarLoc, Type, NRVO);
+ }
+
+ /// Create the initialization entity for an exception object.
+ static InitializedEntity InitializeException(SourceLocation ThrowLoc,
+ QualType Type, bool NRVO) {
+ return InitializedEntity(EK_Exception, ThrowLoc, Type, NRVO);
+ }
+
+ /// 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(TypeSourceInfo *TypeInfo) {
+ return InitializeTemporary(TypeInfo, TypeInfo->getType());
+ }
+
+ /// 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.
+ 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);
+ }
+
+ /// Determine whether this initialization consumes the
+ /// parameter.
+ bool isParameterConsumed() const {
+ assert(isParameterKind() && "Not a parameter");
+ return (Parameter & 1);
+ }
+
+ /// Retrieve the base specifier.
+ const CXXBaseSpecifier *getBaseSpecifier() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return reinterpret_cast<const CXXBaseSpecifier *>(Base & ~0x1);
+ }
+
+ /// Return whether the base is an inherited virtual base.
+ bool isInheritedVirtualBase() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return Base & 0x1;
+ }
+
+ /// Determine whether this is an array new with an unknown bound.
+ bool isVariableLengthArrayNew() const {
+ return getKind() == EK_New && dyn_cast_or_null<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 SourceLocation::getFromRawEncoding(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 SourceLocation::getFromRawEncoding(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->getName();
+ }
+
+ /// 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 SourceLocation::getFromRawEncoding(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 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_CastDerivedToBaseRValue,
+
+ /// 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 an rvalue.
+ SK_QualificationConversionRValue,
+
+ /// Perform a qualification conversion, producing an xvalue.
+ SK_QualificationConversionXValue,
+
+ /// Perform a qualification conversion, producing an lvalue.
+ SK_QualificationConversionLValue,
+
+ /// Perform a conversion adding _Atomic to a type.
+ SK_AtomicConversion,
+
+ /// Perform a load from a glvalue, producing an rvalue.
+ SK_LValueToRValue,
+
+ /// 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
+ };
+
+ /// 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 an lvalue of unrelated
+ /// type.
+ FK_NonConstLValueReferenceBindingToUnrelated,
+
+ /// Rvalue reference binding to an lvalue.
+ FK_RValueReferenceBindingToLValue,
+
+ /// Reference binding drops qualifiers.
+ FK_ReferenceInitDropsQualifiers,
+
+ /// 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,
+ };
+
+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;
+
+ /// Returns whether the last step in this initialization sequence is a
+ /// narrowing conversion, defined by C++0x [dcl.init.list]p7.
+ ///
+ /// If this function returns true, *isInitializerConstant will be set to
+ /// describe whether *Initializer was a constant expression. If
+ /// *isInitializerConstant is set to true, *ConstantValue will be set to the
+ /// evaluated value of *Initializer.
+ bool endsWithNarrowing(ASTContext &Ctx, const Expr *Initializer,
+ bool *isInitializerConstant,
+ APValue *ConstantValue) 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 conversion from non-atomic to atomic
+ /// type.
+ void AddAtomicConversionStep(QualType Ty);
+
+ /// Add a new step that performs a load of the given type.
+ ///
+ /// Although the term "LValueToRValue" is conventional, this applies to both
+ /// lvalues and xvalues.
+ void AddLValueToRValueStep(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);
+
+ /// Add a step to initialize by zero types defined in the
+ /// cl_intel_device_side_avc_motion_estimation OpenCL extension
+ void AddOCLIntelSubgroupAVCZeroInitStep(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
diff --git a/clang-r353983e/include/clang/Sema/Lookup.h b/clang-r353983e/include/clang/Sema/Lookup.h
new file mode 100644
index 00000000..990005f1
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Lookup.h
@@ -0,0 +1,812 @@
+//===- 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/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#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) {}
+
+ // 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)) {
+ 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);
+ 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;
+ }
+
+ 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(sanity());
+ 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) {
+ // If this declaration is not hidden, it's visible.
+ if (!D->isHidden())
+ return true;
+
+ // During template instantiation, we can refer to hidden declarations, if
+ // they were visible in any module along the path of instantiation.
+ return isVisibleSlow(SemaRef, D);
+ }
+
+ /// 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 (isVisible(getSema(), D) || isHiddenDeclarationVisible(D))
+ return D;
+
+ return getAcceptableDeclSlow(D);
+ }
+
+private:
+ static bool isVisibleSlow(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 {
+ llvm::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.getValue();
+ } 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();
+
+ // Sanity checks.
+ bool sanity() const;
+
+ bool sanityCheckUnresolved() 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;
+};
+
+/// 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
diff --git a/clang-r353983e/include/clang/Sema/MultiplexExternalSemaSource.h b/clang-r353983e/include/clang/Sema/MultiplexExternalSemaSource.h
new file mode 100644
index 00000000..8157e488
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -0,0 +1,362 @@
+//===--- 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 {
+
+private:
+ SmallVector<ExternalSemaSource *, 2> Sources; // doesn't own them.
+
+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;
+
+ bool DeclIsFromPCHWithObjectFile(const Decl *D) 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;
+
+ /// \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;
+
+ // isa/cast/dyn_cast support
+ static bool classof(const MultiplexExternalSemaSource*) { return true; }
+ //static bool classof(const ExternalSemaSource*) { return true; }
+};
+
+} // end namespace clang
+
+#endif
diff --git a/clang-r353983e/include/clang/Sema/ObjCMethodList.h b/clang-r353983e/include/clang/Sema/ObjCMethodList.h
new file mode 100644
index 00000000..bd2ce2a9
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/ObjCMethodList.h
@@ -0,0 +1,61 @@
+//===--- 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 *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
diff --git a/clang-r353983e/include/clang/Sema/Overload.h b/clang-r353983e/include/clang/Sema/Overload.h
new file mode 100644
index 00000000..f5490e8e
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Overload.h
@@ -0,0 +1,1007 @@
+//===- 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/None.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
+ };
+
+ /// 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,
+
+ /// 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
+ };
+
+ // 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).
+ enum Kind {
+ StandardConversion = 0,
+ UserDefinedConversion,
+ AmbiguousConversion,
+ EllipsisConversion,
+ BadConversion
+ };
+
+ private:
+ enum {
+ Uninitialized = BadConversion + 1
+ };
+
+ /// ConversionKind - The kind of implicit conversion sequence.
+ unsigned ConversionKind : 30;
+
+ /// Whether the target is really a std::initializer_list, and the
+ /// sequence only represents the worst element conversion.
+ unsigned StdInitializerListElement : 1;
+
+ 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), StdInitializerListElement(false) {
+ Standard.setAsIdentityConversion();
+ }
+
+ ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+ : ConversionKind(Other.ConversionKind),
+ StdInitializerListElement(Other.StdInitializerListElement) {
+ switch (ConversionKind) {
+ case Uninitialized: break;
+ case StandardConversion: Standard = Other.Standard; 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:
+ 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 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 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);
+ }
+
+ /// Whether the target is really a std::initializer_list, and the
+ /// sequence only represents the worst element conversion.
+ bool isStdInitializerListElement() const {
+ return StdInitializerListElement;
+ }
+
+ void setStdInitializerListElement(bool V = true) {
+ StdInitializerListElement = V;
+ }
+
+ // 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 was not viable because its address could not be taken.
+ ovl_fail_addr_not_available,
+
+ /// This candidate was not viable because its OpenCL extension is disabled.
+ ovl_fail_ext_disabled,
+
+ /// 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,
+ };
+
+ /// 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.
+ 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;
+
+ /// 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;
+
+ /// 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;
+ };
+
+ /// 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) {
+ auto STy = Surrogate->getConversionType();
+ while (STy->isPointerType() || STy->isReferenceType())
+ STy = STy->getPointeeType();
+ return STy->getAs<FunctionProtoType>()->getNumParams();
+ }
+ if (Function)
+ return Function->getNumParams();
+ return ExplicitCallArguments;
+ }
+
+ private:
+ friend class OverloadCandidateSet;
+ OverloadCandidate() : IsADLCandidate(CallExpr::NotADL) {}
+ };
+
+ /// 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,
+ };
+
+ private:
+ SmallVector<OverloadCandidate, 16> Candidates;
+ llvm::SmallPtrSet<Decl *, 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;
+
+ constexpr static unsigned NumInlineBytes =
+ 24 * sizeof(ImplicitConversionSequence);
+ unsigned NumInlineBytesUsed = 0;
+ llvm::AlignedCharArray<alignof(void *), NumInlineBytes> InlineSpace;
+
+ /// 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.buffer + 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)
+ : Loc(Loc), Kind(CSK) {}
+ OverloadCandidateSet(const OverloadCandidateSet &) = delete;
+ OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete;
+ ~OverloadCandidateSet() { destroyCandidates(); }
+
+ SourceLocation getLocation() const { return Loc; }
+ CandidateSetKind getKind() const { return Kind; }
+
+ /// Determine when this overload candidate will be new to the
+ /// overload set.
+ bool isNewCandidate(Decl *F) {
+ return Functions.insert(F->getCanonicalDecl()).second;
+ }
+
+ /// 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 = None) {
+ 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);
+
+ void NoteCandidates(Sema &S,
+ OverloadCandidateDisplayKind OCD,
+ ArrayRef<Expr *> Args,
+ StringRef Opc = "",
+ SourceLocation Loc = SourceLocation(),
+ llvm::function_ref<bool(OverloadCandidate&)> Filter =
+ [](OverloadCandidate&) { return true; });
+ };
+
+ 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;
+ }
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_OVERLOAD_H
diff --git a/clang-r353983e/include/clang/Sema/Ownership.h b/clang-r353983e/include/clang/Sema/Ownership.h
new file mode 100644
index 00000000..f395282c
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Ownership.h
@@ -0,0 +1,300 @@
+//===- 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>> {
+ enum { 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 DiagnosticBuilder;
+
+ // 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 ExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); }
+ inline StmtResult StmtError(const DiagnosticBuilder&) { 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
diff --git a/clang-r353983e/include/clang/Sema/ParsedAttr.h b/clang-r353983e/include/clang/Sema/ParsedAttr.h
new file mode 100644
index 00000000..d125d3b8
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/ParsedAttr.h
@@ -0,0 +1,1038 @@
+//======- 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_ATTRIBUTELIST_H
+#define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
+
+#include "clang/Basic/AttrSubjectMatchRules.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/Ownership.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/Allocator.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;
+
+/// 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
+ : 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;
+ }
+
+public:
+ /// The style used to specify an attribute.
+ enum Syntax {
+ /// __attribute__((...))
+ AS_GNU,
+
+ /// [[...]]
+ AS_CXX11,
+
+ /// [[...]]
+ AS_C2x,
+
+ /// __declspec(...)
+ AS_Declspec,
+
+ /// [uuid("...")] class Foo
+ AS_Microsoft,
+
+ /// __ptr16, alignas(...), etc.
+ AS_Keyword,
+
+ /// #pragma ...
+ AS_Pragma,
+
+ // Note TableGen depends on the order above. Do not add or change the order
+ // without adding related code to TableGen/ClangAttrEmitter.cpp.
+ /// Context-sensitive version of a keyword attribute.
+ AS_ContextSensitiveKeyword,
+ };
+
+private:
+ IdentifierInfo *AttrName;
+ IdentifierInfo *ScopeName;
+ SourceRange AttrRange;
+ SourceLocation ScopeLoc;
+ SourceLocation EllipsisLoc;
+
+ unsigned AttrKind : 16;
+
+ /// The number of expression arguments this attribute has.
+ /// The expressions themselves are stored after the object.
+ unsigned NumArgs : 16;
+
+ /// Corresponds to the Syntax enum.
+ unsigned SyntaxUsed : 3;
+
+ /// 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;
+
+ 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)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
+ SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
+ IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
+ HasParsedType(false), HasProcessingCache(false),
+ IsPragmaClangAttribute(false) {
+ if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// 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)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(true),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false),
+ UnavailableLoc(unavailable), MessageExpr(messageExpr) {
+ ArgsUnion PVal(Parm);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
+ new (getAvailabilityData()) detail::AvailabilityData(
+ introduced, deprecated, obsoleted, strict, replacementExpr);
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for objc_bridge_related attributes.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ ArgsUnion *Args = getArgsBuffer();
+ Args[0] = Parm1;
+ Args[1] = Parm2;
+ Args[2] = Parm3;
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// 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)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ ArgsUnion PVal(ArgKind);
+ memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
+ detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
+ new (&ExtraData.MatchingCType) ParsedType(matchingCType);
+ ExtraData.LayoutCompatible = layoutCompatible;
+ ExtraData.MustBeNull = mustBeNull;
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for attributes with a single type argument.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ ParsedType typeArg, Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
+ HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ new (&getTypeBuffer()) ParsedType(typeArg);
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// Constructor for microsoft __declspec(property) attribute.
+ ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange,
+ IdentifierInfo *scopeName, SourceLocation scopeLoc,
+ IdentifierInfo *getterId, IdentifierInfo *setterId,
+ Syntax syntaxUsed)
+ : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
+ ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false),
+ UsedAsTypeAttr(false), IsAvailability(false),
+ IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
+ HasProcessingCache(false), IsPragmaClangAttribute(false) {
+ new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId);
+ AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
+ }
+
+ /// 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 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;
+
+ enum Kind {
+ #define PARSED_ATTR(NAME) AT_##NAME,
+ #include "clang/Sema/AttrParsedAttrList.inc"
+ #undef PARSED_ATTR
+ IgnoredAttribute,
+ UnknownAttribute
+ };
+
+ IdentifierInfo *getName() const { return AttrName; }
+ SourceLocation getLoc() const { return AttrRange.getBegin(); }
+ SourceRange getRange() const { return AttrRange; }
+
+ bool hasScope() const { return ScopeName; }
+ IdentifierInfo *getScopeName() const { return ScopeName; }
+ SourceLocation getScopeLoc() const { return ScopeLoc; }
+
+ bool isGNUScope() const {
+ return ScopeName &&
+ (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
+ }
+
+ bool hasParsedType() const { return HasParsedType; }
+
+ /// Is this the Microsoft __declspec(property) attribute?
+ bool isDeclspecPropertyAttribute() const {
+ return IsProperty;
+ }
+
+ bool isAlignasAttribute() const {
+ // FIXME: Use a better mechanism to determine this.
+ return getKind() == AT_Aligned && isKeywordAttribute();
+ }
+
+ bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
+ bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
+
+ bool isCXX11Attribute() const {
+ return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
+ }
+
+ bool isC2xAttribute() const {
+ return SyntaxUsed == AS_C2x;
+ }
+
+ bool isKeywordAttribute() const {
+ return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
+ }
+
+ bool isContextSensitiveKeywordAttribute() const {
+ return SyntaxUsed == AS_ContextSensitiveKeyword;
+ }
+
+ 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() { UsedAsTypeAttr = true; }
+
+ /// 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; }
+
+ Kind getKind() const { return Kind(AttrKind); }
+ static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope,
+ Syntax SyntaxUsed);
+
+ /// 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(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilityData()->Changes[detail::IntroducedSlot];
+ }
+
+ const AvailabilityChange &getAvailabilityDeprecated() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilityData()->Changes[detail::DeprecatedSlot];
+ }
+
+ const AvailabilityChange &getAvailabilityObsoleted() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilityData()->Changes[detail::ObsoletedSlot];
+ }
+
+ SourceLocation getStrictLoc() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilityData()->StrictLoc;
+ }
+
+ SourceLocation getUnavailableLoc() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return UnavailableLoc;
+ }
+
+ const Expr * getMessageExpr() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return MessageExpr;
+ }
+
+ const Expr *getReplacementExpr() const {
+ assert(getKind() == AT_Availability && "Not an availability attribute");
+ return getAvailabilityData()->Replacement;
+ }
+
+ const ParsedType &getMatchingCType() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().MatchingCType;
+ }
+
+ bool getLayoutCompatible() const {
+ assert(getKind() == AT_TypeTagForDatatype &&
+ "Not a type_tag_for_datatype attribute");
+ return getTypeTagForDatatypeDataSlot().LayoutCompatible;
+ }
+
+ bool getMustBeNull() const {
+ assert(getKind() == 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;
+ }
+
+ /// Get an index into the attribute spelling list
+ /// defined in Attr.td. This index is used by an attribute
+ /// to pretty print itself.
+ unsigned getAttributeSpellingListIndex() const;
+
+ bool isTargetSpecificAttr() const;
+ bool isTypeAttr() const;
+ bool isStmtAttr() const;
+
+ bool hasCustomParsing() const;
+ unsigned getMinArgs() const;
+ unsigned getMaxArgs() const;
+ bool hasVariadicArg() const;
+ bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
+ 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;
+
+ /// 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 addr space attribute returns its representation
+ /// in LangAS, otherwise returns default addr space.
+ LangAS asOpenCLLangAS() const {
+ switch (getKind()) {
+ case ParsedAttr::AT_OpenCLConstantAddressSpace:
+ return LangAS::opencl_constant;
+ case ParsedAttr::AT_OpenCLGlobalAddressSpace:
+ return LangAS::opencl_global;
+ 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;
+ }
+ }
+};
+
+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;
+ AttributeFactory &Factory;
+ llvm::TinyPtrVector<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::TinyPtrVector<ParsedAttr *>;
+ using SizeType = decltype(std::declval<VecTy>().size());
+
+public:
+ 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*() { 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->getKind() == 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 &attrs) {
+ addAll(attrs.begin(), attrs.end());
+ attrs.clearListOnly();
+ pool.takeAllFrom(attrs.pool);
+ }
+
+ void clear() {
+ clearListOnly();
+ pool.clear();
+ }
+
+ /// 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;
+};
+
+/// 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
+};
+
+/// 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 DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const ParsedAttr &At) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const ParsedAttr &At) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(At.getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return PD;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const ParsedAttr *At) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return DB;
+}
+
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+ const ParsedAttr *At) {
+ PD.AddTaggedVal(reinterpret_cast<intptr_t>(At->getName()),
+ DiagnosticsEngine::ak_identifierinfo);
+ return PD;
+}
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H
diff --git a/clang-r353983e/include/clang/Sema/ParsedTemplate.h b/clang-r353983e/include/clang/Sema/ParsedTemplate.h
new file mode 100644
index 00000000..2eed301e
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/ParsedTemplate.h
@@ -0,0 +1,244 @@
+//===--- 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), EllipsisLoc() { }
+
+ /// 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 declaration,
+ /// template arguments, whether those template arguments were types,
+ /// expressions, or template names, and the source locations for important
+ /// tokens. All of the information about template arguments is allocated
+ /// directly after this structure.
+ struct TemplateIdAnnotation final
+ : private llvm::TrailingObjects<TemplateIdAnnotation,
+ ParsedTemplateArgument> {
+ friend TrailingObjects;
+ /// The nested-name-specifier that precedes the template name.
+ CXXScopeSpec SS;
+
+ /// 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.
+ 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;
+
+ /// 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(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
+ SourceLocation TemplateNameLoc, IdentifierInfo *Name,
+ OverloadedOperatorKind OperatorKind,
+ ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
+ SourceLocation LAngleLoc, SourceLocation RAngleLoc,
+ ArrayRef<ParsedTemplateArgument> TemplateArgs,
+ SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
+ TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc(
+ totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
+ TemplateIdAnnotation(SS, TemplateKWLoc, TemplateNameLoc, Name,
+ OperatorKind, OpaqueTemplateName, TemplateKind,
+ LAngleLoc, RAngleLoc, TemplateArgs);
+ CleanupList.push_back(TemplateId);
+ return TemplateId;
+ }
+
+ void Destroy() {
+ std::for_each(
+ getTemplateArgs(), getTemplateArgs() + NumArgs,
+ [](ParsedTemplateArgument &A) { A.~ParsedTemplateArgument(); });
+ this->~TemplateIdAnnotation();
+ free(this);
+ }
+ private:
+ TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
+
+ TemplateIdAnnotation(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
+ SourceLocation TemplateNameLoc, IdentifierInfo *Name,
+ OverloadedOperatorKind OperatorKind,
+ ParsedTemplateTy OpaqueTemplateName,
+ TemplateNameKind TemplateKind,
+ SourceLocation LAngleLoc, SourceLocation RAngleLoc,
+ ArrayRef<ParsedTemplateArgument> TemplateArgs) noexcept
+ : SS(SS), TemplateKWLoc(TemplateKWLoc),
+ TemplateNameLoc(TemplateNameLoc), Name(Name), Operator(OperatorKind),
+ Template(OpaqueTemplateName), Kind(TemplateKind),
+ LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
+ NumArgs(TemplateArgs.size()) {
+
+ 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
diff --git a/clang-r353983e/include/clang/Sema/Scope.h b/clang-r353983e/include/clang/Sema/Scope.h
new file mode 100644
index 00000000..a1b451c8
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Scope.h
@@ -0,0 +1,500 @@
+//===- 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>
+
+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,
+ };
+
+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 lattice consisting of undefined, a single NRVO candidate variable in
+ /// this scope, or over-defined. The bit is true when over-defined.
+ llvm::PointerIntPair<VarDecl *, 1, bool> NRVO;
+
+ 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();
+ }
+
+ /// 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) {
+ 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(Decl *D) {
+ return DeclsInScope.count(D) != 0;
+ }
+
+ DeclContext *getEntity() const { return Entity; }
+ void setEntity(DeclContext *E) { Entity = E; }
+
+ bool hasErrorOccurred() const { return ErrorTrap.hasErrorOccurred(); }
+
+ 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);
+ }
+
+ /// 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;
+ }
+
+ /// isAtCatchScope - Return true if this scope is \@catch.
+ bool isAtCatchScope() const {
+ return getFlags() & Scope::AtCatchScope;
+ }
+
+ /// 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 a C++ 'try' block.
+ bool isTryScope() const { return getFlags() & Scope::TryScope; }
+
+ /// 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;
+ }
+
+ /// 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 addNRVOCandidate(VarDecl *VD) {
+ if (NRVO.getInt())
+ return;
+ if (NRVO.getPointer() == nullptr) {
+ NRVO.setPointer(VD);
+ return;
+ }
+ if (NRVO.getPointer() != VD)
+ setNoNRVO();
+ }
+
+ void setNoNRVO() {
+ NRVO.setInt(true);
+ NRVO.setPointer(nullptr);
+ }
+
+ void mergeNRVOIntoParent();
+
+ /// 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
diff --git a/clang-r353983e/include/clang/Sema/ScopeInfo.h b/clang-r353983e/include/clang/Sema/ScopeInfo.h
new file mode 100644
index 00000000..e2346fd5
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/ScopeInfo.h
@@ -0,0 +1,1019 @@
+//===- 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/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 "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 TemplateTypeParmDecl;
+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;
+
+ CompoundScopeInfo(bool IsStmtExpr) : IsStmtExpr(IsStmtExpr) {}
+
+ void setHasEmptyLoopBodies() {
+ HasEmptyLoopBodies = true;
+ }
+};
+
+class PossiblyUnreachableDiag {
+public:
+ PartialDiagnostic PD;
+ SourceLocation Loc;
+ const Stmt *stmt;
+
+ PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
+ const Stmt *stmt)
+ : PD(PD), Loc(Loc), stmt(stmt) {}
+};
+
+/// 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 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 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' statement in the current function.
+ SourceLocation FirstCXXTryLoc;
+
+ /// First SEH '__try' statement in the current function.
+ SourceLocation FirstSEHTryLoc;
+
+ /// Used to determine if errors occurred in this function or block.
+ DiagnosticErrorTrap ErrorTrap;
+
+ /// 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;
+
+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),
+ HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false),
+ HasFallthroughStmt(false), HasPotentialAvailabilityViolations(false),
+ ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false),
+ ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false),
+ ObjCWarnForNoInitDelegation(false), NeedsCoroutineSuspends(true),
+ ErrorTrap(Diag) {}
+
+ virtual ~FunctionScopeInfo();
+
+ /// 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 setHasDroppedStmt() {
+ HasDroppedStmt = true;
+ }
+
+ void setHasOMPDeclareReductionCombiner() {
+ HasOMPDeclareReductionCombiner = true;
+ }
+
+ void setHasFallthroughStmt() {
+ HasFallthroughStmt = true;
+ }
+
+ void setHasCXXTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstCXXTryLoc = TryLoc;
+ }
+
+ void setHasSEHTry(SourceLocation TryLoc) {
+ setHasBranchProtectedScope();
+ FirstSEHTryLoc = TryLoc;
+ }
+
+ bool NeedsScopeChecking() const {
+ return !HasDroppedStmt &&
+ (HasIndirectGoto ||
+ (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();
+};
+
+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
+ };
+ enum {
+ IsNestedCapture = 0x1,
+ IsThisCaptured = 0x2
+ };
+
+ /// The variable being captured (if we are not capturing 'this') and whether
+ /// this is a nested capture, and whether we are capturing 'this'
+ llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis;
+
+ /// Expression to initialize a field of the given type, and the kind of
+ /// capture (if this is a capture and not an init-capture). The expression
+ /// is only required if we are capturing ByVal and the variable's type has
+ /// a non-trivial copy constructor.
+ llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind;
+
+ /// 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 in effect the type of the
+ /// non-static data member that would hold the capture.
+ QualType CaptureType;
+
+ /// Whether an explicit capture has been odr-used in the body of the
+ /// lambda.
+ bool ODRUsed = false;
+
+ /// Whether an explicit capture has been non-odr-used in the body of
+ /// the lambda.
+ bool NonODRUsed = false;
+
+public:
+ Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
+ QualType CaptureType, Expr *Cpy)
+ : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0),
+ InitExprAndCaptureKind(
+ Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef
+ : Cap_ByCopy),
+ Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
+
+ enum IsThisCapture { ThisCapture };
+ Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
+ QualType CaptureType, Expr *Cpy, const bool ByCopy)
+ : VarAndNestedAndThis(
+ nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))),
+ InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef),
+ Loc(Loc), CaptureType(CaptureType) {}
+
+ bool isThisCapture() const {
+ return VarAndNestedAndThis.getInt() & IsThisCaptured;
+ }
+
+ bool isVariableCapture() const {
+ return !isThisCapture() && !isVLATypeCapture();
+ }
+
+ bool isCopyCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
+ }
+
+ bool isReferenceCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_ByRef;
+ }
+
+ bool isBlockCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_Block;
+ }
+
+ bool isVLATypeCapture() const {
+ return InitExprAndCaptureKind.getInt() == Cap_VLA;
+ }
+
+ bool isNested() const {
+ return VarAndNestedAndThis.getInt() & IsNestedCapture;
+ }
+
+ bool isODRUsed() const { return ODRUsed; }
+ bool isNonODRUsed() const { return NonODRUsed; }
+ void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; }
+
+ VarDecl *getVariable() const {
+ assert(isVariableCapture());
+ return VarAndNestedAndThis.getPointer();
+ }
+
+ /// 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 {
+ assert(!isThisCapture());
+ return CaptureType;
+ }
+
+ Expr *getInitExpr() const {
+ assert(!isVLATypeCapture() && "no init expression for type capture");
+ return static_cast<Expr *>(InitExprAndCaptureKind.getPointer());
+ }
+};
+
+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<VarDecl*, 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(VarDecl *Var, bool isBlock, bool isByref, bool isNested,
+ SourceLocation Loc, SourceLocation EllipsisLoc,
+ QualType CaptureType, Expr *Cpy) {
+ Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
+ EllipsisLoc, CaptureType, Cpy));
+ CaptureMap[Var] = Captures.size();
+ }
+
+ void addVLATypeCapture(SourceLocation Loc, QualType CaptureType) {
+ Captures.push_back(Capture(/*Var*/ nullptr, /*isBlock*/ false,
+ /*isByref*/ false, /*isNested*/ false, Loc,
+ /*EllipsisLoc*/ SourceLocation(), CaptureType,
+ /*Cpy*/ nullptr));
+ }
+
+ // Note, we do not need to add the type of 'this' since that is always
+ // retrievable from Sema::getCurrentThisType - and is also encoded within the
+ // type of the corresponding FieldDecl.
+ void addThisCapture(bool isNested, SourceLocation Loc,
+ Expr *Cpy, 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(VarDecl *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(VarDecl *Var) {
+ assert(isCaptured(Var) && "Variable has not been captured");
+ return Captures[CaptureMap[Var] - 1];
+ }
+
+ const Capture &getCapture(VarDecl *Var) const {
+ llvm::DenseMap<VarDecl*, 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;
+
+ CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
+ RecordDecl *RD, ImplicitParamDecl *Context,
+ CapturedRegionKind K, unsigned OpenMPLevel)
+ : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
+ TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
+ ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel) {
+ 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:
+ /// 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;
+
+ /// If this is a generic lambda, use this as the depth of
+ /// each 'auto' parameter, during initial AST construction.
+ unsigned AutoTemplateParameterDepth = 0;
+
+ /// Store the list of the auto parameters for a generic lambda.
+ /// If this is a generic lambda, store the list of the auto
+ /// parameters converted into TemplateTypeParmDecls into a vector
+ /// that can be used to construct the generic lambda's template
+ /// parameter list, during initial AST construction.
+ SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;
+
+ /// If this is a generic lambda, and the template parameter
+ /// list has been created (from the AutoTemplateParams) 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 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 the first 'auto'-typed parameter.
+ bool isGenericLambda() const {
+ return !AutoTemplateParams.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));
+ 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));
+ NonODRUsedCapturingExprs.insert(CapturingVarExpr);
+ }
+ bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
+ assert(isa<DeclRefExpr>(CapturingVarExpr)
+ || isa<MemberExpr>(CapturingVarExpr));
+ return NonODRUsedCapturingExprs.count(CapturingVarExpr);
+ }
+ void removePotentialCapture(Expr *E) {
+ PotentiallyCapturingExprs.erase(
+ std::remove(PotentiallyCapturingExprs.begin(),
+ PotentiallyCapturingExprs.end(), E),
+ PotentiallyCapturingExprs.end());
+ }
+ void clearPotentialCaptures() {
+ PotentiallyCapturingExprs.clear();
+ PotentialThisCaptureLocation = SourceLocation();
+ }
+ unsigned getNumPotentialVariableCaptures() const {
+ return PotentiallyCapturingExprs.size();
+ }
+
+ bool hasPotentialCaptures() const {
+ return getNumPotentialVariableCaptures() ||
+ PotentialThisCaptureLocation.isValid();
+ }
+
+ // When passed the index, returns the VarDecl and Expr associated
+ // with the index.
+ void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) 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,
+ Expr *Cpy,
+ const bool ByCopy) {
+ Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, QualType(),
+ Cpy, ByCopy));
+ CXXThisCaptureIndex = Captures.size();
+}
+
+} // namespace sema
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_SCOPEINFO_H
diff --git a/clang-r353983e/include/clang/Sema/Sema.h b/clang-r353983e/include/clang/Sema/Sema.h
new file mode 100644
index 00000000..0c2479a0
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Sema.h
@@ -0,0 +1,11063 @@
+//===--- 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/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/ExprObjC.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/TypeLoc.h"
+#include "clang/AST/TypeOrdering.h"
+#include "clang/Basic/ExpressionTraits.h"
+#include "clang/Basic/Module.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/TypoCorrection.h"
+#include "clang/Sema/Weak.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include <deque>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class APSInt;
+ template <typename ValueT> struct DenseMapInfo;
+ 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 OverloadCandidate;
+ 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 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;
+ }
+};
+
+/// Keeps track of expected type during expression parsing. 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 allows
+/// to avoid updating the type on hot paths in the parser.
+class PreferredTypeBuilder {
+public:
+ PreferredTypeBuilder() = default;
+ explicit PreferredTypeBuilder(QualType Type) : Type(Type) {}
+
+ void enterCondition(Sema &S, SourceLocation Tok);
+ void enterReturn(Sema &S, SourceLocation Tok);
+ void enterVariableInit(SourceLocation Tok, Decl *D);
+
+ 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);
+
+ QualType get(SourceLocation Tok) const {
+ if (Tok == ExpectedLoc)
+ return Type;
+ return QualType();
+ }
+
+private:
+ /// Start position of a token for which we store expected type.
+ SourceLocation ExpectedLoc;
+ /// Expected type for a token starting at ExpectedLoc.
+ QualType Type;
+};
+
+/// Sema - This implements semantic analysis and AST building for C.
+class Sema {
+ Sema(const Sema &) = delete;
+ void operator=(const Sema &) = delete;
+
+ ///Source of additional semantic information.
+ ExternalSemaSource *ExternalSource;
+
+ ///Whether Sema has generated a multiplexer and has to delete it.
+ bool isMultiplexExternalSource;
+
+ static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
+
+ bool isVisibleSlow(const NamedDecl *D);
+
+ /// 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:
+ typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
+ typedef OpaquePtr<TemplateName> TemplateTy;
+ typedef OpaquePtr<QualType> TypeTy;
+
+ OpenCLOptions OpenCLFeatures;
+ FPOptions FPFeatures;
+
+ 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;
+
+ /// pragma clang section kind
+ enum PragmaClangSectionKind {
+ PCSK_Invalid = 0,
+ PCSK_BSS = 1,
+ PCSK_Data = 2,
+ PCSK_Rodata = 3,
+ PCSK_Text = 4
+ };
+
+ enum PragmaClangSectionAction {
+ PCSA_Set = 0,
+ PCSA_Clear = 1
+ };
+
+ struct PragmaClangSection {
+ std::string SectionName;
+ bool Valid = false;
+ SourceLocation PragmaLocation;
+
+ void Act(SourceLocation PragmaLocation,
+ PragmaClangSectionAction Action,
+ StringLiteral* Name);
+ };
+
+ PragmaClangSection PragmaClangBSSSection;
+ PragmaClangSection PragmaClangDataSection;
+ PragmaClangSection PragmaClangRodataSection;
+ 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)
+ };
+
+ 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);
+
+ // 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<MSVtorDispAttr::Mode> VtorDispStack;
+ // #pragma pack.
+ // Sentinel to represent when the stack is set to mac68k alignment.
+ static const unsigned kMac68kAlignmentSentinel = ~0U;
+ PragmaStack<unsigned> PackStack;
+ // The current #pragma pack values and locations at each #include.
+ struct PackIncludeState {
+ unsigned CurrentValue;
+ SourceLocation CurrentPragmaLocation;
+ bool HasNonDefaultValue, ShouldWarnOnInclude;
+ };
+ SmallVector<PackIncludeState, 8> PackIncludeStack;
+ // Segment #pragmas.
+ PragmaStack<StringLiteral *> DataSegStack;
+ PragmaStack<StringLiteral *> BSSSegStack;
+ PragmaStack<StringLiteral *> ConstSegStack;
+ PragmaStack<StringLiteral *> CodeSegStack;
+
+ // 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;
+
+ /// 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;
+
+ /// 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. The
+ /// element type here is ExprWithCleanups::Object.
+ SmallVector<BlockDecl*, 8> ExprCleanupObjects;
+
+ /// Store a list 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.
+ llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
+
+ std::unique_ptr<sema::FunctionScopeInfo> PreallocatedFunctionScope;
+
+ /// Stack containing information about each of the nested
+ /// function, block, and method scopes that are currently active.
+ SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+
+ 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;
+
+ 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;
+
+ /// All the members seen during a class definition which were both
+ /// explicitly defaulted and had explicitly-specified exception
+ /// specifications, along with the function type containing their
+ /// user-specified exception specification. Those exception specifications
+ /// were overridden with the default specifications, but we still need to
+ /// check whether they are compatible with the default specification, and
+ /// we can't do that until the nesting set of class definitions is complete.
+ SmallVector<std::pair<CXXMethodDecl*, const FunctionProtoType*>, 2>
+ DelayedDefaultedMemberExceptionSpecs;
+
+ 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;
+
+ public:
+ ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true)
+ : S(S), SavedContext(S.CurContext),
+ SavedContextState(S.DelayedDiagnostics.pushUndelayed()),
+ SavedCXXThisTypeOverride(S.CXXThisTypeOverride)
+ {
+ assert(ContextToPush && "pushing null context");
+ S.CurContext = ContextToPush;
+ if (NewThisContext)
+ S.CXXThisTypeOverride = QualType();
+ }
+
+ void pop() {
+ if (!SavedContext) return;
+ S.CurContext = SavedContext;
+ S.DelayedDiagnostics.popUndelayed(SavedContextState);
+ S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
+ SavedContext = nullptr;
+ }
+
+ ~ContextRAII() {
+ pop();
+ }
+ };
+
+ /// 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
+ llvm::MapVector<IdentifierInfo *, WeakInfo> 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 C++ "type_info" declaration, which is defined in \<typeinfo>.
+ RecordDecl *CXXTypeInfoDecl;
+
+ /// The MSVC "_GUID" struct, which is defined in MSVC header files.
+ RecordDecl *MSVCGuidDecl;
+
+ /// 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;
+
+ /// A flag to indicate that we're in a context that permits abstract
+ /// references to fields. This is really a
+ bool AllowAbstractFieldReference;
+
+ /// 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,
+
+ /// 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
+ };
+
+ /// 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;
+
+ /// Whether we are in a decltype expression.
+ bool IsDecltype;
+
+ /// 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;
+
+ llvm::SmallPtrSet<Expr*, 2> 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;
+
+ /// The context information used to mangle lambda expressions
+ /// and block literals within this context.
+ ///
+ /// This mangling information is allocated lazily, since most contexts
+ /// do not have lambda expressions or block literals.
+ std::unique_ptr<MangleNumberingContext> MangleNumbering;
+
+ /// 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;
+
+ /// \brief Describes whether we are in an expression constext which we have
+ /// to handle differently.
+ enum ExpressionKind {
+ EK_Decltype, EK_TemplateArgument, EK_Other
+ } ExprContext;
+
+ ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
+ unsigned NumCleanupObjects,
+ CleanupInfo ParentCleanup,
+ Decl *ManglingContextDecl,
+ ExpressionKind ExprContext)
+ : Context(Context), ParentCleanup(ParentCleanup),
+ NumCleanupObjects(NumCleanupObjects), NumTypos(0),
+ ManglingContextDecl(ManglingContextDecl), MangleNumbering(),
+ ExprContext(ExprContext) {}
+
+ /// Retrieve the mangling numbering context, used to consistently
+ /// number constructs like lambdas for mangling.
+ MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx);
+
+ bool isUnevaluated() const {
+ return Context == ExpressionEvaluationContext::Unevaluated ||
+ Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
+ Context == ExpressionEvaluationContext::UnevaluatedList;
+ }
+ bool isConstantEvaluated() const {
+ return Context == ExpressionEvaluationContext::ConstantEvaluated;
+ }
+ };
+
+ /// 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.
+ ///
+ /// \param DC - The DeclContext containing the lambda expression or
+ /// block literal.
+ /// \param[out] ManglingContextDecl - Returns the ManglingContextDecl
+ /// associated with the context, if relevant.
+ MangleNumberingContext *getCurrentMangleNumberContext(
+ const DeclContext *DC,
+ Decl *&ManglingContextDecl);
+
+
+ /// 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() : Pair() {}
+ 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.
+ 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;
+
+ typedef std::pair<ObjCMethodList, ObjCMethodList> GlobalMethods;
+ typedef llvm::DenseMap<Selector, GlobalMethods> GlobalMethodPool;
+
+ /// 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;
+
+ /// 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;
+
+ /// 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 FP_CONTRACT state on entry/exit of compound
+ /// statements.
+ class FPContractStateRAII {
+ public:
+ FPContractStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.FPFeatures) {}
+ ~FPContractStateRAII() { S.FPFeatures = OldFPFeaturesState; }
+
+ private:
+ Sema& S;
+ FPOptions OldFPFeaturesState;
+ };
+
+ void addImplicitTypedef(StringRef Name, QualType T);
+
+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();
+
+ const LangOptions &getLangOpts() const { return LangOpts; }
+ OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
+ FPOptions &getFPOptions() { return FPFeatures; }
+
+ 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; }
+
+ ///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;
+
+ /// Helper class that creates diagnostics with optional
+ /// template instantiation stacks.
+ ///
+ /// This class provides a wrapper around the basic DiagnosticBuilder
+ /// class that emits diagnostics. SemaDiagnosticBuilder 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 SemaDiagnosticBuilder : public DiagnosticBuilder {
+ Sema &SemaRef;
+ unsigned DiagID;
+
+ public:
+ SemaDiagnosticBuilder(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 ~SemaDiagnosticBuilder is a safe no-op
+ // in that case anwyay.
+ SemaDiagnosticBuilder(const SemaDiagnosticBuilder&) = default;
+
+ ~SemaDiagnosticBuilder() {
+ // If we aren't active, there is nothing to do.
+ if (!isActive()) return;
+
+ // Otherwise, we need to emit the diagnostic. First flush the underlying
+ // DiagnosticBuilder data, and 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.
+ FlushCounts();
+ 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 SemaDiagnosticBuilder &operator<<(
+ const SemaDiagnosticBuilder &Diag, const T &Value) {
+ const DiagnosticBuilder &BaseDiag = Diag;
+ BaseDiag << Value;
+ return Diag;
+ }
+ };
+
+ /// Emit a diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+ DiagnosticBuilder DB = Diags.Report(Loc, DiagID);
+ return SemaDiagnosticBuilder(DB, *this, DiagID);
+ }
+
+ /// Emit a partial diagnostic.
+ SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD);
+
+ /// Build a partial diagnostic.
+ PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+
+ 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;
+
+ void emitAndClearUnusedLocalTypedefWarnings();
+
+ void ActOnStartOfTranslationUnit();
+ void ActOnEndOfTranslationUnit();
+
+ 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);
+ void
+ PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
+ const Decl *D = nullptr,
+ const BlockExpr *blkExpr = nullptr);
+
+ sema::FunctionScopeInfo *getCurFunction() const {
+ return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
+ }
+
+ sema::FunctionScopeInfo *getEnclosingFunction() const;
+
+ void setFunctionHasBranchIntoScope();
+ void setFunctionHasBranchProtectedScope();
+ void setFunctionHasIndirectGoto();
+
+ void PushCompoundScope(bool IsStmtExpr);
+ void PopCompoundScope();
+
+ sema::CompoundScopeInfo &getCurCompoundScope() const;
+ bool isCurCompoundStmtAStmtExpr() const;
+
+ bool hasAnyUnrecoverableErrorsInThisFunction() const;
+
+ /// Retrieve the current block, if any.
+ sema::BlockScopeInfo *getCurBlock();
+
+ /// 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();
+
+ /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
+ SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+
+ 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 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 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);
+
+ 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 Expr *E);
+ 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 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 {
+ unsigned DiagID;
+ std::tuple<const Ts &...> Args;
+
+ template <std::size_t... Is>
+ void emit(const SemaDiagnosticBuilder &DB,
+ llvm::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, llvm::index_sequence_for<Ts...>());
+ DB << T;
+ }
+ };
+
+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,
+ TypeDiagnoser *Diagnoser);
+
+ struct ModuleScope {
+ clang::Module *Module = nullptr;
+ bool ModuleInterface = false;
+ VisibleModuleSet OuterVisibleModules;
+ };
+ /// The modules we're currently parsing.
+ llvm::SmallVector<ModuleScope, 16> ModuleScopes;
+
+ /// Get the module whose scope we are currently within.
+ Module *getCurrentModule() const {
+ return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
+ }
+
+ VisibleModuleSet VisibleModules;
+
+public:
+ /// Get the module owning an entity.
+ Module *getOwningModule(Decl *Entity) { return Entity->getOwningModule(); }
+
+ /// 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);
+
+ /// Determine whether a declaration is visible to name lookup.
+ bool isVisible(const NamedDecl *D) {
+ return !D->isHidden() || isVisibleSlow(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);
+
+ 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 the template parameter \p D has a visible default argument.
+ bool
+ hasVisibleDefaultArgument(const NamedDecl *D,
+ llvm::SmallVectorImpl<Module *> *Modules = nullptr);
+
+ /// 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 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 \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);
+
+ bool isCompleteType(SourceLocation Loc, QualType T) {
+ return !RequireCompleteTypeImpl(Loc, T, nullptr);
+ }
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ TypeDiagnoser &Diagnoser);
+ bool RequireCompleteType(SourceLocation Loc, QualType T,
+ unsigned 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);
+ }
+
+ void completeExprArrayBound(Expr *E);
+ bool RequireCompleteExprType(Expr *E, 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, 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);
+
+ QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
+ /// 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, SourceLocation Loc,
+ bool AsUnevaluated = true);
+ QualType BuildUnaryTransformType(QualType BaseType,
+ UnaryTransformType::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,
+ 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 {
+ NC_Unknown,
+ NC_Error,
+ NC_Keyword,
+ NC_Type,
+ NC_Expression,
+ NC_NestedNameSpecifier,
+ NC_TypeTemplate,
+ NC_VarTemplate,
+ NC_FunctionTemplate
+ };
+
+ class NameClassification {
+ NameClassificationKind Kind;
+ ExprResult Expr;
+ TemplateName Template;
+ ParsedType Type;
+
+ explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {}
+
+ public:
+ NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {}
+
+ 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 NestedNameSpecifier() {
+ return NameClassification(NC_NestedNameSpecifier);
+ }
+
+ 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;
+ }
+
+ NameClassificationKind getKind() const { return Kind; }
+
+ ParsedType getType() const {
+ assert(Kind == NC_Type);
+ return Type;
+ }
+
+ ExprResult getExpression() const {
+ assert(Kind == NC_Expression);
+ return Expr;
+ }
+
+ TemplateName getTemplateName() const {
+ assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate ||
+ Kind == NC_VarTemplate);
+ 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;
+ 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 IsAddressOfOperand True if this name is the operand of a unary
+ /// address of ('&') expression, assuming it is classified as an
+ /// expression.
+ ///
+ /// \param CCC The correction callback, if typo correction is desired.
+ NameClassification
+ ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
+ SourceLocation NameLoc, const Token &NextToken,
+ bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr);
+
+ /// Describes the detailed kind of a template name. Used in diagnostics.
+ enum class TemplateNameKindForDiagnostics {
+ ClassTemplate,
+ FunctionTemplate,
+ VarTemplate,
+ AliasTemplate,
+ TemplateTemplateParam,
+ 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);
+
+ Decl *ActOnDeclarator(Scope *S, Declarator &D);
+
+ NamedDecl *HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists);
+ 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);
+ 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 = None);
+ 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);
+
+ bool CheckConstexprFunctionDecl(const FunctionDecl *FD);
+ bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body);
+
+ 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 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);
+ Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition);
+ 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);
+ bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
+ SourceLocation EqualLoc);
+
+ 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,
+ SourceLocation AttrEnd);
+ void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+ void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
+ void CheckStaticLocalForDllExport(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);
+
+ 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);
+ Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
+ SkipBodyInfo *SkipBody = nullptr);
+ 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);
+
+ 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);
+
+ /// 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;'
+ Partition, ///< 'module partition X;'
+ };
+
+ /// 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);
+
+ /// The parser has processed a module import declaration.
+ ///
+ /// \param AtLoc The location of the '@' symbol, if any.
+ ///
+ /// \param ImportLoc The location of the 'import' keyword.
+ ///
+ /// \param Path The module access path.
+ DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc,
+ 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, and diagnose if not.
+ void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
+
+ /// We've found a use of a template specialization that would select a
+ /// partial specialization. Check that the partial specialization is visible,
+ /// and diagnose if not.
+ void checkPartialSpecializationVisibility(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,
+ RecordDecl *&AnonRecord);
+ Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
+ 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;'
+ };
+
+ Decl *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,
+ SkipBodyInfo *SkipBody = nullptr);
+
+ Decl *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);
+ CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD);
+ 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(DeclSpec &DS, Decl *Prev,
+ SkipBodyInfo &SkipBody);
+
+ typedef void *SkippedDefinitionContext;
+
+ /// Invoked when we enter a tag definition that we're skipping.
+ SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD);
+
+ Decl *ActOnObjCContainerStartDefinition(Decl *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,
+ 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(DeclContext *DC);
+ void ActOnObjCReenterContainerContext(DeclContext *DC);
+
+ /// 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);
+
+ DeclContext *getContainingDC(DeclContext *DC);
+
+ /// 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);
+
+ /// Push the parameters of D, which must be a function, into scope.
+ void ActOnReenterFunctionContext(Scope* S, Decl* D);
+ void ActOnExitFunctionContext();
+
+ DeclContext *getFunctionLevelDeclContext();
+
+ /// getCurFunctionDecl - If inside of a function body, this returns a pointer
+ /// to the function decl for the function being parsed. If we're currently
+ /// in a 'block', this returns the containing context.
+ FunctionDecl *getCurFunctionDecl();
+
+ /// 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);
+
+ /// Make the given externally-produced declaration visible at the
+ /// top level scope.
+ ///
+ /// \param D The externally-produced declaration to push.
+ ///
+ /// \param Name The name of the externally-produced declaration.
+ void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name);
+
+ /// 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,
+ };
+
+ /// 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, SourceRange Range, IdentifierInfo *Platform, bool Implicit,
+ VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted,
+ bool IsUnavailable, StringRef Message, bool IsStrict,
+ StringRef Replacement, AvailabilityMergeKind AMK, int Priority,
+ unsigned AttrSpellingListIndex);
+ TypeVisibilityAttr *mergeTypeVisibilityAttr(Decl *D, SourceRange Range,
+ TypeVisibilityAttr::VisibilityType Vis,
+ unsigned AttrSpellingListIndex);
+ VisibilityAttr *mergeVisibilityAttr(Decl *D, SourceRange Range,
+ VisibilityAttr::VisibilityType Vis,
+ unsigned AttrSpellingListIndex);
+ UuidAttr *mergeUuidAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex, StringRef Uuid);
+ DLLImportAttr *mergeDLLImportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ DLLExportAttr *mergeDLLExportAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ MSInheritanceAttr *
+ mergeMSInheritanceAttr(Decl *D, SourceRange Range, bool BestCase,
+ unsigned AttrSpellingListIndex,
+ MSInheritanceAttr::Spelling SemanticSpelling);
+ FormatAttr *mergeFormatAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Format, int FormatIdx,
+ int FirstArg, unsigned AttrSpellingListIndex);
+ SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name,
+ unsigned AttrSpellingListIndex);
+ CodeSegAttr *mergeCodeSegAttr(Decl *D, SourceRange Range, StringRef Name,
+ unsigned AttrSpellingListIndex);
+ AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range,
+ IdentifierInfo *Ident,
+ unsigned AttrSpellingListIndex);
+ MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ NoSpeculativeLoadHardeningAttr *
+ mergeNoSpeculativeLoadHardeningAttr(Decl *D,
+ const NoSpeculativeLoadHardeningAttr &AL);
+ SpeculativeLoadHardeningAttr *
+ mergeSpeculativeLoadHardeningAttr(Decl *D,
+ const SpeculativeLoadHardeningAttr &AL);
+ OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range,
+ unsigned AttrSpellingListIndex);
+ InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
+ InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D,
+ const InternalLinkageAttr &AL);
+ CommonAttr *mergeCommonAttr(Decl *D, const ParsedAttr &AL);
+ CommonAttr *mergeCommonAttr(Decl *D, const CommonAttr &AL);
+
+ 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 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 IsForUsingDecl);
+ bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl,
+ bool ConsiderCudaAttrs = true);
+
+ /// Checks availability of the function depending on the current
+ /// function context.Inside an unavailable function,unavailability is ignored.
+ ///
+ /// \returns true if \p FD is unavailable and current context is inside
+ /// an available function, false otherwise.
+ bool isFunctionConsideredUnavailable(FunctionDecl *FD);
+
+ ImplicitConversionSequence
+ TryImplicitConversion(Expr *From, QualType ToType,
+ bool SuppressUserConversions,
+ bool 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);
+ 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(CanQualType Param, CanQualType Arg);
+
+ ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+ const VarDecl *NRVOCandidate,
+ QualType ResultType,
+ Expr *Value,
+ bool AllowNRVO = true);
+
+ 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_NewExpr, ///< Constant expression in a noptr-new-declarator.
+ CCEK_ConstexprIf ///< Condition in a constexpr if statement.
+ };
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ llvm::APSInt &Value, CCEKind CCE);
+ ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+ APValue &Value, CCEKind CCE);
+
+ /// 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 = false,
+ ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
+ ConversionSequenceList EarlyConversions = None);
+ 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);
+ 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 = None);
+ 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);
+ void AddTemplateOverloadCandidate(
+ FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+ TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
+ OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+ bool PartialOverloading = false,
+ ADLCallKind IsADLCandidate = ADLCallKind::NotADL);
+ 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 = {});
+ void AddConversionCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet& CandidateSet,
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion = true);
+ void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ Expr *From, QualType ToType,
+ OverloadCandidateSet &CandidateSet,
+ bool AllowObjCConversionOnExplicit,
+ bool AllowResultConversion = true);
+ void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+ DeclAccessPair FoundDecl,
+ CXXRecordDecl *ActingContext,
+ const FunctionProtoType *Proto,
+ Expr *Object, ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet);
+ void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+ SourceLocation OpLoc, ArrayRef<Expr *> Args,
+ OverloadCandidateSet& CandidateSet,
+ SourceRange OpRange = SourceRange());
+ 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,
+ 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, 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 *
+ resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
+ DeclAccessPair &FoundResult);
+
+ bool resolveAndFixAddressOfOnlyViableOverloadCandidate(
+ ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
+
+ FunctionDecl *
+ ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
+ bool Complain = false,
+ DeclAccessPair *Found = nullptr);
+
+ bool ResolveAndFixSingleFunctionTemplateSpecialization(
+ ExprResult &SrcExpr,
+ bool DoFunctionPointerConverion = 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);
+
+ // 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 CreateOverloadedUnaryOp(SourceLocation OpLoc,
+ UnaryOperatorKind Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *input, bool RequiresADL = true);
+
+ ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
+ BinaryOperatorKind Opc,
+ const UnresolvedSetImpl &Fns,
+ Expr *LHS, Expr *RHS,
+ bool RequiresADL = true);
+
+ ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+ SourceLocation RLoc,
+ Expr *Base,Expr *Idx);
+
+ ExprResult
+ BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc);
+ 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 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_StringTemplate
+ };
+
+ 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);
+
+ // 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,
+ std::unique_ptr<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 LookupName(LookupResult &R, Scope *S,
+ bool AllowBuiltinCreation = 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,
+ QualType T1, QualType T2,
+ 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);
+ LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R,
+ ArrayRef<QualType> ArgTys,
+ bool AllowRaw,
+ bool AllowTemplate,
+ bool AllowStringTemplate,
+ bool DiagnoseMissing);
+ bool isKnownName(StringRef name);
+
+ 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,
+ std::unique_ptr<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,
+ std::unique_ptr<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 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,
+ llvm::function_ref<ExprResult(Expr *)> Filter =
+ [](Expr *E) -> ExprResult { return E; });
+
+ ExprResult
+ CorrectDelayedTyposInExpr(Expr *E,
+ llvm::function_ref<ExprResult(Expr *)> Filter) {
+ return CorrectDelayedTyposInExpr(E, nullptr, Filter);
+ }
+
+ ExprResult
+ CorrectDelayedTyposInExpr(ExprResult ER, VarDecl *InitDecl = nullptr,
+ llvm::function_ref<ExprResult(Expr *)> Filter =
+ [](Expr *E) -> ExprResult { return E; }) {
+ return ER.isInvalid() ? ER : CorrectDelayedTyposInExpr(ER.get(), Filter);
+ }
+
+ ExprResult
+ CorrectDelayedTyposInExpr(ExprResult ER,
+ llvm::function_ref<ExprResult(Expr *)> Filter) {
+ return CorrectDelayedTyposInExpr(ER, nullptr, 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);
+
+ void DiagnoseAmbiguousLookup(LookupResult &Result);
+ //@}
+
+ ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
+ SourceLocation IdLoc,
+ bool TypoCorrection = false);
+ NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
+ Scope *S, bool ForRedeclaration,
+ SourceLocation Loc);
+ NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+ Scope *S);
+ 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);
+ void ProcessDeclAttributeList(Scope *S, Decl *D, const ParsedAttributesView &AL,
+ bool IncludeCXX11Attributes = true);
+ bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
+ const ParsedAttributesView &AttrList);
+
+ void checkUnusedDeclAttributes(Declarator &D);
+
+ /// 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 ParsedAttr &Attr, unsigned ArgNum,
+ StringRef &Str,
+ SourceLocation *ArgLocation = nullptr);
+ bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
+ bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
+ bool checkMSInheritanceAttrOnDefinition(
+ CXXRecordDecl *RD, SourceRange Range, bool BestCase,
+ MSInheritanceAttr::Spelling 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;
+
+ /// Stmt attributes - this routine is the top level dispatcher.
+ StmtResult ProcessStmtAttributes(Stmt *Stmt,
+ const ParsedAttributesView &Attrs,
+ SourceRange Range);
+
+ 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);
+
+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 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 ActOnAttributedStmt(SourceLocation AttrLoc,
+ ArrayRef<const Attr*> Attrs,
+ Stmt *SubStmt);
+
+ class ConditionResult;
+ StmtResult ActOnIfStmt(SourceLocation IfLoc, bool IsConstexpr,
+ Stmt *InitStmt,
+ ConditionResult Cond, Stmt *ThenVal,
+ SourceLocation ElseLoc, Stmt *ElseVal);
+ StmtResult BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr,
+ Stmt *InitStmt,
+ ConditionResult Cond, Stmt *ThenVal,
+ SourceLocation ElseLoc, Stmt *ElseVal);
+ StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
+ Stmt *InitStmt,
+ ConditionResult Cond);
+ StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
+ Stmt *Switch, Stmt *Body);
+ StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
+ 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);
+ StmtResult ActOnCapturedRegionEnd(Stmt *S);
+ void ActOnCapturedRegionError();
+ RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
+ SourceLocation Loc,
+ unsigned NumParams);
+
+ enum CopyElisionSemanticsKind {
+ CES_Strict = 0,
+ CES_AllowParameters = 1,
+ CES_AllowDifferentTypes = 2,
+ CES_AllowExceptionVariables = 4,
+ CES_FormerDefault = (CES_AllowParameters),
+ CES_Default = (CES_AllowParameters | CES_AllowDifferentTypes),
+ CES_AsIfByStdMove = (CES_AllowParameters | CES_AllowDifferentTypes |
+ CES_AllowExceptionVariables),
+ };
+
+ VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E,
+ CopyElisionSemanticsKind CESK);
+ bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD,
+ CopyElisionSemanticsKind CESK);
+
+ StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
+ Scope *CurScope);
+ StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+ StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp);
+
+ StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
+ bool IsVolatile, unsigned NumOutputs,
+ unsigned NumInputs, IdentifierInfo **Names,
+ MultiExprArg Constraints, MultiExprArg Exprs,
+ Expr *AsmString, MultiExprArg Clobbers,
+ 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);
+
+ /// DiagnoseUnusedExprResult - If the statement passed in is an expression
+ /// whose result is unused, warn.
+ void DiagnoseUnusedExprResult(const Stmt *S);
+ void DiagnoseUnusedNestedTypedefs(const RecordDecl *D);
+ void DiagnoseUnusedDecl(const NamedDecl *ND);
+
+ /// 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);
+
+ /// 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() {
+ return DelayedDiagnostics.pushUndelayed();
+ }
+ void PopParsingClass(ParsingClassState state) {
+ 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);
+
+ //===--------------------------------------------------------------------===//
+ // Expression Parsing Callbacks: SemaExpr.cpp.
+
+ bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid);
+ bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
+ const ObjCInterfaceDecl *UnknownObjCClass = nullptr,
+ bool ObjCPropertyAccess = false,
+ bool AvoidPartialAvailabilityChecks = false,
+ ObjCInterfaceDecl *ClassReciever = nullptr);
+ void NoteDeletedFunction(FunctionDecl *FD);
+ void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD);
+ std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
+ 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);
+ ExprResult HandleExprEvaluationContextForTypeof(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 UpdateMarkingForLValueToRValue(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(VarDecl *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(VarDecl *Var, SourceLocation Loc,
+ TryCaptureKind Kind = TryCapture_Implicit,
+ SourceLocation EllipsisLoc = SourceLocation());
+
+ /// Checks if the variable must be captured.
+ bool NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc);
+
+ /// Given a variable, determine the type that a reference to that
+ /// variable will have in the given scope.
+ QualType getCapturedDeclRefType(VarDecl *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);
+
+ /// 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);
+
+ /// 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);
+
+ // Primary Expressions.
+ SourceRange getExprRange(Expr *E) const;
+
+ ExprResult ActOnIdExpression(
+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
+ std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr,
+ bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
+
+ void DecomposeUnqualifiedId(const UnqualifiedId &Id,
+ TemplateArgumentListInfo &Buffer,
+ DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *&TemplateArgs);
+
+ bool
+ DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+ std::unique_ptr<CorrectionCandidateCallback> CCC,
+ TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+ ArrayRef<Expr *> Args = None, TypoExpr **Out = nullptr);
+
+ 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);
+
+ ExprResult BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ ExprValueKind VK,
+ SourceLocation Loc,
+ const CXXScopeSpec *SS = nullptr);
+ ExprResult
+ BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+ const DeclarationNameInfo &NameInfo,
+ const CXXScopeSpec *SS = nullptr,
+ NamedDecl *FoundD = nullptr,
+ 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);
+ 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);
+
+ 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);
+ ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc,
+ UnaryOperatorKind Opc, Expr *Input);
+ ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
+ tok::TokenKind Op, Expr *Input);
+
+ bool isQualifiedMemberAccess(Expr *E);
+ QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+
+ 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,
+ Expr *Idx, SourceLocation RLoc);
+ ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+ Expr *Idx, SourceLocation RLoc);
+ ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
+ Expr *LowerBound, SourceLocation ColonLoc,
+ Expr *Length, SourceLocation RBLoc);
+
+ // 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);
+
+ 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,
+ bool IsExecConfig = false);
+ 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 ActOnDesignatedInitializer(Designation &Desig,
+ SourceLocation Loc,
+ 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 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(SourceLocation LPLoc, Stmt *SubStmt,
+ SourceLocation RPLoc); // "({..})"
+ 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);
+
+ // __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);
+
+ //===---------------------------- 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);
+ void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
+
+ NamespaceDecl *getStdNamespace() const;
+ NamespaceDecl *getOrCreateStdNamespace();
+
+ NamespaceDecl *lookupStdExperimentalNamespace();
+
+ 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:
+ /// 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);
+
+ /// 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 HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
+ bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
+ const LookupResult &PreviousDecls,
+ UsingShadowDecl *&PrevShadow);
+ UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
+ 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);
+
+ NamedDecl *BuildUsingDeclaration(
+ Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
+ bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
+ DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
+ const ParsedAttributesView &AttrList, bool IsInstantiation);
+ 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 *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 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);
+
+ /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+ /// the default expr if needed.
+ ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc,
+ FunctionDecl *FD,
+ ParmVarDecl *Param);
+
+ /// 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);
+
+ /// 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;
+ }
+ };
+
+ /// Determine what sort of exception specification a defaulted
+ /// copy constructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
+ CXXMethodDecl *MD);
+
+ /// Determine what sort of exception specification a defaulted
+ /// default constructor of a class will have, and whether the parameter
+ /// will be const.
+ ImplicitExceptionSpecification
+ ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD);
+
+ /// Determine what sort of exception specification a defaulted
+ /// copy assignment operator of a class will have, and whether the
+ /// parameter will be const.
+ ImplicitExceptionSpecification
+ ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD);
+
+ /// Determine what sort of exception specification a defaulted move
+ /// constructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD);
+
+ /// Determine what sort of exception specification a defaulted move
+ /// assignment operator of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD);
+
+ /// Determine what sort of exception specification a defaulted
+ /// destructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD);
+
+ /// Determine what sort of exception specification an inheriting
+ /// constructor of a class will have.
+ ImplicitExceptionSpecification
+ ComputeInheritingCtorExceptionSpec(SourceLocation Loc,
+ CXXConstructorDecl *CD);
+
+ /// Evaluate the implicit exception specification for a defaulted
+ /// special member function.
+ void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD);
+
+ /// Check the given noexcept-specifier, convert its expression, and compute
+ /// the appropriate ExceptionSpecificationType.
+ ExprResult ActOnNoexceptSpec(SourceLocation NoexceptLoc, 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);
+
+ /// 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);
+
+ bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+ 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);
+
+ /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_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 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(SourceLocation LParenLoc, Expr *LHS,
+ tok::TokenKind Operator,
+ SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc);
+ ExprResult BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS,
+ BinaryOperatorKind Operator,
+ SourceLocation EllipsisLoc, Expr *RHS,
+ SourceLocation RParenLoc);
+ ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
+ BinaryOperatorKind Operator);
+
+ //// ActOnCXXThis - Parse 'this' pointer.
+ ExprResult ActOnCXXThis(SourceLocation loc);
+
+ /// 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,
+ 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);
+ 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);
+ StmtResult ActOnFinishFullStmt(Stmt *Stmt);
+
+ // Marks SS invalid if it represents an incomplete type.
+ bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
+
+ 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 ErrorRecoveryLookup If true, then this method is called to improve
+ /// error recovery. In this case do not emit error message.
+ ///
+ /// \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 ErrorRecoveryLookup = false,
+ 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,
+ bool KnownDependent,
+ LambdaCaptureDefault CaptureDefault);
+
+ /// Start the definition of a lambda expression.
+ CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class,
+ SourceRange IntroducerRange,
+ TypeSourceInfo *MethodType,
+ SourceLocation EndLoc,
+ ArrayRef<ParmVarDecl *> Params,
+ bool IsConstexprSpecified);
+
+ /// 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, IdentifierInfo *Id,
+ LambdaCaptureInitKind InitKind, Expr *&Init) {
+ return ParsedType::make(buildLambdaInitCaptureInitialization(
+ Loc, ByRef, Id, InitKind != LambdaCaptureInitKind::CopyInit, Init));
+ }
+ QualType buildLambdaInitCaptureInitialization(SourceLocation Loc, bool ByRef,
+ 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,
+ IdentifierInfo *Id,
+ unsigned InitStyle, Expr *Init);
+
+ /// Build the implicit field for an init-capture.
+ FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var);
+
+ /// Note that we have finished the explicit captures for the
+ /// given lambda.
+ void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ // 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 = None);
+
+ 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);
+
+ /// 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);
+
+ /// 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);
+
+ void CheckCompletedCXXClass(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(Decl *D);
+
+ void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
+ unsigned ActOnReenterTemplateScope(Scope *S, Decl *Template);
+ 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);
+
+ 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 CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD);
+ void CheckExplicitlyDefaultedMemberExceptionSpec(CXXMethodDecl *MD,
+ const FunctionProtoType *T);
+ void CheckDelayedMemberExceptionSpecs();
+
+ //===--------------------------------------------------------------------===//
+ // 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,
+ ParsedAttributes &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 AmbigiousBaseConvID,
+ 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);
+
+ /// 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,
+ Expr *ArgExpr,
+ 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 isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
+ AccessSpecifier access,
+ QualType objectType);
+
+ 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 hasAnyAcceptableTemplateNames(LookupResult &R,
+ bool AllowFunctionTemplates = true);
+
+ bool LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
+ QualType ObjectType, bool EnteringContext,
+ bool &MemberOfUnknownSpecialization,
+ SourceLocation TemplateKWLoc = SourceLocation());
+
+ TemplateNameKind isTemplateName(Scope *S,
+ CXXScopeSpec &SS,
+ bool hasTemplateKeyword,
+ const UnqualifiedId &Name,
+ ParsedType ObjectType,
+ bool EnteringContext,
+ TemplateTy &Template,
+ bool &MemberOfUnknownSpecialization);
+
+ /// 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);
+
+ 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);
+
+ 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);
+
+ 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(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ TemplateTy Template, IdentifierInfo *TemplateII,
+ SourceLocation TemplateIILoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation RAngleLoc,
+ bool IsCtorOrDtorName = false,
+ bool IsClassName = false);
+
+ /// 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);
+
+ DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ SourceLocation TemplateNameLoc,
+ const TemplateArgumentListInfo &TemplateArgs);
+
+ ExprResult CheckVarTemplateId(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ VarTemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ 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 ActOnDependentTemplateName(
+ 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, 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,
+ SmallVectorImpl<TemplateArgument>
+ &Converted,
+ 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> &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+
+ /// Check that the given template arguments can be 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.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool CheckTemplateArgumentList(TemplateDecl *Template,
+ SourceLocation TemplateLoc,
+ TemplateArgumentListInfo &TemplateArgs,
+ bool PartialTemplateArgs,
+ SmallVectorImpl<TemplateArgument> &Converted,
+ bool UpdateArgsWithConversions = true);
+
+ bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
+ TemplateArgumentLoc &Arg,
+ SmallVectorImpl<TemplateArgument> &Converted);
+
+ bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+ TypeSourceInfo *Arg);
+ ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+ QualType InstantiatedParamType, Expr *Arg,
+ TemplateArgument &Converted,
+ CheckTemplateArgumentKind CTAK = CTAK_Specified);
+ bool CheckTemplateTemplateArgument(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(TemplateParameterList *New,
+ TemplateParameterList *Old,
+ bool Complain,
+ TemplateParameterListEqualKind Kind,
+ SourceLocation TemplateArgLoc
+ = SourceLocation());
+
+ 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.
+ TypeResult
+ ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+ const CXXScopeSpec &SS, const IdentifierInfo &II,
+ SourceLocation IdLoc);
+
+ /// 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 *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++ 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
+ };
+
+ /// 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 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,
+ Optional<unsigned> NumExpansions);
+
+ /// Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ QualType CheckPackExpansion(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc,
+ 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,
+ 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,
+ 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.
+ 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,
+ 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.
+ 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,
+ /// Deduction failed; that's all we know.
+ TDK_MiscellaneousDeductionFailure,
+ /// CUDA Target attributes do not match.
+ TDK_CUDATargetMismatch
+ };
+
+ 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);
+ /// 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);
+
+ /// Result type of DeduceAutoType.
+ enum DeduceAutoResult {
+ DAR_Succeeded,
+ DAR_Failed,
+ DAR_FailedAlreadyDiagnosed
+ };
+
+ DeduceAutoResult
+ DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth = None);
+ DeduceAutoResult
+ DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer, QualType &Result,
+ Optional<unsigned> DependentDeductionDepth = None);
+ 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, AutoType *AT);
+
+ FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
+ FunctionTemplateDecl *FT2,
+ SourceLocation Loc,
+ TemplatePartialOrderingContext TPOC,
+ unsigned NumCallArguments1,
+ unsigned NumCallArguments2);
+ 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 *P, TemplateDecl *AArg, SourceLocation Loc);
+
+ 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(NamedDecl *D,
+ const TemplateArgumentList *Innermost = nullptr,
+ bool RelativeToPrimary = false,
+ const FunctionDecl *Pattern = nullptr);
+
+ /// 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 declaring an implicit special member function.
+ DeclaringSpecialMember,
+
+ /// We are defining a synthesized function (such as a defaulted special
+ /// member).
+ DefiningSynthesizedFunction,
+
+ /// 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;
+
+ /// The list of template arguments we are substituting, if they
+ /// are not part of the entity.
+ const TemplateArgument *TemplateArgs;
+
+ // 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 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), 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);
+
+
+ /// 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 = None,
+ 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.
+ 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();
+ }
+
+ /// 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.
+ assert(S.PendingInstantiations.empty() &&
+ "PendingInstantiations should be empty before it is discarded.");
+ S.PendingInstantiations.swap(SavedPendingInstantiations);
+ }
+
+ 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);
+ 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,
+ Optional<unsigned> NumExpansions,
+ bool ExpectParameterPack);
+ bool SubstParmTypes(SourceLocation Loc, ArrayRef<ParmVarDecl *> Params,
+ const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ SmallVectorImpl<QualType> &ParamTypes,
+ SmallVectorImpl<ParmVarDecl *> *OutParams,
+ ExtParameterInfoBuilder &ParamInfos);
+ ExprResult SubstExpr(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);
+
+ Decl *SubstDecl(Decl *D, DeclContext *Owner,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ ExprResult SubstInitializer(Expr *E,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ bool CXXDirectInit);
+
+ bool
+ SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
+ CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ bool
+ InstantiateClass(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
+ bool InstantiateEnum(SourceLocation PointOfInstantiation,
+ EnumDecl *Instantiation, EnumDecl *Pattern,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK);
+
+ bool InstantiateInClassInitializer(
+ SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
+ FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ 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);
+
+ 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 Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+ TemplateArgumentListInfo &Result,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
+ void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function);
+ FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
+ const TemplateArgumentList *Args,
+ SourceLocation Loc);
+ void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function,
+ bool Recursive = false,
+ bool DefinitionRequired = false,
+ bool AtEndOfTU = false);
+ VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+ const TemplateArgumentList &TemplateArgList,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ SmallVectorImpl<TemplateArgument> &Converted,
+ SourceLocation PointOfInstantiation, void *InsertPos,
+ 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);
+ 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);
+
+ Decl *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);
+
+ 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);
+
+ Decl *ActOnStartProtocolInterface(
+ SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
+ SourceLocation ProtocolLoc, Decl *const *ProtoRefNames,
+ unsigned NumProtoRefs, const SourceLocation *ProtoLocs,
+ SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList);
+
+ Decl *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);
+
+ Decl *ActOnStartClassImplementation(
+ SourceLocation AtClassImplLoc,
+ IdentifierInfo *ClassName, SourceLocation ClassLoc,
+ IdentifierInfo *SuperClassname,
+ SourceLocation SuperClassLoc);
+
+ Decl *ActOnStartCategoryImplementation(SourceLocation AtCatImplLoc,
+ IdentifierInfo *ClassName,
+ SourceLocation ClassLoc,
+ IdentifierInfo *CatName,
+ SourceLocation CatLoc);
+
+ 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 = false);
+
+ /// 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 = None,
+ ArrayRef<DeclGroupPtrTy> allTUVars = None);
+
+ 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);
+
+ 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 ConversionToObjCStringLiteralCheck(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 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 PragmaPackDiagnoseKind {
+ NonDefaultStateAtInclude,
+ ChangedStateAtExit
+ };
+
+ void DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind,
+ SourceLocation IncludeLoc);
+ void DiagnoseUnterminatedPragmaPack();
+
+ /// 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,
+ MSVtorDispAttr::Mode Value);
+
+ enum PragmaSectionKind {
+ PSK_DataSeg,
+ PSK_BSSSeg,
+ PSK_ConstSeg,
+ PSK_CodeSeg,
+ };
+
+ bool UnifySection(StringRef SectionName,
+ int SectionFlags,
+ DeclaratorDecl *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 #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);
+
+ /// 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, IdentifierInfo *II,
+ SourceLocation Loc);
+ void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, 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(LangOptions::FPContractModeKind FPC);
+
+ /// ActOnPragmaFenvAccess - Called on well formed
+ /// \#pragma STDC FENV_ACCESS
+ void ActOnPragmaFEnvAccess(LangOptions::FEnvAccessModeKind FPC);
+
+ /// 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);
+
+ /// FreePackedContext - Deallocate and null out PackContext.
+ void FreePackedContext();
+
+ /// 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);
+
+ /// 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);
+
+ /// 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);
+
+ /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
+ void AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ unsigned SpellingListIndex, bool IsPackExpansion);
+ void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T,
+ unsigned SpellingListIndex, bool IsPackExpansion);
+
+ /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
+ /// declaration.
+ void AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, Expr *OE,
+ unsigned SpellingListIndex);
+
+ /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
+ /// declaration.
+ void AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr,
+ unsigned SpellingListIndex);
+
+ /// AddAlignValueAttr - Adds an align_value attribute to a particular
+ /// declaration.
+ void AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E,
+ unsigned SpellingListIndex);
+
+ /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
+ /// declaration.
+ void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
+ Expr *MinBlocks, unsigned SpellingListIndex);
+
+ /// AddModeAttr - Adds a mode attribute to a particular declaration.
+ void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
+ unsigned SpellingListIndex, bool InInstantiation = false);
+
+ void AddParameterABIAttr(SourceRange AttrRange, Decl *D,
+ ParameterABI ABI, unsigned SpellingListIndex);
+
+ enum class RetainOwnershipKind {NS, CF, OS};
+ void AddXConsumedAttr(Decl *D, SourceRange SR, unsigned SpellingIndex,
+ RetainOwnershipKind K, bool IsTemplateInstantiation);
+
+ 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 BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *E,
+ bool IsImplicit = false);
+ ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *E,
+ 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);
+ ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
+ SourceLocation FuncLoc);
+
+ //===--------------------------------------------------------------------===//
+ // OpenCL extensions.
+ //
+private:
+ std::string CurrOpenCLExtension;
+ /// Extensions required by an OpenCL type.
+ llvm::DenseMap<const Type*, std::set<std::string>> OpenCLTypeExtMap;
+ /// Extensions required by an OpenCL declaration.
+ llvm::DenseMap<const Decl*, std::set<std::string>> OpenCLDeclExtMap;
+public:
+ llvm::StringRef getCurrentOpenCLExtension() const {
+ return CurrOpenCLExtension;
+ }
+
+ /// Check if a function declaration \p FD associates with any
+ /// extensions present in OpenCLDeclExtMap and if so return the
+ /// extension(s) name(s).
+ std::string getOpenCLExtensionsFromDeclExtMap(FunctionDecl *FD);
+
+ /// Check if a function type \p FT associates with any
+ /// extensions present in OpenCLTypeExtMap and if so return the
+ /// extension(s) name(s).
+ std::string getOpenCLExtensionsFromTypeExtMap(FunctionType *FT);
+
+ /// Find an extension in an appropriate extension map and return its name
+ template<typename T, typename MapT>
+ std::string getOpenCLExtensionsFromExtMap(T* FT, MapT &Map);
+
+ void setCurrentOpenCLExtension(llvm::StringRef Ext) {
+ CurrOpenCLExtension = Ext;
+ }
+
+ /// Set OpenCL extensions for a type which can only be used when these
+ /// OpenCL extensions are enabled. If \p Exts is empty, do nothing.
+ /// \param Exts A space separated list of OpenCL extensions.
+ void setOpenCLExtensionForType(QualType T, llvm::StringRef Exts);
+
+ /// Set OpenCL extensions for a declaration which can only be
+ /// used when these OpenCL extensions are enabled. If \p Exts is empty, do
+ /// nothing.
+ /// \param Exts A space separated list of OpenCL extensions.
+ void setOpenCLExtensionForDecl(Decl *FD, llvm::StringRef Exts);
+
+ /// Set current OpenCL extensions for a type which can only be used
+ /// when these OpenCL extensions are enabled. If current OpenCL extension is
+ /// empty, do nothing.
+ void setCurrentOpenCLExtensionForType(QualType T);
+
+ /// Set current OpenCL extensions for a declaration which
+ /// can only be used when these OpenCL extensions are enabled. If current
+ /// OpenCL extension is empty, do nothing.
+ void setCurrentOpenCLExtensionForDecl(Decl *FD);
+
+ bool isOpenCLDisabledDecl(Decl *FD);
+
+ /// Check if type \p T corresponding to declaration specifier \p DS
+ /// is disabled due to required OpenCL extensions being disabled. If so,
+ /// emit diagnostics.
+ /// \return true if type is disabled.
+ bool checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType T);
+
+ /// Check if declaration \p D used by expression \p E
+ /// is disabled due to required OpenCL extensions being disabled. If so,
+ /// emit diagnostics.
+ /// \return true if type is disabled.
+ bool checkOpenCLDisabledDecl(const NamedDecl &D, const Expr &E);
+
+ //===--------------------------------------------------------------------===//
+ // OpenMP directives and clauses.
+ //
+private:
+ void *VarDataSharingAttributesStack;
+ /// Number of nested '#pragma omp declare target' directives.
+ unsigned DeclareTargetNestingLevel = 0;
+ /// Initialization of data-sharing attributes stack.
+ void InitDataSharingAttributesStack();
+ void DestroyDataSharingAttributesStack();
+ ExprResult
+ VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
+ bool StrictlyPositive = true);
+ /// 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;
+
+ /// 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);
+
+ /// Check whether we're allowed to call Callee from the current function.
+ void checkOpenMPDeviceFunction(SourceLocation Loc, FunctionDecl *Callee);
+
+ /// Checks if a type or a declaration is disabled due to the owning extension
+ /// being disabled, and emits diagnostic messages if it is disabled.
+ /// \param D type or declaration to be checked.
+ /// \param DiagLoc source location for the diagnostic message.
+ /// \param DiagInfo information to be emitted for the diagnostic message.
+ /// \param SrcRange source range of the declaration.
+ /// \param Map maps type or declaration to the extensions.
+ /// \param Selector selects diagnostic message: 0 for type and 1 for
+ /// declaration.
+ /// \return true if the type or declaration is disabled.
+ template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
+ bool checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc, DiagInfoT DiagInfo,
+ MapT &Map, unsigned Selector = 0,
+ SourceRange SrcRange = SourceRange());
+
+public:
+ /// 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.
+ bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) 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);
+ 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();
+
+ /// Check if the specified variable is used in 'private' clause.
+ /// \param Level Relative level of nested OpenMP construct for that the check
+ /// is performed.
+ bool isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) 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) 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);
+
+ // OpenMP directives and clauses.
+ /// Called on correct id-expression from the '#pragma omp
+ /// threadprivate'.
+ ExprResult ActOnOpenMPIdExpression(Scope *CurScope,
+ CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id);
+ /// 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 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'.
+ OMPDeclareMapperDecl *ActOnOpenMPDeclareMapperDirectiveStart(
+ Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
+ SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
+ Decl *PrevDeclInScope = nullptr);
+ /// Build the mapper variable of '#pragma omp declare mapper'.
+ void ActOnOpenMPDeclareMapperDirectiveVarDecl(OMPDeclareMapperDecl *DMD,
+ Scope *S, QualType MapperType,
+ SourceLocation StartLoc,
+ DeclarationName VN);
+ /// Called at the end of '#pragma omp declare mapper'.
+ DeclGroupPtrTy
+ ActOnOpenMPDeclareMapperDirectiveEnd(OMPDeclareMapperDecl *D, Scope *S,
+ ArrayRef<OMPClause *> ClauseList);
+
+ /// Called on the start of target region i.e. '#pragma omp declare target'.
+ bool ActOnStartOpenMPDeclareTargetDirective(SourceLocation Loc);
+ /// Called at the end of target region i.e. '#pragme omp end declare target'.
+ void ActOnFinishOpenMPDeclareTargetDirective();
+ /// Called on correct id-expression from the '#pragma omp declare target'.
+ void ActOnOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec,
+ const DeclarationNameInfo &Id,
+ OMPDeclareTargetDeclAttr::MapTypeTy MT,
+ NamedDeclSetType &SameDirectiveDecls);
+ /// Check declaration inside target region.
+ void
+ checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+ SourceLocation IdLoc = SourceLocation());
+ /// Return true inside OpenMP declare target region.
+ bool isInOpenMPDeclareTargetContext() const {
+ return DeclareTargetNestingLevel > 0;
+ }
+ /// Return true inside OpenMP target region.
+ bool isInOpenMPTargetExecutionDirective() const;
+ /// Return true if (un)supported features for the current target should be
+ /// diagnosed if OpenMP (offloading) is enabled.
+ bool shouldDiagnoseTargetSupportFromOpenMP() const {
+ return !getLangOpts().OpenMPIsDevice || isInOpenMPDeclareTargetContext() ||
+ isInOpenMPTargetExecutionDirective();
+ }
+
+ /// 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);
+ /// 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 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 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 barrier'.
+ StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed '\#pragma omp taskwait'.
+ StmtResult ActOnOpenMPTaskwaitDirective(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 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 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 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);
+
+ /// 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);
+
+ /// 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);
+
+ OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
+ Expr *Expr,
+ 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 '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-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(Expr *Size, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'num_tasks' clause.
+ OMPClause *ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'hint' clause.
+ OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+
+ OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
+ unsigned Argument,
+ SourceLocation ArgumentLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'default' clause.
+ OMPClause *ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
+ SourceLocation KindLoc,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'proc_bind' clause.
+ OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind 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 'seq_cst' clause.
+ OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
+ 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);
+
+ OMPClause *ActOnOpenMPVarListClause(
+ OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *TailExpr,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId, OpenMPDependClauseKind DepKind,
+ OpenMPLinearClauseKind LinKind,
+ ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
+ OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
+ SourceLocation DepLinMapLoc);
+ /// 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,
+ 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, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
+ CXXScopeSpec &ReductionIdScopeSpec,
+ const DeclarationNameInfo &ReductionId,
+ ArrayRef<Expr *> UnresolvedReductions = llvm::None);
+ /// 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 = llvm::None);
+ /// 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 = llvm::None);
+ /// 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 'depend' clause.
+ OMPClause *
+ ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'device' clause.
+ OMPClause *ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'map' clause.
+ OMPClause *
+ ActOnOpenMPMapClause(ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
+ ArrayRef<SourceLocation> MapTypeModifiersLoc,
+ OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
+ SourceLocation MapLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc);
+ /// 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<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'from' clause.
+ OMPClause *ActOnOpenMPFromClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'use_device_ptr' clause.
+ OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
+ /// Called on well-formed 'is_device_ptr' clause.
+ OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
+ 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_RValue,
+ 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 is DefaultFunctionArrayLvalueConversion,
+ // except that it assumes the operand isn't of function or 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 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);
+
+ // 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,
+ bool IsCompAssign = false);
+
+ /// AssignConvertType - All of the 'assignment' semantic checks return this
+ /// enum to indicate whether the assignment was allowed. These checks are
+ /// done for simple assignments, as well as initialization, return from
+ /// function, argument passing, etc. The query is phrased in terms of a
+ /// source and destination type.
+ enum AssignConvertType {
+ /// Compatible - the types are compatible according to the standard.
+ Compatible,
+
+ /// 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,
+
+ /// 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,
+
+ /// 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,
+ AssignmentAction Action,
+ bool AllowExplicit,
+ ImplicitConversionSequence& ICS);
+ 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_RValue,
+ 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);
+ 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);
+
+ 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 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);
+ QualType GetSignedVectorType(QualType V);
+ QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc,
+ BinaryOperatorKind Opc);
+ QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
+ SourceLocation Loc);
+
+ bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
+ bool isLaxVectorConversion(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
+ };
+
+ ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
+ QualType T1, QualType T2,
+ bool &DerivedToBase,
+ bool &ObjCConversion,
+ bool &ObjCLifetimeConversion);
+
+ 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);
+
+ // 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());
+ }
+ llvm::Optional<bool> getKnownValue() const {
+ if (!HasKnownValue)
+ return None;
+ 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.
+ };
+
+ ConditionResult ActOnCondition(Scope *S, SourceLocation Loc,
+ Expr *SubExpr, ConditionKind CK);
+
+ 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);
+
+ /// 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 void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) =0;
+ virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR);
+ virtual ~VerifyICEDiagnoser() { }
+ };
+
+ /// 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,
+ bool AllowFold = true);
+ ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ unsigned DiagID,
+ bool AllowFold = true);
+ ExprResult VerifyIntegerConstantExpression(Expr *E,
+ llvm::APSInt *Result = nullptr);
+
+ /// 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.
+ /// Can optionally return whether the bit-field is of width 0
+ ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+ QualType FieldTy, bool IsMsStruct,
+ Expr *BitWidth, bool *ZeroWidth = nullptr);
+
+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;
+
+ /// A partial call graph maintained during CUDA/OpenMP device code compilation
+ /// to support deferred diagnostics.
+ ///
+ /// Functions are only added here if, at the time they're considered, they are
+ /// not known-emitted. As soon as we discover that a function is
+ /// known-emitted, we remove it and everything it transitively calls from this
+ /// set and add those functions to DeviceKnownEmittedFns.
+ llvm::DenseMap</* Caller = */ CanonicalDeclPtr<FunctionDecl>,
+ /* Callees = */ llvm::MapVector<CanonicalDeclPtr<FunctionDecl>,
+ SourceLocation>>
+ DeviceCallGraph;
+
+ /// Diagnostic builder for CUDA/OpenMP devices 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 DeviceDiagBuilder {
+ 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
+ };
+
+ DeviceDiagBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
+ FunctionDecl *Fn, Sema &S);
+ ~DeviceDiagBuilder();
+
+ /// 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 (DeviceDiagBuilder(...) << foo << bar)
+ /// return ExprError();
+ ///
+ /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably
+ /// want to use these instead of creating a DeviceDiagBuilder yourself.
+ operator bool() const { return ImmediateDiag.hasValue(); }
+
+ template <typename T>
+ friend const DeviceDiagBuilder &operator<<(const DeviceDiagBuilder &Diag,
+ const T &Value) {
+ if (Diag.ImmediateDiag.hasValue())
+ *Diag.ImmediateDiag << Value;
+ else if (Diag.PartialDiag.hasValue())
+ *Diag.PartialDiag << Value;
+ return Diag;
+ }
+
+ 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.
+ llvm::Optional<SemaDiagnosticBuilder> ImmediateDiag;
+ llvm::Optional<PartialDiagnostic> PartialDiag;
+ };
+
+ /// Indicate that this function (and thus everything it transtively calls)
+ /// will be codegen'ed, and emit any deferred diagnostics on this function and
+ /// its (transitive) callees.
+ void markKnownEmitted(
+ Sema &S, FunctionDecl *OrigCaller, FunctionDecl *OrigCallee,
+ SourceLocation OrigLoc,
+ const llvm::function_ref<bool(Sema &, FunctionDecl *)> IsKnownEmitted);
+
+ /// Creates a DeviceDiagBuilder that emits the diagnostic if the current context
+ /// is "used as device code".
+ ///
+ /// - If CurContext is a __host__ function, does not emit any diagnostics.
+ /// - 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.
+ DeviceDiagBuilder CUDADiagIfDeviceCode(SourceLocation Loc, unsigned DiagID);
+
+ /// Creates a DeviceDiagBuilder that emits the diagnostic if the current context
+ /// is "used as host code".
+ ///
+ /// Same as CUDADiagIfDeviceCode, with "host" and "device" switched.
+ DeviceDiagBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID);
+
+ /// Creates a DeviceDiagBuilder 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.
+ DeviceDiagBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID);
+
+ 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);
+
+ /// Gets the CUDA target for the current context.
+ CUDAFunctionTarget CurrentCUDATarget() {
+ return IdentifyCUDATarget(dyn_cast<FunctionDecl>(CurContext));
+ }
+
+ // 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);
+
+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);
+
+ /// Set __device__ or __host__ __device__ attributes on the given lambda
+ /// operator() method.
+ ///
+ /// CUDA lambdas declared inside __device__ or __global__ functions inherit
+ /// the __device__ attribute. Similarly, lambdas inside __host__ __device__
+ /// functions become __host__ __device__ themselves.
+ 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);
+ /// Reports signatures for a call to CodeCompleteConsumer and returns the
+ /// preferred type for the current argument. Returned type can be null.
+ QualType ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc);
+ QualType ProduceConstructorSignatureHelp(Scope *S, QualType Type,
+ SourceLocation Loc,
+ ArrayRef<Expr *> Args,
+ SourceLocation OpenParLoc);
+ QualType ProduceCtorInitMemberSignatureHelp(Scope *S, Decl *ConstructorDecl,
+ CXXScopeSpec SS,
+ ParsedType TemplateTypeTy,
+ ArrayRef<Expr *> ArgExprs,
+ IdentifierInfo *II,
+ SourceLocation OpenParLoc);
+ void CodeCompleteInitializer(Scope *S, Decl *D);
+ void CodeCompleteAfterIf(Scope *S);
+
+ void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
+ bool EnteringContext, QualType BaseType);
+ 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 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, 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;
+
+private:
+ void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
+ const ArraySubscriptExpr *ASE=nullptr,
+ bool AllowOnePastEnd=true, bool IndexNegated=false);
+ void CheckArrayAccess(const Expr *E);
+ // Used to grab the relevant information from a FormatAttr and a
+ // FunctionDeclaration.
+ struct FormatStringInfo {
+ unsigned FormatIdx;
+ unsigned FirstDataArg;
+ bool HasVAListArg;
+ };
+
+ static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+ FormatStringInfo *FSI);
+ 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,
+ ArrayRef<const Expr *> Args,
+ const FunctionProtoType *Proto,
+ SourceLocation Loc);
+
+ 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 CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
+ unsigned MaxWidth);
+ bool CheckNeonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+ bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+ bool CheckPPCBuiltinFunctionCall(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 SemaBuiltinVSX(CallExpr *TheCall);
+ bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
+
+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 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 SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
+ int ArgNum, unsigned ExpectedFieldNum,
+ bool AllowName);
+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,
+ bool HasVAListArg, 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 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);
+
+private:
+ void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+ void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
+ void CheckForIntOverflow(Expr *E);
+ void CheckUnsequencedOperations(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 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__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;
+
+ /// 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;
+
+ Decl *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;
+ }
+
+ /// 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;
+
+private:
+ 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");
+ assert(S.DelayedDefaultedMemberExceptionSpecs.empty() &&
+ "there shouldn't be any pending delayed defaulted member "
+ "exception specs");
+ assert(S.DelayedDllExportClasses.empty() &&
+ "there shouldn't be any pending delayed DLL export classes");
+ swapSavedState();
+ }
+
+ private:
+ Sema &S;
+ decltype(DelayedOverridingExceptionSpecChecks)
+ SavedOverridingExceptionSpecChecks;
+ decltype(DelayedEquivalentExceptionSpecChecks)
+ SavedEquivalentExceptionSpecChecks;
+ decltype(DelayedDefaultedMemberExceptionSpecs)
+ SavedDefaultedMemberExceptionSpecs;
+ decltype(DelayedDllExportClasses) SavedDllExportClasses;
+
+ void swapSavedState() {
+ SavedOverridingExceptionSpecChecks.swap(
+ S.DelayedOverridingExceptionSpecChecks);
+ SavedEquivalentExceptionSpecChecks.swap(
+ S.DelayedEquivalentExceptionSpecChecks);
+ SavedDefaultedMemberExceptionSpecs.swap(
+ S.DelayedDefaultedMemberExceptionSpecs);
+ SavedDllExportClasses.swap(S.DelayedDllExportClasses);
+ }
+ };
+
+ /// 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(), Alignment() {}
+ 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);
+};
+
+/// 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;
+};
+} // 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.getRawEncoding());
+ }
+
+ static bool isEqual(const FunctionDeclAndLoc &LHS,
+ const FunctionDeclAndLoc &RHS) {
+ return LHS.FD == RHS.FD && LHS.Loc == RHS.Loc;
+ }
+};
+} // namespace llvm
+
+#endif
diff --git a/clang-r353983e/include/clang/Sema/SemaConsumer.h b/clang-r353983e/include/clang/Sema/SemaConsumer.h
new file mode 100644
index 00000000..1c5962e9
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/SemaConsumer.h
@@ -0,0 +1,47 @@
+//===--- 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
diff --git a/clang-r353983e/include/clang/Sema/SemaDiagnostic.h b/clang-r353983e/include/clang/Sema/SemaDiagnostic.h
new file mode 100644
index 00000000..ae027eca
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/SemaDiagnostic.h
@@ -0,0 +1,14 @@
+//===--- 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
diff --git a/clang-r353983e/include/clang/Sema/SemaFixItUtils.h b/clang-r353983e/include/clang/Sema/SemaFixItUtils.h
new file mode 100644
index 00000000..df9bc429
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/SemaFixItUtils.h
@@ -0,0 +1,90 @@
+//===--- 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
diff --git a/clang-r353983e/include/clang/Sema/SemaInternal.h b/clang-r353983e/include/clang/Sema/SemaInternal.h
new file mode 100644
index 00000000..07e633ca
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/SemaInternal.h
@@ -0,0 +1,371 @@
+//===--- 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);
+}
+
+// This requires the variable to be non-dependent and the initializer
+// to not be value dependent.
+inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {
+ const VarDecl *DefVD = nullptr;
+ return !isa<ParmVarDecl>(Var) &&
+ Var->isUsableInConstantExpressions(Context) &&
+ Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();
+}
+
+// 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;
+}
+
+// Directly mark a variable odr-used. Given a choice, prefer to use
+// MarkVariableReferenced since it does additional checks and then
+// calls MarkVarDeclODRUsed.
+// If the variable must be captured:
+// - if FunctionScopeIndexToStopAt is null, capture it in the CurContext
+// - else capture it in the DeclContext that maps to the
+// *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack.
+inline void MarkVarDeclODRUsed(VarDecl *Var,
+ SourceLocation Loc, Sema &SemaRef,
+ const unsigned *const FunctionScopeIndexToStopAt) {
+ // Keep track of used but undefined variables.
+ // FIXME: We shouldn't suppress this warning for static data members.
+ if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
+ (!Var->isExternallyVisible() || Var->isInline() ||
+ SemaRef.isExternalWithNoLinkageType(Var)) &&
+ !(Var->isStaticDataMember() && Var->hasInit())) {
+ SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
+ if (old.isInvalid())
+ old = Loc;
+ }
+ QualType CaptureType, DeclRefType;
+ SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit,
+ /*EllipsisLoc*/ SourceLocation(),
+ /*BuildAndDiagnose*/ true,
+ CaptureType, DeclRefType,
+ FunctionScopeIndexToStopAt);
+
+ Var->markUsed(SemaRef.Context);
+}
+
+/// 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 ? llvm::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;
+ }
+
+ /// 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
diff --git a/clang-r353983e/include/clang/Sema/SemaLambda.h b/clang-r353983e/include/clang/Sema/SemaLambda.h
new file mode 100644
index 00000000..e8eaa46b
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/SemaLambda.h
@@ -0,0 +1,39 @@
+//===--- 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"
+
+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.
+
+Optional<unsigned> getStackIndexOfNearestEnclosingCaptureCapableLambda(
+ ArrayRef<const sema::FunctionScopeInfo *> FunctionScopes,
+ VarDecl *VarToCapture, Sema &S);
+
+} // clang
+
+#endif
diff --git a/clang-r353983e/include/clang/Sema/Template.h b/clang-r353983e/include/clang/Sema/Template.h
new file mode 100644
index 00000000..b2f0fbb9
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Template.h
@@ -0,0 +1,568 @@
+//===- 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 <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;
+
+ /// 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>;
+
+ /// The template argument lists, stored from the innermost template
+ /// argument list (first) to the outermost template argument list (last).
+ SmallVector<ArgList, 4> TemplateArgumentLists;
+
+ /// The number of outer levels of template arguments that are not
+ /// being substituted.
+ unsigned NumRetainedOuterLevels = 0;
+
+ public:
+ /// Construct an empty set of template argument lists.
+ MultiLevelTemplateArgumentList() = default;
+
+ /// Construct a single-level template argument list.
+ explicit
+ MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
+ addOuterTemplateArguments(&TemplateArgs);
+ }
+
+ /// 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();
+ }
+
+ /// 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].size());
+ return TemplateArgumentLists[getNumLevels() - Depth - 1][Index];
+ }
+
+ /// 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].size())
+ return false;
+
+ return !(*this)(Depth, Index).isNull();
+ }
+
+ /// 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].size());
+ const_cast<TemplateArgument&>(
+ TemplateArgumentLists[getNumLevels() - Depth - 1][Index])
+ = Arg;
+ }
+
+ /// Add a new outermost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
+ addOuterTemplateArguments(ArgList(TemplateArgs->data(),
+ TemplateArgs->size()));
+ }
+
+ /// Add a new outmost level to the multi-level template argument
+ /// list.
+ void addOuterTemplateArguments(ArgList Args) {
+ assert(!NumRetainedOuterLevels &&
+ "substituted args outside retained args?");
+ TemplateArgumentLists.push_back(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;
+ }
+
+ /// Retrieve the innermost template argument list.
+ const ArgList &getInnermost() const {
+ return TemplateArgumentLists.front();
+ }
+ };
+
+ /// 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<ParmVarDecl *, 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 otuer 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, ParmVarDecl *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;
+ };
+
+ class TemplateDeclInstantiator
+ : public DeclVisitor<TemplateDeclInstantiator, Decl *>
+ {
+ Sema &SemaRef;
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
+ DeclContext *Owner;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
+ Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
+ LocalInstantiationScope *StartingScope = nullptr;
+
+ /// 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) {}
+
+// 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 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)
+
+// Decls which use special-case instantiation code.
+#define BLOCK(DERIVED, BASE)
+#define CAPTURED(DERIVED, BASE)
+#define IMPLICITPARAM(DERIVED, BASE)
+
+#include "clang/AST/DeclNodes.inc"
+
+ // A few supplemental visitor functions.
+ Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
+ TemplateParameterList *TemplateParams,
+ bool IsClassScopeSpecialization = false);
+ Decl *VisitFunctionDecl(FunctionDecl *D,
+ TemplateParameterList *TemplateParams);
+ Decl *VisitDecl(Decl *D);
+ Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate,
+ ArrayRef<BindingDecl *> *Bindings = nullptr);
+
+ // 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);
+
+ TemplateParameterList *
+ SubstTemplateParams(TemplateParameterList *List);
+
+ bool SubstQualifier(const DeclaratorDecl *OldDecl,
+ DeclaratorDecl *NewDecl);
+ bool SubstQualifier(const TagDecl *OldDecl,
+ TagDecl *NewDecl);
+
+ Decl *VisitVarTemplateSpecializationDecl(
+ VarTemplateDecl *VarTemplate, VarDecl *FromVar, void *InsertPos,
+ const TemplateArgumentListInfo &TemplateArgsInfo,
+ ArrayRef<TemplateArgument> Converted);
+
+ 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
diff --git a/clang-r353983e/include/clang/Sema/TemplateDeduction.h b/clang-r353983e/include/clang/Sema/TemplateDeduction.h
new file mode 100644
index 00000000..662c4072
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/TemplateDeduction.h
@@ -0,0 +1,351 @@
+//===- 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/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/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include <cassert>
+#include <cstddef>
+#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 *Deduced = 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;
+
+ /// 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 list.
+ TemplateArgumentList *take() {
+ TemplateArgumentList *Result = Deduced;
+ Deduced = 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 *NewDeduced) {
+ Deduced = NewDeduced;
+ ExplicitArgs = Deduced->size();
+ }
+
+ /// Provide a new template argument list that contains the
+ /// results of template argument deduction.
+ void reset(TemplateArgumentList *NewDeduced) {
+ Deduced = NewDeduced;
+ }
+
+ /// 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;
+};
+
+} // 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.
+ llvm::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
diff --git a/clang-r353983e/include/clang/Sema/TemplateInstCallback.h b/clang-r353983e/include/clang/Sema/TemplateInstCallback.h
new file mode 100644
index 00000000..3ab0e8c6
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/TemplateInstCallback.h
@@ -0,0 +1,82 @@
+//===- 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_TEMPLATE_INST_CALLBACK_H
+#define LLVM_CLANG_TEMPLATE_INST_CALLBACK_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
diff --git a/clang-r353983e/include/clang/Sema/TypoCorrection.h b/clang-r353983e/include/clang/Sema/TypoCorrection.h
new file mode 100644
index 00000000..da57d1bf
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/TypoCorrection.h
@@ -0,0 +1,391 @@
+//===- 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;
+ }
+
+ 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;
+};
+
+/// Simple template class for restricting typo correction candidates
+/// to ones having a single Decl* of the given type.
+template <class C>
+class DeclFilterCCC : public CorrectionCandidateCallback {
+public:
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ return candidate.getCorrectionDeclAs<C>();
+ }
+};
+
+// 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;
+
+private:
+ unsigned NumArgs;
+ bool HasExplicitTemplateArgs;
+ DeclContext *CurContext;
+ MemberExpr *MemberFn;
+};
+
+// Callback class that effectively disabled typo correction
+class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
+public:
+ NoTypoCorrectionCCC() {
+ WantTypeSpecifiers = false;
+ WantExpressionKeywords = false;
+ WantCXXNamedCasts = false;
+ WantFunctionLikeCasts = false;
+ WantRemainingKeywords = false;
+ }
+
+ bool ValidateCandidate(const TypoCorrection &candidate) override {
+ return false;
+ }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_SEMA_TYPOCORRECTION_H
diff --git a/clang-r353983e/include/clang/Sema/Weak.h b/clang-r353983e/include/clang/Sema/Weak.h
new file mode 100644
index 00000000..43439367
--- /dev/null
+++ b/clang-r353983e/include/clang/Sema/Weak.h
@@ -0,0 +1,45 @@
+//===-- 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"
+
+namespace clang {
+
+class IdentifierInfo;
+
+/// Captures information about a \#pragma weak directive.
+class WeakInfo {
+ IdentifierInfo *alias; // alias (optional)
+ SourceLocation loc; // for diagnostics
+ bool used; // identifier later declared?
+public:
+ WeakInfo()
+ : alias(nullptr), loc(SourceLocation()), used(false) {}
+ WeakInfo(IdentifierInfo *Alias, SourceLocation Loc)
+ : alias(Alias), loc(Loc), used(false) {}
+ inline IdentifierInfo * getAlias() const { return alias; }
+ inline SourceLocation getLocation() const { return loc; }
+ void setUsed(bool Used=true) { used = Used; }
+ inline bool getUsed() { return used; }
+ bool operator==(WeakInfo RHS) const {
+ return alias == RHS.getAlias() && loc == RHS.getLocation();
+ }
+ bool operator!=(WeakInfo RHS) const { return !(*this == RHS); }
+};
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_SEMA_WEAK_H