diff options
| author | Stephen Hines <srhines@google.com> | 2019-07-02 16:25:20 -0700 |
|---|---|---|
| committer | Ali B <abittin@gmail.com> | 2019-07-05 19:33:16 +0300 |
| commit | 9afee4e65dc5f9f5eb371683729ff67b8df81d03 (patch) | |
| tree | 4cf241d6c9044f91ee8c06e6920174d06f8de0b6 /clang-r353983e/include/clang/Sema | |
| parent | 2f19bd722c4c825320d1511c1ed83161b7f95d51 (diff) | |
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')
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 ¶mType); + + // 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 |
