diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/Decl.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/Decl.cpp | 5094 |
1 files changed, 5094 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/Decl.cpp b/contrib/llvm-project/clang/lib/AST/Decl.cpp new file mode 100644 index 000000000000..10cfe145b3f0 --- /dev/null +++ b/contrib/llvm-project/clang/lib/AST/Decl.cpp @@ -0,0 +1,5094 @@ +//===- Decl.cpp - Declaration AST Node Implementation ---------------------===// +// +// 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 the Decl subclasses. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Decl.h" +#include "Linkage.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/ASTLambda.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" +#include "clang/AST/CanonicalType.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/ODRHash.h" +#include "clang/AST/PrettyDeclStackTrace.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Redeclarable.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/Linkage.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SanitizerBlacklist.h" +#include "clang/Basic/Sanitizers.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Visibility.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> +#include <memory> +#include <string> +#include <tuple> +#include <type_traits> + +using namespace clang; + +Decl *clang::getPrimaryMergedDecl(Decl *D) { + return D->getASTContext().getPrimaryMergedDecl(D); +} + +void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { + SourceLocation Loc = this->Loc; + if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); + if (Loc.isValid()) { + Loc.print(OS, Context.getSourceManager()); + OS << ": "; + } + OS << Message; + + if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) { + OS << " '"; + ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); + OS << "'"; + } + + OS << '\n'; +} + +// Defined here so that it can be inlined into its direct callers. +bool Decl::isOutOfLine() const { + return !getLexicalDeclContext()->Equals(getDeclContext()); +} + +TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx) + : Decl(TranslationUnit, nullptr, SourceLocation()), + DeclContext(TranslationUnit), Ctx(ctx) {} + +//===----------------------------------------------------------------------===// +// NamedDecl Implementation +//===----------------------------------------------------------------------===// + +// Visibility rules aren't rigorously externally specified, but here +// are the basic principles behind what we implement: +// +// 1. An explicit visibility attribute is generally a direct expression +// of the user's intent and should be honored. Only the innermost +// visibility attribute applies. If no visibility attribute applies, +// global visibility settings are considered. +// +// 2. There is one caveat to the above: on or in a template pattern, +// an explicit visibility attribute is just a default rule, and +// visibility can be decreased by the visibility of template +// arguments. But this, too, has an exception: an attribute on an +// explicit specialization or instantiation causes all the visibility +// restrictions of the template arguments to be ignored. +// +// 3. A variable that does not otherwise have explicit visibility can +// be restricted by the visibility of its type. +// +// 4. A visibility restriction is explicit if it comes from an +// attribute (or something like it), not a global visibility setting. +// When emitting a reference to an external symbol, visibility +// restrictions are ignored unless they are explicit. +// +// 5. When computing the visibility of a non-type, including a +// non-type member of a class, only non-type visibility restrictions +// are considered: the 'visibility' attribute, global value-visibility +// settings, and a few special cases like __private_extern. +// +// 6. When computing the visibility of a type, including a type member +// of a class, only type visibility restrictions are considered: +// the 'type_visibility' attribute and global type-visibility settings. +// However, a 'visibility' attribute counts as a 'type_visibility' +// attribute on any declaration that only has the former. +// +// The visibility of a "secondary" entity, like a template argument, +// is computed using the kind of that entity, not the kind of the +// primary entity for which we are computing visibility. For example, +// the visibility of a specialization of either of these templates: +// template <class T, bool (&compare)(T, X)> bool has_match(list<T>, X); +// template <class T, bool (&compare)(T, X)> class matcher; +// is restricted according to the type visibility of the argument 'T', +// the type visibility of 'bool(&)(T,X)', and the value visibility of +// the argument function 'compare'. That 'has_match' is a value +// and 'matcher' is a type only matters when looking for attributes +// and settings from the immediate context. + +/// Does this computation kind permit us to consider additional +/// visibility settings from attributes and the like? +static bool hasExplicitVisibilityAlready(LVComputationKind computation) { + return computation.IgnoreExplicitVisibility; +} + +/// Given an LVComputationKind, return one of the same type/value sort +/// that records that it already has explicit visibility. +static LVComputationKind +withExplicitVisibilityAlready(LVComputationKind Kind) { + Kind.IgnoreExplicitVisibility = true; + return Kind; +} + +static Optional<Visibility> getExplicitVisibility(const NamedDecl *D, + LVComputationKind kind) { + assert(!kind.IgnoreExplicitVisibility && + "asking for explicit visibility when we shouldn't be"); + return D->getExplicitVisibility(kind.getExplicitVisibilityKind()); +} + +/// Is the given declaration a "type" or a "value" for the purposes of +/// visibility computation? +static bool usesTypeVisibility(const NamedDecl *D) { + return isa<TypeDecl>(D) || + isa<ClassTemplateDecl>(D) || + isa<ObjCInterfaceDecl>(D); +} + +/// Does the given declaration have member specialization information, +/// and if so, is it an explicit specialization? +template <class T> static typename +std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type +isExplicitMemberSpecialization(const T *D) { + if (const MemberSpecializationInfo *member = + D->getMemberSpecializationInfo()) { + return member->isExplicitSpecialization(); + } + return false; +} + +/// For templates, this question is easier: a member template can't be +/// explicitly instantiated, so there's a single bit indicating whether +/// or not this is an explicit member specialization. +static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) { + return D->isMemberSpecialization(); +} + +/// Given a visibility attribute, return the explicit visibility +/// associated with it. +template <class T> +static Visibility getVisibilityFromAttr(const T *attr) { + switch (attr->getVisibility()) { + case T::Default: + return DefaultVisibility; + case T::Hidden: + return HiddenVisibility; + case T::Protected: + return ProtectedVisibility; + } + llvm_unreachable("bad visibility kind"); +} + +/// Return the explicit visibility of the given declaration. +static Optional<Visibility> getVisibilityOf(const NamedDecl *D, + NamedDecl::ExplicitVisibilityKind kind) { + // If we're ultimately computing the visibility of a type, look for + // a 'type_visibility' attribute before looking for 'visibility'. + if (kind == NamedDecl::VisibilityForType) { + if (const auto *A = D->getAttr<TypeVisibilityAttr>()) { + return getVisibilityFromAttr(A); + } + } + + // If this declaration has an explicit visibility attribute, use it. + if (const auto *A = D->getAttr<VisibilityAttr>()) { + return getVisibilityFromAttr(A); + } + + return None; +} + +LinkageInfo LinkageComputer::getLVForType(const Type &T, + LVComputationKind computation) { + if (computation.IgnoreAllVisibility) + return LinkageInfo(T.getLinkage(), DefaultVisibility, true); + return getTypeLinkageAndVisibility(&T); +} + +/// Get the most restrictive linkage for the types in the given +/// template parameter list. For visibility purposes, template +/// parameters are part of the signature of a template. +LinkageInfo LinkageComputer::getLVForTemplateParameterList( + const TemplateParameterList *Params, LVComputationKind computation) { + LinkageInfo LV; + for (const NamedDecl *P : *Params) { + // Template type parameters are the most common and never + // contribute to visibility, pack or not. + if (isa<TemplateTypeParmDecl>(P)) + continue; + + // Non-type template parameters can be restricted by the value type, e.g. + // template <enum X> class A { ... }; + // We have to be careful here, though, because we can be dealing with + // dependent types. + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { + // Handle the non-pack case first. + if (!NTTP->isExpandedParameterPack()) { + if (!NTTP->getType()->isDependentType()) { + LV.merge(getLVForType(*NTTP->getType(), computation)); + } + continue; + } + + // Look at all the types in an expanded pack. + for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) { + QualType type = NTTP->getExpansionType(i); + if (!type->isDependentType()) + LV.merge(getTypeLinkageAndVisibility(type)); + } + continue; + } + + // Template template parameters can be restricted by their + // template parameters, recursively. + const auto *TTP = cast<TemplateTemplateParmDecl>(P); + + // Handle the non-pack case first. + if (!TTP->isExpandedParameterPack()) { + LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters(), + computation)); + continue; + } + + // Look at all expansions in an expanded pack. + for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters(); + i != n; ++i) { + LV.merge(getLVForTemplateParameterList( + TTP->getExpansionTemplateParameters(i), computation)); + } + } + + return LV; +} + +static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { + const Decl *Ret = nullptr; + const DeclContext *DC = D->getDeclContext(); + while (DC->getDeclKind() != Decl::TranslationUnit) { + if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC)) + Ret = cast<Decl>(DC); + DC = DC->getParent(); + } + return Ret; +} + +/// Get the most restrictive linkage for the types and +/// declarations in the given template argument list. +/// +/// Note that we don't take an LVComputationKind because we always +/// want to honor the visibility of template arguments in the same way. +LinkageInfo +LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, + LVComputationKind computation) { + LinkageInfo LV; + + for (const TemplateArgument &Arg : Args) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Integral: + case TemplateArgument::Expression: + continue; + + case TemplateArgument::Type: + LV.merge(getLVForType(*Arg.getAsType(), computation)); + continue; + + case TemplateArgument::Declaration: { + const NamedDecl *ND = Arg.getAsDecl(); + assert(!usesTypeVisibility(ND)); + LV.merge(getLVForDecl(ND, computation)); + continue; + } + + case TemplateArgument::NullPtr: + LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType())); + continue; + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + if (TemplateDecl *Template = + Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) + LV.merge(getLVForDecl(Template, computation)); + continue; + + case TemplateArgument::Pack: + LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation)); + continue; + } + llvm_unreachable("bad template argument kind"); + } + + return LV; +} + +LinkageInfo +LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, + LVComputationKind computation) { + return getLVForTemplateArgumentList(TArgs.asArray(), computation); +} + +static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility. (Implicit instantiations won't + // have a direct attribute.) + if (!specInfo->isExplicitInstantiationOrSpecialization()) + return true; + + return !fn->hasAttr<VisibilityAttr>(); +} + +/// Merge in template-related linkage and visibility for the given +/// function template specialization. +/// +/// We don't need a computation kind here because we can assume +/// LVForValue. +/// +/// \param[out] LV the computation to use for the parent +void LinkageComputer::mergeTemplateLV( + LinkageInfo &LV, const FunctionDecl *fn, + const FunctionTemplateSpecializationInfo *specInfo, + LVComputationKind computation) { + bool considerVisibility = + shouldConsiderTemplateVisibility(fn, specInfo); + + // Merge information from the template parameters. + FunctionTemplateDecl *temp = specInfo->getTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + // Merge information from the template arguments. + const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments; + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); + LV.mergeMaybeWithVisibility(argsLV, considerVisibility); +} + +/// Does the given declaration have a direct visibility attribute +/// that would match the given rules? +static bool hasDirectVisibilityAttribute(const NamedDecl *D, + LVComputationKind computation) { + if (computation.IgnoreAllVisibility) + return false; + + return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) || + D->hasAttr<VisibilityAttr>(); +} + +/// Should we consider visibility associated with the template +/// arguments and parameters of the given class template specialization? +static bool shouldConsiderTemplateVisibility( + const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility (and note that implicit + // instantiations won't have a direct attribute). + // + // Furthermore, we want to ignore template parameters and arguments + // for an explicit specialization when computing the visibility of a + // member thereof with explicit visibility. + // + // This is a bit complex; let's unpack it. + // + // An explicit class specialization is an independent, top-level + // declaration. As such, if it or any of its members has an + // explicit visibility attribute, that must directly express the + // user's intent, and we should honor it. The same logic applies to + // an explicit instantiation of a member of such a thing. + + // Fast path: if this is not an explicit instantiation or + // specialization, we always want to consider template-related + // visibility restrictions. + if (!spec->isExplicitInstantiationOrSpecialization()) + return true; + + // This is the 'member thereof' check. + if (spec->isExplicitSpecialization() && + hasExplicitVisibilityAlready(computation)) + return false; + + return !hasDirectVisibilityAttribute(spec, computation); +} + +/// Merge in template-related linkage and visibility for the given +/// class template specialization. +void LinkageComputer::mergeTemplateLV( + LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec, + LVComputationKind computation) { + bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); + + // Merge information from the template parameters, but ignore + // visibility if we're only considering template arguments. + + ClassTemplateDecl *temp = spec->getSpecializedTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, + considerVisibility && !hasExplicitVisibilityAlready(computation)); + + // Merge information from the template arguments. We ignore + // template-argument visibility if we've got an explicit + // instantiation with a visibility attribute. + const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); + if (considerVisibility) + LV.mergeVisibility(argsLV); + LV.mergeExternalVisibility(argsLV); +} + +/// Should we consider visibility associated with the template +/// arguments and parameters of the given variable template +/// specialization? As usual, follow class template specialization +/// logic up to initialization. +static bool shouldConsiderTemplateVisibility( + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility (and note that implicit + // instantiations won't have a direct attribute). + if (!spec->isExplicitInstantiationOrSpecialization()) + return true; + + // An explicit variable specialization is an independent, top-level + // declaration. As such, if it has an explicit visibility attribute, + // that must directly express the user's intent, and we should honor + // it. + if (spec->isExplicitSpecialization() && + hasExplicitVisibilityAlready(computation)) + return false; + + return !hasDirectVisibilityAttribute(spec, computation); +} + +/// Merge in template-related linkage and visibility for the given +/// variable template specialization. As usual, follow class template +/// specialization logic up to initialization. +void LinkageComputer::mergeTemplateLV(LinkageInfo &LV, + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); + + // Merge information from the template parameters, but ignore + // visibility if we're only considering template arguments. + + VarTemplateDecl *temp = spec->getSpecializedTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, + considerVisibility && !hasExplicitVisibilityAlready(computation)); + + // Merge information from the template arguments. We ignore + // template-argument visibility if we've got an explicit + // instantiation with a visibility attribute. + const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); + if (considerVisibility) + LV.mergeVisibility(argsLV); + LV.mergeExternalVisibility(argsLV); +} + +static bool useInlineVisibilityHidden(const NamedDecl *D) { + // FIXME: we should warn if -fvisibility-inlines-hidden is used with c. + const LangOptions &Opts = D->getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden) + return false; + + const auto *FD = dyn_cast<FunctionDecl>(D); + if (!FD) + return false; + + TemplateSpecializationKind TSK = TSK_Undeclared; + if (FunctionTemplateSpecializationInfo *spec + = FD->getTemplateSpecializationInfo()) { + TSK = spec->getTemplateSpecializationKind(); + } else if (MemberSpecializationInfo *MSI = + FD->getMemberSpecializationInfo()) { + TSK = MSI->getTemplateSpecializationKind(); + } + + const FunctionDecl *Def = nullptr; + // InlineVisibilityHidden only applies to definitions, and + // isInlined() only gives meaningful answers on definitions + // anyway. + return TSK != TSK_ExplicitInstantiationDeclaration && + TSK != TSK_ExplicitInstantiationDefinition && + FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>(); +} + +template <typename T> static bool isFirstInExternCContext(T *D) { + const T *First = D->getFirstDecl(); + return First->isInExternCContext(); +} + +static bool isSingleLineLanguageLinkage(const Decl &D) { + if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) + if (!SD->hasBraces()) + return true; + return false; +} + +/// Determine whether D is declared in the purview of a named module. +static bool isInModulePurview(const NamedDecl *D) { + if (auto *M = D->getOwningModule()) + return M->isModulePurview(); + return false; +} + +static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) { + // FIXME: Handle isModulePrivate. + switch (D->getModuleOwnershipKind()) { + case Decl::ModuleOwnershipKind::Unowned: + case Decl::ModuleOwnershipKind::ModulePrivate: + return false; + case Decl::ModuleOwnershipKind::Visible: + case Decl::ModuleOwnershipKind::VisibleWhenImported: + return isInModulePurview(D); + } + llvm_unreachable("unexpected module ownership kind"); +} + +static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { + // Internal linkage declarations within a module interface unit are modeled + // as "module-internal linkage", which means that they have internal linkage + // formally but can be indirectly accessed from outside the module via inline + // functions and templates defined within the module. + if (isInModulePurview(D)) + return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); + + return LinkageInfo::internal(); +} + +static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { + // C++ Modules TS [basic.link]/6.8: + // - A name declared at namespace scope that does not have internal linkage + // by the previous rules and that is introduced by a non-exported + // declaration has module linkage. + if (isInModulePurview(D) && !isExportedFromModuleInterfaceUnit( + cast<NamedDecl>(D->getCanonicalDecl()))) + return LinkageInfo(ModuleLinkage, DefaultVisibility, false); + + return LinkageInfo::external(); +} + +static StorageClass getStorageClass(const Decl *D) { + if (auto *TD = dyn_cast<TemplateDecl>(D)) + D = TD->getTemplatedDecl(); + if (D) { + if (auto *VD = dyn_cast<VarDecl>(D)) + return VD->getStorageClass(); + if (auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->getStorageClass(); + } + return SC_None; +} + +LinkageInfo +LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage) { + assert(D->getDeclContext()->getRedeclContext()->isFileContext() && + "Not a name having namespace scope"); + ASTContext &Context = D->getASTContext(); + + // C++ [basic.link]p3: + // A name having namespace scope (3.3.6) has internal linkage if it + // is the name of + + if (getStorageClass(D->getCanonicalDecl()) == SC_Static) { + // - a variable, variable template, function, or function template + // that is explicitly declared static; or + // (This bullet corresponds to C99 6.2.2p3.) + return getInternalLinkageFor(D); + } + + if (const auto *Var = dyn_cast<VarDecl>(D)) { + // - a non-template variable of non-volatile const-qualified type, unless + // - it is explicitly declared extern, or + // - it is inline or exported, or + // - it was previously declared and the prior declaration did not have + // internal linkage + // (There is no equivalent in C99.) + if (Context.getLangOpts().CPlusPlus && + Var->getType().isConstQualified() && + !Var->getType().isVolatileQualified() && + !Var->isInline() && + !isExportedFromModuleInterfaceUnit(Var) && + !isa<VarTemplateSpecializationDecl>(Var) && + !Var->getDescribedVarTemplate()) { + const VarDecl *PrevVar = Var->getPreviousDecl(); + if (PrevVar) + return getLVForDecl(PrevVar, computation); + + if (Var->getStorageClass() != SC_Extern && + Var->getStorageClass() != SC_PrivateExtern && + !isSingleLineLanguageLinkage(*Var)) + return getInternalLinkageFor(Var); + } + + for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar; + PrevVar = PrevVar->getPreviousDecl()) { + if (PrevVar->getStorageClass() == SC_PrivateExtern && + Var->getStorageClass() == SC_None) + return getDeclLinkageAndVisibility(PrevVar); + // Explicitly declared static. + if (PrevVar->getStorageClass() == SC_Static) + return getInternalLinkageFor(Var); + } + } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { + // - a data member of an anonymous union. + const VarDecl *VD = IFD->getVarDecl(); + assert(VD && "Expected a VarDecl in this IndirectFieldDecl!"); + return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage); + } + assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!"); + + // FIXME: This gives internal linkage to names that should have no linkage + // (those not covered by [basic.link]p6). + if (D->isInAnonymousNamespace()) { + const auto *Var = dyn_cast<VarDecl>(D); + const auto *Func = dyn_cast<FunctionDecl>(D); + // FIXME: The check for extern "C" here is not justified by the standard + // wording, but we retain it from the pre-DR1113 model to avoid breaking + // code. + // + // C++11 [basic.link]p4: + // An unnamed namespace or a namespace declared directly or indirectly + // within an unnamed namespace has internal linkage. + if ((!Var || !isFirstInExternCContext(Var)) && + (!Func || !isFirstInExternCContext(Func))) + return getInternalLinkageFor(D); + } + + // Set up the defaults. + + // C99 6.2.2p5: + // If the declaration of an identifier for an object has file + // scope and no storage-class specifier, its linkage is + // external. + LinkageInfo LV = getExternalLinkageFor(D); + + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) { + LV.mergeVisibility(*Vis, true); + } else { + // If we're declared in a namespace with a visibility attribute, + // use that namespace's visibility, and it still counts as explicit. + for (const DeclContext *DC = D->getDeclContext(); + !isa<TranslationUnitDecl>(DC); + DC = DC->getParent()) { + const auto *ND = dyn_cast<NamespaceDecl>(DC); + if (!ND) continue; + if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) { + LV.mergeVisibility(*Vis, true); + break; + } + } + } + + // Add in global settings if the above didn't give us direct visibility. + if (!LV.isVisibilityExplicit()) { + // Use global type/value visibility as appropriate. + Visibility globalVisibility = + computation.isValueVisibility() + ? Context.getLangOpts().getValueVisibilityMode() + : Context.getLangOpts().getTypeVisibilityMode(); + LV.mergeVisibility(globalVisibility, /*explicit*/ false); + + // If we're paying attention to global visibility, apply + // -finline-visibility-hidden if this is an inline method. + if (useInlineVisibilityHidden(D)) + LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false); + } + } + + // C++ [basic.link]p4: + + // A name having namespace scope that has not been given internal linkage + // above and that is the name of + // [...bullets...] + // has its linkage determined as follows: + // - if the enclosing namespace has internal linkage, the name has + // internal linkage; [handled above] + // - otherwise, if the declaration of the name is attached to a named + // module and is not exported, the name has module linkage; + // - otherwise, the name has external linkage. + // LV is currently set up to handle the last two bullets. + // + // The bullets are: + + // - a variable; or + if (const auto *Var = dyn_cast<VarDecl>(D)) { + // GCC applies the following optimization to variables and static + // data members, but not to functions: + // + // Modify the variable's LV by the LV of its type unless this is + // C or extern "C". This follows from [basic.link]p9: + // A type without linkage shall not be used as the type of a + // variable or function with external linkage unless + // - the entity has C language linkage, or + // - the entity is declared within an unnamed namespace, or + // - the entity is not used or is defined in the same + // translation unit. + // and [basic.link]p10: + // ...the types specified by all declarations referring to a + // given variable or function shall be identical... + // C does not have an equivalent rule. + // + // Ignore this if we've got an explicit attribute; the user + // probably knows what they're doing. + // + // Note that we don't want to make the variable non-external + // because of this, but unique-external linkage suits us. + if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) && + !IgnoreVarTypeLinkage) { + LinkageInfo TypeLV = getLVForType(*Var->getType(), computation); + if (!isExternallyVisible(TypeLV.getLinkage())) + return LinkageInfo::uniqueExternal(); + if (!LV.isVisibilityExplicit()) + LV.mergeVisibility(TypeLV); + } + + if (Var->getStorageClass() == SC_PrivateExtern) + LV.mergeVisibility(HiddenVisibility, true); + + // Note that Sema::MergeVarDecl already takes care of implementing + // C99 6.2.2p4 and propagating the visibility attribute, so we don't have + // to do it here. + + // As per function and class template specializations (below), + // consider LV for the template and template arguments. We're at file + // scope, so we do not need to worry about nested specializations. + if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(Var)) { + mergeTemplateLV(LV, spec, computation); + } + + // - a function; or + } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) { + // In theory, we can modify the function's LV by the LV of its + // type unless it has C linkage (see comment above about variables + // for justification). In practice, GCC doesn't do this, so it's + // just too painful to make work. + + if (Function->getStorageClass() == SC_PrivateExtern) + LV.mergeVisibility(HiddenVisibility, true); + + // Note that Sema::MergeCompatibleFunctionDecls already takes care of + // merging storage classes and visibility attributes, so we don't have to + // look at previous decls in here. + + // In C++, then if the type of the function uses a type with + // unique-external linkage, it's not legally usable from outside + // this translation unit. However, we should use the C linkage + // rules instead for extern "C" declarations. + if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) { + // Only look at the type-as-written. Otherwise, deducing the return type + // of a function could change its linkage. + QualType TypeAsWritten = Function->getType(); + if (TypeSourceInfo *TSI = Function->getTypeSourceInfo()) + TypeAsWritten = TSI->getType(); + if (!isExternallyVisible(TypeAsWritten->getLinkage())) + return LinkageInfo::uniqueExternal(); + } + + // Consider LV from the template and the template arguments. + // We're at file scope, so we do not need to worry about nested + // specializations. + if (FunctionTemplateSpecializationInfo *specInfo + = Function->getTemplateSpecializationInfo()) { + mergeTemplateLV(LV, Function, specInfo, computation); + } + + // - a named class (Clause 9), or an unnamed class defined in a + // typedef declaration in which the class has the typedef name + // for linkage purposes (7.1.3); or + // - a named enumeration (7.2), or an unnamed enumeration + // defined in a typedef declaration in which the enumeration + // has the typedef name for linkage purposes (7.1.3); or + } else if (const auto *Tag = dyn_cast<TagDecl>(D)) { + // Unnamed tags have no linkage. + if (!Tag->hasNameForLinkage()) + return LinkageInfo::none(); + + // If this is a class template specialization, consider the + // linkage of the template and template arguments. We're at file + // scope, so we do not need to worry about nested specializations. + if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) { + mergeTemplateLV(LV, spec, computation); + } + + // FIXME: This is not part of the C++ standard any more. + // - an enumerator belonging to an enumeration with external linkage; or + } else if (isa<EnumConstantDecl>(D)) { + LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), + computation); + if (!isExternalFormalLinkage(EnumLV.getLinkage())) + return LinkageInfo::none(); + LV.merge(EnumLV); + + // - a template + } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) { + bool considerVisibility = !hasExplicitVisibilityAlready(computation); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + // An unnamed namespace or a namespace declared directly or indirectly + // within an unnamed namespace has internal linkage. All other namespaces + // have external linkage. + // + // We handled names in anonymous namespaces above. + } else if (isa<NamespaceDecl>(D)) { + return LV; + + // By extension, we assign external linkage to Objective-C + // interfaces. + } else if (isa<ObjCInterfaceDecl>(D)) { + // fallout + + } else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) { + // A typedef declaration has linkage if it gives a type a name for + // linkage purposes. + if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) + return LinkageInfo::none(); + + } else if (isa<MSGuidDecl>(D)) { + // A GUID behaves like an inline variable with external linkage. Fall + // through. + + // Everything not covered here has no linkage. + } else { + return LinkageInfo::none(); + } + + // If we ended up with non-externally-visible linkage, visibility should + // always be default. + if (!isExternallyVisible(LV.getLinkage())) + return LinkageInfo(LV.getLinkage(), DefaultVisibility, false); + + // Mark the symbols as hidden when compiling for the device. + if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice) + LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false); + + return LV; +} + +LinkageInfo +LinkageComputer::getLVForClassMember(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage) { + // Only certain class members have linkage. Note that fields don't + // really have linkage, but it's convenient to say they do for the + // purposes of calculating linkage of pointer-to-data-member + // template arguments. + // + // Templates also don't officially have linkage, but since we ignore + // the C++ standard and look at template arguments when determining + // linkage and visibility of a template specialization, we might hit + // a template template argument that way. If we do, we need to + // consider its linkage. + if (!(isa<CXXMethodDecl>(D) || + isa<VarDecl>(D) || + isa<FieldDecl>(D) || + isa<IndirectFieldDecl>(D) || + isa<TagDecl>(D) || + isa<TemplateDecl>(D))) + return LinkageInfo::none(); + + LinkageInfo LV; + + // If we have an explicit visibility attribute, merge that in. + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) + LV.mergeVisibility(*Vis, true); + // If we're paying attention to global visibility, apply + // -finline-visibility-hidden if this is an inline method. + // + // Note that we do this before merging information about + // the class visibility. + if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D)) + LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false); + } + + // If this class member has an explicit visibility attribute, the only + // thing that can change its visibility is the template arguments, so + // only look for them when processing the class. + LVComputationKind classComputation = computation; + if (LV.isVisibilityExplicit()) + classComputation = withExplicitVisibilityAlready(computation); + + LinkageInfo classLV = + getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation); + // The member has the same linkage as the class. If that's not externally + // visible, we don't need to compute anything about the linkage. + // FIXME: If we're only computing linkage, can we bail out here? + if (!isExternallyVisible(classLV.getLinkage())) + return classLV; + + + // Otherwise, don't merge in classLV yet, because in certain cases + // we need to completely ignore the visibility from it. + + // Specifically, if this decl exists and has an explicit attribute. + const NamedDecl *explicitSpecSuppressor = nullptr; + + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { + // Only look at the type-as-written. Otherwise, deducing the return type + // of a function could change its linkage. + QualType TypeAsWritten = MD->getType(); + if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) + TypeAsWritten = TSI->getType(); + if (!isExternallyVisible(TypeAsWritten->getLinkage())) + return LinkageInfo::uniqueExternal(); + + // If this is a method template specialization, use the linkage for + // the template parameters and arguments. + if (FunctionTemplateSpecializationInfo *spec + = MD->getTemplateSpecializationInfo()) { + mergeTemplateLV(LV, MD, spec, computation); + if (spec->isExplicitSpecialization()) { + explicitSpecSuppressor = MD; + } else if (isExplicitMemberSpecialization(spec->getTemplate())) { + explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl(); + } + } else if (isExplicitMemberSpecialization(MD)) { + explicitSpecSuppressor = MD; + } + + } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { + if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + mergeTemplateLV(LV, spec, computation); + if (spec->isExplicitSpecialization()) { + explicitSpecSuppressor = spec; + } else { + const ClassTemplateDecl *temp = spec->getSpecializedTemplate(); + if (isExplicitMemberSpecialization(temp)) { + explicitSpecSuppressor = temp->getTemplatedDecl(); + } + } + } else if (isExplicitMemberSpecialization(RD)) { + explicitSpecSuppressor = RD; + } + + // Static data members. + } else if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD)) + mergeTemplateLV(LV, spec, computation); + + // Modify the variable's linkage by its type, but ignore the + // type's visibility unless it's a definition. + if (!IgnoreVarTypeLinkage) { + LinkageInfo typeLV = getLVForType(*VD->getType(), computation); + // FIXME: If the type's linkage is not externally visible, we can + // give this static data member UniqueExternalLinkage. + if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit()) + LV.mergeVisibility(typeLV); + LV.mergeExternalVisibility(typeLV); + } + + if (isExplicitMemberSpecialization(VD)) { + explicitSpecSuppressor = VD; + } + + // Template members. + } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) { + bool considerVisibility = + (!LV.isVisibilityExplicit() && + !classLV.isVisibilityExplicit() && + !hasExplicitVisibilityAlready(computation)); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, considerVisibility); + + if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) { + if (isExplicitMemberSpecialization(redeclTemp)) { + explicitSpecSuppressor = temp->getTemplatedDecl(); + } + } + } + + // We should never be looking for an attribute directly on a template. + assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor)); + + // If this member is an explicit member specialization, and it has + // an explicit attribute, ignore visibility from the parent. + bool considerClassVisibility = true; + if (explicitSpecSuppressor && + // optimization: hasDVA() is true only with explicit visibility. + LV.isVisibilityExplicit() && + classLV.getVisibility() != DefaultVisibility && + hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) { + considerClassVisibility = false; + } + + // Finally, merge in information from the class. + LV.mergeMaybeWithVisibility(classLV, considerClassVisibility); + return LV; +} + +void NamedDecl::anchor() {} + +bool NamedDecl::isLinkageValid() const { + if (!hasCachedLinkage()) + return true; + + Linkage L = LinkageComputer{} + .computeLVForDecl(this, LVComputationKind::forLinkageOnly()) + .getLinkage(); + return L == getCachedLinkage(); +} + +ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const { + StringRef name = getName(); + if (name.empty()) return SFF_None; + + if (name.front() == 'C') + if (name == "CFStringCreateWithFormat" || + name == "CFStringCreateWithFormatAndArguments" || + name == "CFStringAppendFormat" || + name == "CFStringAppendFormatAndArguments") + return SFF_CFString; + return SFF_None; +} + +Linkage NamedDecl::getLinkageInternal() const { + // We don't care about visibility here, so ask for the cheapest + // possible visibility analysis. + return LinkageComputer{} + .getLVForDecl(this, LVComputationKind::forLinkageOnly()) + .getLinkage(); +} + +LinkageInfo NamedDecl::getLinkageAndVisibility() const { + return LinkageComputer{}.getDeclLinkageAndVisibility(this); +} + +static Optional<Visibility> +getExplicitVisibilityAux(const NamedDecl *ND, + NamedDecl::ExplicitVisibilityKind kind, + bool IsMostRecent) { + assert(!IsMostRecent || ND == ND->getMostRecentDecl()); + + // Check the declaration itself first. + if (Optional<Visibility> V = getVisibilityOf(ND, kind)) + return V; + + // If this is a member class of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) { + CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom, kind); + } + + // If there wasn't explicit visibility there, and this is a + // specialization of a class template, check for visibility + // on the pattern. + if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + // Walk all the template decl till this point to see if there are + // explicit visibility attributes. + const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl(); + while (TD != nullptr) { + auto Vis = getVisibilityOf(TD, kind); + if (Vis != None) + return Vis; + TD = TD->getPreviousDecl(); + } + return None; + } + + // Use the most recent declaration. + if (!IsMostRecent && !isa<NamespaceDecl>(ND)) { + const NamedDecl *MostRecent = ND->getMostRecentDecl(); + if (MostRecent != ND) + return getExplicitVisibilityAux(MostRecent, kind, true); + } + + if (const auto *Var = dyn_cast<VarDecl>(ND)) { + if (Var->isStaticDataMember()) { + VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom, kind); + } + + if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var)) + return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(), + kind); + + return None; + } + // Also handle function template specializations. + if (const auto *fn = dyn_cast<FunctionDecl>(ND)) { + // If the function is a specialization of a template with an + // explicit visibility attribute, use that. + if (FunctionTemplateSpecializationInfo *templateInfo + = fn->getTemplateSpecializationInfo()) + return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(), + kind); + + // If the function is a member of a specialization of a class template + // and the corresponding decl has explicit visibility, use that. + FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction(); + if (InstantiatedFrom) + return getVisibilityOf(InstantiatedFrom, kind); + + return None; + } + + // The visibility of a template is stored in the templated decl. + if (const auto *TD = dyn_cast<TemplateDecl>(ND)) + return getVisibilityOf(TD->getTemplatedDecl(), kind); + + return None; +} + +Optional<Visibility> +NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const { + return getExplicitVisibilityAux(this, kind, false); +} + +LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC, + Decl *ContextDecl, + LVComputationKind computation) { + // This lambda has its linkage/visibility determined by its owner. + const NamedDecl *Owner; + if (!ContextDecl) + Owner = dyn_cast<NamedDecl>(DC); + else if (isa<ParmVarDecl>(ContextDecl)) + Owner = + dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext()); + else + Owner = cast<NamedDecl>(ContextDecl); + + if (!Owner) + return LinkageInfo::none(); + + // If the owner has a deduced type, we need to skip querying the linkage and + // visibility of that type, because it might involve this closure type. The + // only effect of this is that we might give a lambda VisibleNoLinkage rather + // than NoLinkage when we don't strictly need to, which is benign. + auto *VD = dyn_cast<VarDecl>(Owner); + LinkageInfo OwnerLV = + VD && VD->getType()->getContainedDeducedType() + ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true) + : getLVForDecl(Owner, computation); + + // A lambda never formally has linkage. But if the owner is externally + // visible, then the lambda is too. We apply the same rules to blocks. + if (!isExternallyVisible(OwnerLV.getLinkage())) + return LinkageInfo::none(); + return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(), + OwnerLV.isVisibilityExplicit()); +} + +LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D, + LVComputationKind computation) { + if (const auto *Function = dyn_cast<FunctionDecl>(D)) { + if (Function->isInAnonymousNamespace() && + !isFirstInExternCContext(Function)) + return getInternalLinkageFor(Function); + + // This is a "void f();" which got merged with a file static. + if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) + return getInternalLinkageFor(Function); + + LinkageInfo LV; + if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = + getExplicitVisibility(Function, computation)) + LV.mergeVisibility(*Vis, true); + } + + // Note that Sema::MergeCompatibleFunctionDecls already takes care of + // merging storage classes and visibility attributes, so we don't have to + // look at previous decls in here. + + return LV; + } + + if (const auto *Var = dyn_cast<VarDecl>(D)) { + if (Var->hasExternalStorage()) { + if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var)) + return getInternalLinkageFor(Var); + + LinkageInfo LV; + if (Var->getStorageClass() == SC_PrivateExtern) + LV.mergeVisibility(HiddenVisibility, true); + else if (!hasExplicitVisibilityAlready(computation)) { + if (Optional<Visibility> Vis = getExplicitVisibility(Var, computation)) + LV.mergeVisibility(*Vis, true); + } + + if (const VarDecl *Prev = Var->getPreviousDecl()) { + LinkageInfo PrevLV = getLVForDecl(Prev, computation); + if (PrevLV.getLinkage()) + LV.setLinkage(PrevLV.getLinkage()); + LV.mergeVisibility(PrevLV); + } + + return LV; + } + + if (!Var->isStaticLocal()) + return LinkageInfo::none(); + } + + ASTContext &Context = D->getASTContext(); + if (!Context.getLangOpts().CPlusPlus) + return LinkageInfo::none(); + + const Decl *OuterD = getOutermostFuncOrBlockContext(D); + if (!OuterD || OuterD->isInvalidDecl()) + return LinkageInfo::none(); + + LinkageInfo LV; + if (const auto *BD = dyn_cast<BlockDecl>(OuterD)) { + if (!BD->getBlockManglingNumber()) + return LinkageInfo::none(); + + LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(), + BD->getBlockManglingContextDecl(), computation); + } else { + const auto *FD = cast<FunctionDecl>(OuterD); + if (!FD->isInlined() && + !isTemplateInstantiation(FD->getTemplateSpecializationKind())) + return LinkageInfo::none(); + + // If a function is hidden by -fvisibility-inlines-hidden option and + // is not explicitly attributed as a hidden function, + // we should not make static local variables in the function hidden. + LV = getLVForDecl(FD, computation); + if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) && + !LV.isVisibilityExplicit() && + !Context.getLangOpts().VisibilityInlinesHiddenStaticLocalVar) { + assert(cast<VarDecl>(D)->isStaticLocal()); + // If this was an implicitly hidden inline method, check again for + // explicit visibility on the parent class, and use that for static locals + // if present. + if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) + LV = getLVForDecl(MD->getParent(), computation); + if (!LV.isVisibilityExplicit()) { + Visibility globalVisibility = + computation.isValueVisibility() + ? Context.getLangOpts().getValueVisibilityMode() + : Context.getLangOpts().getTypeVisibilityMode(); + return LinkageInfo(VisibleNoLinkage, globalVisibility, + /*visibilityExplicit=*/false); + } + } + } + if (!isExternallyVisible(LV.getLinkage())) + return LinkageInfo::none(); + return LinkageInfo(VisibleNoLinkage, LV.getVisibility(), + LV.isVisibilityExplicit()); +} + +LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D, + LVComputationKind computation, + bool IgnoreVarTypeLinkage) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return getInternalLinkageFor(D); + + // Objective-C: treat all Objective-C declarations as having external + // linkage. + switch (D->getKind()) { + default: + break; + + // Per C++ [basic.link]p2, only the names of objects, references, + // functions, types, templates, namespaces, and values ever have linkage. + // + // Note that the name of a typedef, namespace alias, using declaration, + // and so on are not the name of the corresponding type, namespace, or + // declaration, so they do *not* have linkage. + case Decl::ImplicitParam: + case Decl::Label: + case Decl::NamespaceAlias: + case Decl::ParmVar: + case Decl::Using: + case Decl::UsingShadow: + case Decl::UsingDirective: + return LinkageInfo::none(); + + case Decl::EnumConstant: + // C++ [basic.link]p4: an enumerator has the linkage of its enumeration. + if (D->getASTContext().getLangOpts().CPlusPlus) + return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation); + return LinkageInfo::visible_none(); + + case Decl::Typedef: + case Decl::TypeAlias: + // A typedef declaration has linkage if it gives a type a name for + // linkage purposes. + if (!cast<TypedefNameDecl>(D) + ->getAnonDeclWithTypedefName(/*AnyRedecl*/true)) + return LinkageInfo::none(); + break; + + case Decl::TemplateTemplateParm: // count these as external + case Decl::NonTypeTemplateParm: + case Decl::ObjCAtDefsField: + case Decl::ObjCCategory: + case Decl::ObjCCategoryImpl: + case Decl::ObjCCompatibleAlias: + case Decl::ObjCImplementation: + case Decl::ObjCMethod: + case Decl::ObjCProperty: + case Decl::ObjCPropertyImpl: + case Decl::ObjCProtocol: + return getExternalLinkageFor(D); + + case Decl::CXXRecord: { + const auto *Record = cast<CXXRecordDecl>(D); + if (Record->isLambda()) { + if (Record->hasKnownLambdaInternalLinkage() || + !Record->getLambdaManglingNumber()) { + // This lambda has no mangling number, so it's internal. + return getInternalLinkageFor(D); + } + + return getLVForClosure( + Record->getDeclContext()->getRedeclContext(), + Record->getLambdaContextDecl(), computation); + } + + break; + } + + case Decl::TemplateParamObject: { + // The template parameter object can be referenced from anywhere its type + // and value can be referenced. + auto *TPO = cast<TemplateParamObjectDecl>(D); + LinkageInfo LV = getLVForType(*TPO->getType(), computation); + LV.merge(getLVForValue(TPO->getValue(), computation)); + return LV; + } + } + + // Handle linkage for namespace-scope names. + if (D->getDeclContext()->getRedeclContext()->isFileContext()) + return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage); + + // C++ [basic.link]p5: + // In addition, a member function, static data member, a named + // class or enumeration of class scope, or an unnamed class or + // enumeration defined in a class-scope typedef declaration such + // that the class or enumeration has the typedef name for linkage + // purposes (7.1.3), has external linkage if the name of the class + // has external linkage. + if (D->getDeclContext()->isRecord()) + return getLVForClassMember(D, computation, IgnoreVarTypeLinkage); + + // C++ [basic.link]p6: + // The name of a function declared in block scope and the name of + // an object declared by a block scope extern declaration have + // linkage. If there is a visible declaration of an entity with + // linkage having the same name and type, ignoring entities + // declared outside the innermost enclosing namespace scope, the + // block scope declaration declares that same entity and receives + // the linkage of the previous declaration. If there is more than + // one such matching entity, the program is ill-formed. Otherwise, + // if no matching entity is found, the block scope entity receives + // external linkage. + if (D->getDeclContext()->isFunctionOrMethod()) + return getLVForLocalDecl(D, computation); + + // C++ [basic.link]p6: + // Names not covered by these rules have no linkage. + return LinkageInfo::none(); +} + +/// getLVForDecl - Get the linkage and visibility for the given declaration. +LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D, + LVComputationKind computation) { + // Internal_linkage attribute overrides other considerations. + if (D->hasAttr<InternalLinkageAttr>()) + return getInternalLinkageFor(D); + + if (computation.IgnoreAllVisibility && D->hasCachedLinkage()) + return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); + + if (llvm::Optional<LinkageInfo> LI = lookup(D, computation)) + return *LI; + + LinkageInfo LV = computeLVForDecl(D, computation); + if (D->hasCachedLinkage()) + assert(D->getCachedLinkage() == LV.getLinkage()); + + D->setCachedLinkage(LV.getLinkage()); + cache(D, computation, LV); + +#ifndef NDEBUG + // In C (because of gnu inline) and in c++ with microsoft extensions an + // static can follow an extern, so we can have two decls with different + // linkages. + const LangOptions &Opts = D->getASTContext().getLangOpts(); + if (!Opts.CPlusPlus || Opts.MicrosoftExt) + return LV; + + // We have just computed the linkage for this decl. By induction we know + // that all other computed linkages match, check that the one we just + // computed also does. + NamedDecl *Old = nullptr; + for (auto I : D->redecls()) { + auto *T = cast<NamedDecl>(I); + if (T == D) + continue; + if (!T->isInvalidDecl() && T->hasCachedLinkage()) { + Old = T; + break; + } + } + assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage()); +#endif + + return LV; +} + +LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) { + return getLVForDecl(D, + LVComputationKind(usesTypeVisibility(D) + ? NamedDecl::VisibilityForType + : NamedDecl::VisibilityForValue)); +} + +Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { + Module *M = getOwningModule(); + if (!M) + return nullptr; + + switch (M->Kind) { + case Module::ModuleMapModule: + // Module map modules have no special linkage semantics. + return nullptr; + + case Module::ModuleInterfaceUnit: + return M; + + case Module::GlobalModuleFragment: { + // External linkage declarations in the global module have no owning module + // for linkage purposes. But internal linkage declarations in the global + // module fragment of a particular module are owned by that module for + // linkage purposes. + if (IgnoreLinkage) + return nullptr; + bool InternalLinkage; + if (auto *ND = dyn_cast<NamedDecl>(this)) + InternalLinkage = !ND->hasExternalFormalLinkage(); + else { + auto *NSD = dyn_cast<NamespaceDecl>(this); + InternalLinkage = (NSD && NSD->isAnonymousNamespace()) || + isInAnonymousNamespace(); + } + return InternalLinkage ? M->Parent : nullptr; + } + + case Module::PrivateModuleFragment: + // The private module fragment is part of its containing module for linkage + // purposes. + return M->Parent; + } + + llvm_unreachable("unknown module kind"); +} + +void NamedDecl::printName(raw_ostream &os) const { + os << Name; +} + +std::string NamedDecl::getQualifiedNameAsString() const { + std::string QualName; + llvm::raw_string_ostream OS(QualName); + printQualifiedName(OS, getASTContext().getPrintingPolicy()); + return OS.str(); +} + +void NamedDecl::printQualifiedName(raw_ostream &OS) const { + printQualifiedName(OS, getASTContext().getPrintingPolicy()); +} + +void NamedDecl::printQualifiedName(raw_ostream &OS, + const PrintingPolicy &P) const { + if (getDeclContext()->isFunctionOrMethod()) { + // We do not print '(anonymous)' for function parameters without name. + printName(OS); + return; + } + printNestedNameSpecifier(OS, P); + if (getDeclName()) + OS << *this; + else { + // Give the printName override a chance to pick a different name before we + // fall back to "(anonymous)". + SmallString<64> NameBuffer; + llvm::raw_svector_ostream NameOS(NameBuffer); + printName(NameOS); + if (NameBuffer.empty()) + OS << "(anonymous)"; + else + OS << NameBuffer; + } +} + +void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const { + printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy()); +} + +void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, + const PrintingPolicy &P) const { + const DeclContext *Ctx = getDeclContext(); + + // For ObjC methods and properties, look through categories and use the + // interface as context. + if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) { + if (auto *ID = MD->getClassInterface()) + Ctx = ID; + } else if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) { + if (auto *MD = PD->getGetterMethodDecl()) + if (auto *ID = MD->getClassInterface()) + Ctx = ID; + } else if (auto *ID = dyn_cast<ObjCIvarDecl>(this)) { + if (auto *CI = ID->getContainingInterface()) + Ctx = CI; + } + + if (Ctx->isFunctionOrMethod()) + return; + + using ContextsTy = SmallVector<const DeclContext *, 8>; + ContextsTy Contexts; + + // Collect named contexts. + DeclarationName NameInScope = getDeclName(); + for (; Ctx; Ctx = Ctx->getParent()) { + // Suppress anonymous namespace if requested. + if (P.SuppressUnwrittenScope && isa<NamespaceDecl>(Ctx) && + cast<NamespaceDecl>(Ctx)->isAnonymousNamespace()) + continue; + + // Suppress inline namespace if it doesn't make the result ambiguous. + if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope && + Ctx->lookup(NameInScope).size() == + Ctx->getParent()->lookup(NameInScope).size()) + continue; + + // Skip non-named contexts such as linkage specifications and ExportDecls. + const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx); + if (!ND) + continue; + + Contexts.push_back(Ctx); + NameInScope = ND->getDeclName(); + } + + for (unsigned I = Contexts.size(); I != 0; --I) { + const DeclContext *DC = Contexts[I - 1]; + if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) { + OS << Spec->getName(); + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + printTemplateArgumentList( + OS, TemplateArgs.asArray(), P, + Spec->getSpecializedTemplate()->getTemplateParameters()); + } else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) { + if (ND->isAnonymousNamespace()) { + OS << (P.MSVCFormatting ? "`anonymous namespace\'" + : "(anonymous namespace)"); + } + else + OS << *ND; + } else if (const auto *RD = dyn_cast<RecordDecl>(DC)) { + if (!RD->getIdentifier()) + OS << "(anonymous " << RD->getKindName() << ')'; + else + OS << *RD; + } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) { + const FunctionProtoType *FT = nullptr; + if (FD->hasWrittenPrototype()) + FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>()); + + OS << *FD << '('; + if (FT) { + unsigned NumParams = FD->getNumParams(); + for (unsigned i = 0; i < NumParams; ++i) { + if (i) + OS << ", "; + OS << FD->getParamDecl(i)->getType().stream(P); + } + + if (FT->isVariadic()) { + if (NumParams > 0) + OS << ", "; + OS << "..."; + } + } + OS << ')'; + } else if (const auto *ED = dyn_cast<EnumDecl>(DC)) { + // C++ [dcl.enum]p10: Each enum-name and each unscoped + // enumerator is declared in the scope that immediately contains + // the enum-specifier. Each scoped enumerator is declared in the + // scope of the enumeration. + // For the case of unscoped enumerator, do not include in the qualified + // name any information about its enum enclosing scope, as its visibility + // is global. + if (ED->isScoped()) + OS << *ED; + else + continue; + } else { + OS << *cast<NamedDecl>(DC); + } + OS << "::"; + } +} + +void NamedDecl::getNameForDiagnostic(raw_ostream &OS, + const PrintingPolicy &Policy, + bool Qualified) const { + if (Qualified) + printQualifiedName(OS, Policy); + else + printName(OS); +} + +template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) { + return true; +} +static bool isRedeclarableImpl(...) { return false; } +static bool isRedeclarable(Decl::Kind K) { + switch (K) { +#define DECL(Type, Base) \ + case Decl::Type: \ + return isRedeclarableImpl((Type##Decl *)nullptr); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + } + llvm_unreachable("unknown decl kind"); +} + +bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const { + assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch"); + + // Never replace one imported declaration with another; we need both results + // when re-exporting. + if (OldD->isFromASTFile() && isFromASTFile()) + return false; + + // A kind mismatch implies that the declaration is not replaced. + if (OldD->getKind() != getKind()) + return false; + + // For method declarations, we never replace. (Why?) + if (isa<ObjCMethodDecl>(this)) + return false; + + // For parameters, pick the newer one. This is either an error or (in + // Objective-C) permitted as an extension. + if (isa<ParmVarDecl>(this)) + return true; + + // Inline namespaces can give us two declarations with the same + // name and kind in the same scope but different contexts; we should + // keep both declarations in this case. + if (!this->getDeclContext()->getRedeclContext()->Equals( + OldD->getDeclContext()->getRedeclContext())) + return false; + + // Using declarations can be replaced if they import the same name from the + // same context. + if (auto *UD = dyn_cast<UsingDecl>(this)) { + ASTContext &Context = getASTContext(); + return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) == + Context.getCanonicalNestedNameSpecifier( + cast<UsingDecl>(OldD)->getQualifier()); + } + if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) { + ASTContext &Context = getASTContext(); + return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) == + Context.getCanonicalNestedNameSpecifier( + cast<UnresolvedUsingValueDecl>(OldD)->getQualifier()); + } + + if (isRedeclarable(getKind())) { + if (getCanonicalDecl() != OldD->getCanonicalDecl()) + return false; + + if (IsKnownNewer) + return true; + + // Check whether this is actually newer than OldD. We want to keep the + // newer declaration. This loop will usually only iterate once, because + // OldD is usually the previous declaration. + for (auto D : redecls()) { + if (D == OldD) + break; + + // If we reach the canonical declaration, then OldD is not actually older + // than this one. + // + // FIXME: In this case, we should not add this decl to the lookup table. + if (D->isCanonicalDecl()) + return false; + } + + // It's a newer declaration of the same kind of declaration in the same + // scope: we want this decl instead of the existing one. + return true; + } + + // In all other cases, we need to keep both declarations in case they have + // different visibility. Any attempt to use the name will result in an + // ambiguity if more than one is visible. + return false; +} + +bool NamedDecl::hasLinkage() const { + return getFormalLinkage() != NoLinkage; +} + +NamedDecl *NamedDecl::getUnderlyingDeclImpl() { + NamedDecl *ND = this; + while (auto *UD = dyn_cast<UsingShadowDecl>(ND)) + ND = UD->getTargetDecl(); + + if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND)) + return AD->getClassInterface(); + + if (auto *AD = dyn_cast<NamespaceAliasDecl>(ND)) + return AD->getNamespace(); + + return ND; +} + +bool NamedDecl::isCXXInstanceMember() const { + if (!isCXXClassMember()) + return false; + + const NamedDecl *D = this; + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D)) + return true; + if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction())) + return MD->isInstance(); + return false; +} + +//===----------------------------------------------------------------------===// +// DeclaratorDecl Implementation +//===----------------------------------------------------------------------===// + +template <typename DeclT> +static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) { + if (decl->getNumTemplateParameterLists() > 0) + return decl->getTemplateParameterList(0)->getTemplateLoc(); + return decl->getInnerLocStart(); +} + +SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { + TypeSourceInfo *TSI = getTypeSourceInfo(); + if (TSI) return TSI->getTypeLoc().getBeginLoc(); + return SourceLocation(); +} + +SourceLocation DeclaratorDecl::getTypeSpecEndLoc() const { + TypeSourceInfo *TSI = getTypeSourceInfo(); + if (TSI) return TSI->getTypeLoc().getEndLoc(); + return SourceLocation(); +} + +void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { + if (QualifierLoc) { + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) { + // Save (non-extended) type source info pointer. + auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); + // Allocate external info struct. + DeclInfo = new (getASTContext()) ExtInfo; + // Restore savedTInfo into (extended) decl info. + getExtInfo()->TInfo = savedTInfo; + } + // Set qualifier info. + getExtInfo()->QualifierLoc = QualifierLoc; + } else if (hasExtInfo()) { + // Here Qualifier == 0, i.e., we are removing the qualifier (if any). + getExtInfo()->QualifierLoc = QualifierLoc; + } +} + +void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) { + assert(TrailingRequiresClause); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) { + // Save (non-extended) type source info pointer. + auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); + // Allocate external info struct. + DeclInfo = new (getASTContext()) ExtInfo; + // Restore savedTInfo into (extended) decl info. + getExtInfo()->TInfo = savedTInfo; + } + // Set requires clause info. + getExtInfo()->TrailingRequiresClause = TrailingRequiresClause; +} + +void DeclaratorDecl::setTemplateParameterListsInfo( + ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { + assert(!TPLists.empty()); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) { + // Save (non-extended) type source info pointer. + auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); + // Allocate external info struct. + DeclInfo = new (getASTContext()) ExtInfo; + // Restore savedTInfo into (extended) decl info. + getExtInfo()->TInfo = savedTInfo; + } + // Set the template parameter lists info. + getExtInfo()->setTemplateParameterListsInfo(Context, TPLists); +} + +SourceLocation DeclaratorDecl::getOuterLocStart() const { + return getTemplateOrInnerLocStart(this); +} + +// Helper function: returns true if QT is or contains a type +// having a postfix component. +static bool typeIsPostfix(QualType QT) { + while (true) { + const Type* T = QT.getTypePtr(); + switch (T->getTypeClass()) { + default: + return false; + case Type::Pointer: + QT = cast<PointerType>(T)->getPointeeType(); + break; + case Type::BlockPointer: + QT = cast<BlockPointerType>(T)->getPointeeType(); + break; + case Type::MemberPointer: + QT = cast<MemberPointerType>(T)->getPointeeType(); + break; + case Type::LValueReference: + case Type::RValueReference: + QT = cast<ReferenceType>(T)->getPointeeType(); + break; + case Type::PackExpansion: + QT = cast<PackExpansionType>(T)->getPattern(); + break; + case Type::Paren: + case Type::ConstantArray: + case Type::DependentSizedArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::FunctionProto: + case Type::FunctionNoProto: + return true; + } + } +} + +SourceRange DeclaratorDecl::getSourceRange() const { + SourceLocation RangeEnd = getLocation(); + if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { + // If the declaration has no name or the type extends past the name take the + // end location of the type. + if (!getDeclName() || typeIsPostfix(TInfo->getType())) + RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); + } + return SourceRange(getOuterLocStart(), RangeEnd); +} + +void QualifierInfo::setTemplateParameterListsInfo( + ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { + // Free previous template parameters (if any). + if (NumTemplParamLists > 0) { + Context.Deallocate(TemplParamLists); + TemplParamLists = nullptr; + NumTemplParamLists = 0; + } + // Set info on matched template parameter lists (if any). + if (!TPLists.empty()) { + TemplParamLists = new (Context) TemplateParameterList *[TPLists.size()]; + NumTemplParamLists = TPLists.size(); + std::copy(TPLists.begin(), TPLists.end(), TemplParamLists); + } +} + +//===----------------------------------------------------------------------===// +// VarDecl Implementation +//===----------------------------------------------------------------------===// + +const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { + switch (SC) { + case SC_None: break; + case SC_Auto: return "auto"; + case SC_Extern: return "extern"; + case SC_PrivateExtern: return "__private_extern__"; + case SC_Register: return "register"; + case SC_Static: return "static"; + } + + llvm_unreachable("Invalid storage class"); +} + +VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass SC) + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), + redeclarable_base(C) { + static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned), + "VarDeclBitfields too large!"); + static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned), + "ParmVarDeclBitfields too large!"); + static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned), + "NonParmVarDeclBitfields too large!"); + AllBits = 0; + VarDeclBits.SClass = SC; + // Everything else is implicitly initialized to false. +} + +VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartL, SourceLocation IdL, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass S) { + return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S); +} + +VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) + VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr, + QualType(), nullptr, SC_None); +} + +void VarDecl::setStorageClass(StorageClass SC) { + assert(isLegalForVariable(SC)); + VarDeclBits.SClass = SC; +} + +VarDecl::TLSKind VarDecl::getTLSKind() const { + switch (VarDeclBits.TSCSpec) { + case TSCS_unspecified: + if (!hasAttr<ThreadAttr>() && + !(getASTContext().getLangOpts().OpenMPUseTLS && + getASTContext().getTargetInfo().isTLSSupported() && + hasAttr<OMPThreadPrivateDeclAttr>())) + return TLS_None; + return ((getASTContext().getLangOpts().isCompatibleWithMSVC( + LangOptions::MSVC2015)) || + hasAttr<OMPThreadPrivateDeclAttr>()) + ? TLS_Dynamic + : TLS_Static; + case TSCS___thread: // Fall through. + case TSCS__Thread_local: + return TLS_Static; + case TSCS_thread_local: + return TLS_Dynamic; + } + llvm_unreachable("Unknown thread storage class specifier!"); +} + +SourceRange VarDecl::getSourceRange() const { + if (const Expr *Init = getInit()) { + SourceLocation InitEnd = Init->getEndLoc(); + // If Init is implicit, ignore its source range and fallback on + // DeclaratorDecl::getSourceRange() to handle postfix elements. + if (InitEnd.isValid() && InitEnd != getLocation()) + return SourceRange(getOuterLocStart(), InitEnd); + } + return DeclaratorDecl::getSourceRange(); +} + +template<typename T> +static LanguageLinkage getDeclLanguageLinkage(const T &D) { + // C++ [dcl.link]p1: All function types, function names with external linkage, + // and variable names with external linkage have a language linkage. + if (!D.hasExternalFormalLinkage()) + return NoLanguageLinkage; + + // Language linkage is a C++ concept, but saying that everything else in C has + // C language linkage fits the implementation nicely. + ASTContext &Context = D.getASTContext(); + if (!Context.getLangOpts().CPlusPlus) + return CLanguageLinkage; + + // C++ [dcl.link]p4: A C language linkage is ignored in determining the + // language linkage of the names of class members and the function type of + // class member functions. + const DeclContext *DC = D.getDeclContext(); + if (DC->isRecord()) + return CXXLanguageLinkage; + + // If the first decl is in an extern "C" context, any other redeclaration + // will have C language linkage. If the first one is not in an extern "C" + // context, we would have reported an error for any other decl being in one. + if (isFirstInExternCContext(&D)) + return CLanguageLinkage; + return CXXLanguageLinkage; +} + +template<typename T> +static bool isDeclExternC(const T &D) { + // Since the context is ignored for class members, they can only have C++ + // language linkage or no language linkage. + const DeclContext *DC = D.getDeclContext(); + if (DC->isRecord()) { + assert(D.getASTContext().getLangOpts().CPlusPlus); + return false; + } + + return D.getLanguageLinkage() == CLanguageLinkage; +} + +LanguageLinkage VarDecl::getLanguageLinkage() const { + return getDeclLanguageLinkage(*this); +} + +bool VarDecl::isExternC() const { + return isDeclExternC(*this); +} + +bool VarDecl::isInExternCContext() const { + return getLexicalDeclContext()->isExternCContext(); +} + +bool VarDecl::isInExternCXXContext() const { + return getLexicalDeclContext()->isExternCXXContext(); +} + +VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); } + +VarDecl::DefinitionKind +VarDecl::isThisDeclarationADefinition(ASTContext &C) const { + if (isThisDeclarationADemotedDefinition()) + return DeclarationOnly; + + // C++ [basic.def]p2: + // A declaration is a definition unless [...] it contains the 'extern' + // specifier or a linkage-specification and neither an initializer [...], + // it declares a non-inline static data member in a class declaration [...], + // it declares a static data member outside a class definition and the variable + // was defined within the class with the constexpr specifier [...], + // C++1y [temp.expl.spec]p15: + // An explicit specialization of a static data member or an explicit + // specialization of a static data member template is a definition if the + // declaration includes an initializer; otherwise, it is a declaration. + // + // FIXME: How do you declare (but not define) a partial specialization of + // a static data member template outside the containing class? + if (isStaticDataMember()) { + if (isOutOfLine() && + !(getCanonicalDecl()->isInline() && + getCanonicalDecl()->isConstexpr()) && + (hasInit() || + // If the first declaration is out-of-line, this may be an + // instantiation of an out-of-line partial specialization of a variable + // template for which we have not yet instantiated the initializer. + (getFirstDecl()->isOutOfLine() + ? getTemplateSpecializationKind() == TSK_Undeclared + : getTemplateSpecializationKind() != + TSK_ExplicitSpecialization) || + isa<VarTemplatePartialSpecializationDecl>(this))) + return Definition; + if (!isOutOfLine() && isInline()) + return Definition; + return DeclarationOnly; + } + // C99 6.7p5: + // A definition of an identifier is a declaration for that identifier that + // [...] causes storage to be reserved for that object. + // Note: that applies for all non-file-scope objects. + // C99 6.9.2p1: + // If the declaration of an identifier for an object has file scope and an + // initializer, the declaration is an external definition for the identifier + if (hasInit()) + return Definition; + + if (hasDefiningAttr()) + return Definition; + + if (const auto *SAA = getAttr<SelectAnyAttr>()) + if (!SAA->isInherited()) + return Definition; + + // A variable template specialization (other than a static data member + // template or an explicit specialization) is a declaration until we + // instantiate its initializer. + if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) { + if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization && + !isa<VarTemplatePartialSpecializationDecl>(VTSD) && + !VTSD->IsCompleteDefinition) + return DeclarationOnly; + } + + if (hasExternalStorage()) + return DeclarationOnly; + + // [dcl.link] p7: + // A declaration directly contained in a linkage-specification is treated + // as if it contains the extern specifier for the purpose of determining + // the linkage of the declared name and whether it is a definition. + if (isSingleLineLanguageLinkage(*this)) + return DeclarationOnly; + + // C99 6.9.2p2: + // A declaration of an object that has file scope without an initializer, + // and without a storage class specifier or the scs 'static', constitutes + // a tentative definition. + // No such thing in C++. + if (!C.getLangOpts().CPlusPlus && isFileVarDecl()) + return TentativeDefinition; + + // What's left is (in C, block-scope) declarations without initializers or + // external storage. These are definitions. + return Definition; +} + +VarDecl *VarDecl::getActingDefinition() { + DefinitionKind Kind = isThisDeclarationADefinition(); + if (Kind != TentativeDefinition) + return nullptr; + + VarDecl *LastTentative = nullptr; + VarDecl *First = getFirstDecl(); + for (auto I : First->redecls()) { + Kind = I->isThisDeclarationADefinition(); + if (Kind == Definition) + return nullptr; + if (Kind == TentativeDefinition) + LastTentative = I; + } + return LastTentative; +} + +VarDecl *VarDecl::getDefinition(ASTContext &C) { + VarDecl *First = getFirstDecl(); + for (auto I : First->redecls()) { + if (I->isThisDeclarationADefinition(C) == Definition) + return I; + } + return nullptr; +} + +VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { + DefinitionKind Kind = DeclarationOnly; + + const VarDecl *First = getFirstDecl(); + for (auto I : First->redecls()) { + Kind = std::max(Kind, I->isThisDeclarationADefinition(C)); + if (Kind == Definition) + break; + } + + return Kind; +} + +const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const { + for (auto I : redecls()) { + if (auto Expr = I->getInit()) { + D = I; + return Expr; + } + } + return nullptr; +} + +bool VarDecl::hasInit() const { + if (auto *P = dyn_cast<ParmVarDecl>(this)) + if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg()) + return false; + + return !Init.isNull(); +} + +Expr *VarDecl::getInit() { + if (!hasInit()) + return nullptr; + + if (auto *S = Init.dyn_cast<Stmt *>()) + return cast<Expr>(S); + + return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value); +} + +Stmt **VarDecl::getInitAddress() { + if (auto *ES = Init.dyn_cast<EvaluatedStmt *>()) + return &ES->Value; + + return Init.getAddrOfPtr1(); +} + +VarDecl *VarDecl::getInitializingDeclaration() { + VarDecl *Def = nullptr; + for (auto I : redecls()) { + if (I->hasInit()) + return I; + + if (I->isThisDeclarationADefinition()) { + if (isStaticDataMember()) + return I; + Def = I; + } + } + return Def; +} + +bool VarDecl::isOutOfLine() const { + if (Decl::isOutOfLine()) + return true; + + if (!isStaticDataMember()) + return false; + + // If this static data member was instantiated from a static data member of + // a class template, check whether that static data member was defined + // out-of-line. + if (VarDecl *VD = getInstantiatedFromStaticDataMember()) + return VD->isOutOfLine(); + + return false; +} + +void VarDecl::setInit(Expr *I) { + if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) { + Eval->~EvaluatedStmt(); + getASTContext().Deallocate(Eval); + } + + Init = I; +} + +bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const { + const LangOptions &Lang = C.getLangOpts(); + + // OpenCL permits const integral variables to be used in constant + // expressions, like in C++98. + if (!Lang.CPlusPlus && !Lang.OpenCL) + return false; + + // Function parameters are never usable in constant expressions. + if (isa<ParmVarDecl>(this)) + return false; + + // The values of weak variables are never usable in constant expressions. + if (isWeak()) + return false; + + // In C++11, any variable of reference type can be used in a constant + // expression if it is initialized by a constant expression. + if (Lang.CPlusPlus11 && getType()->isReferenceType()) + return true; + + // Only const objects can be used in constant expressions in C++. C++98 does + // not require the variable to be non-volatile, but we consider this to be a + // defect. + if (!getType().isConstant(C) || getType().isVolatileQualified()) + return false; + + // In C++, const, non-volatile variables of integral or enumeration types + // can be used in constant expressions. + if (getType()->isIntegralOrEnumerationType()) + return true; + + // Additionally, in C++11, non-volatile constexpr variables can be used in + // constant expressions. + return Lang.CPlusPlus11 && isConstexpr(); +} + +bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const { + // C++2a [expr.const]p3: + // A variable is usable in constant expressions after its initializing + // declaration is encountered... + const VarDecl *DefVD = nullptr; + const Expr *Init = getAnyInitializer(DefVD); + if (!Init || Init->isValueDependent() || getType()->isDependentType()) + return false; + // ... if it is a constexpr variable, or it is of reference type or of + // const-qualified integral or enumeration type, ... + if (!DefVD->mightBeUsableInConstantExpressions(Context)) + return false; + // ... and its initializer is a constant initializer. + if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization()) + return false; + // C++98 [expr.const]p1: + // An integral constant-expression can involve only [...] const variables + // or static data members of integral or enumeration types initialized with + // [integer] constant expressions (dcl.init) + if ((Context.getLangOpts().CPlusPlus || Context.getLangOpts().OpenCL) && + !Context.getLangOpts().CPlusPlus11 && !DefVD->hasICEInitializer(Context)) + return false; + return true; +} + +/// Convert the initializer for this declaration to the elaborated EvaluatedStmt +/// form, which contains extra information on the evaluated value of the +/// initializer. +EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const { + auto *Eval = Init.dyn_cast<EvaluatedStmt *>(); + if (!Eval) { + // Note: EvaluatedStmt contains an APValue, which usually holds + // resources not allocated from the ASTContext. We need to do some + // work to avoid leaking those, but we do so in VarDecl::evaluateValue + // where we can detect whether there's anything to clean up or not. + Eval = new (getASTContext()) EvaluatedStmt; + Eval->Value = Init.get<Stmt *>(); + Init = Eval; + } + return Eval; +} + +EvaluatedStmt *VarDecl::getEvaluatedStmt() const { + return Init.dyn_cast<EvaluatedStmt *>(); +} + +APValue *VarDecl::evaluateValue() const { + SmallVector<PartialDiagnosticAt, 8> Notes; + return evaluateValue(Notes); +} + +APValue *VarDecl::evaluateValue( + SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + EvaluatedStmt *Eval = ensureEvaluatedStmt(); + + const auto *Init = cast<Expr>(Eval->Value); + assert(!Init->isValueDependent()); + + // We only produce notes indicating why an initializer is non-constant the + // first time it is evaluated. FIXME: The notes won't always be emitted the + // first time we try evaluation, so might not be produced at all. + if (Eval->WasEvaluated) + return Eval->Evaluated.isAbsent() ? nullptr : &Eval->Evaluated; + + if (Eval->IsEvaluating) { + // FIXME: Produce a diagnostic for self-initialization. + return nullptr; + } + + Eval->IsEvaluating = true; + + bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(), + this, Notes); + + // Ensure the computed APValue is cleaned up later if evaluation succeeded, + // or that it's empty (so that there's nothing to clean up) if evaluation + // failed. + if (!Result) + Eval->Evaluated = APValue(); + else if (Eval->Evaluated.needsCleanup()) + getASTContext().addDestruction(&Eval->Evaluated); + + Eval->IsEvaluating = false; + Eval->WasEvaluated = true; + + return Result ? &Eval->Evaluated : nullptr; +} + +APValue *VarDecl::getEvaluatedValue() const { + if (EvaluatedStmt *Eval = getEvaluatedStmt()) + if (Eval->WasEvaluated) + return &Eval->Evaluated; + + return nullptr; +} + +bool VarDecl::hasICEInitializer(const ASTContext &Context) const { + const Expr *Init = getInit(); + assert(Init && "no initializer"); + + EvaluatedStmt *Eval = ensureEvaluatedStmt(); + if (!Eval->CheckedForICEInit) { + Eval->CheckedForICEInit = true; + Eval->HasICEInit = Init->isIntegerConstantExpr(Context); + } + return Eval->HasICEInit; +} + +bool VarDecl::hasConstantInitialization() const { + // In C, all globals (and only globals) have constant initialization. + if (hasGlobalStorage() && !getASTContext().getLangOpts().CPlusPlus) + return true; + + // In C++, it depends on whether the evaluation at the point of definition + // was evaluatable as a constant initializer. + if (EvaluatedStmt *Eval = getEvaluatedStmt()) + return Eval->HasConstantInitialization; + + return false; +} + +bool VarDecl::checkForConstantInitialization( + SmallVectorImpl<PartialDiagnosticAt> &Notes) const { + EvaluatedStmt *Eval = ensureEvaluatedStmt(); + // If we ask for the value before we know whether we have a constant + // initializer, we can compute the wrong value (for example, due to + // std::is_constant_evaluated()). + assert(!Eval->WasEvaluated && + "already evaluated var value before checking for constant init"); + assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++"); + + assert(!cast<Expr>(Eval->Value)->isValueDependent()); + + // Evaluate the initializer to check whether it's a constant expression. + Eval->HasConstantInitialization = evaluateValue(Notes) && Notes.empty(); + return Eval->HasConstantInitialization; +} + +bool VarDecl::isParameterPack() const { + return isa<PackExpansionType>(getType()); +} + +template<typename DeclT> +static DeclT *getDefinitionOrSelf(DeclT *D) { + assert(D); + if (auto *Def = D->getDefinition()) + return Def; + return D; +} + +bool VarDecl::isEscapingByref() const { + return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref; +} + +bool VarDecl::isNonEscapingByref() const { + return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref; +} + +VarDecl *VarDecl::getTemplateInstantiationPattern() const { + const VarDecl *VD = this; + + // If this is an instantiated member, walk back to the template from which + // it was instantiated. + if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) { + if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { + VD = VD->getInstantiatedFromStaticDataMember(); + while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) + VD = NewVD; + } + } + + // If it's an instantiated variable template specialization, find the + // template or partial specialization from which it was instantiated. + if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(VD)) { + if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) { + auto From = VDTemplSpec->getInstantiatedFrom(); + if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) { + while (!VTD->isMemberSpecialization()) { + auto *NewVTD = VTD->getInstantiatedFromMemberTemplate(); + if (!NewVTD) + break; + VTD = NewVTD; + } + return getDefinitionOrSelf(VTD->getTemplatedDecl()); + } + if (auto *VTPSD = + From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { + while (!VTPSD->isMemberSpecialization()) { + auto *NewVTPSD = VTPSD->getInstantiatedFromMember(); + if (!NewVTPSD) + break; + VTPSD = NewVTPSD; + } + return getDefinitionOrSelf<VarDecl>(VTPSD); + } + } + } + + // If this is the pattern of a variable template, find where it was + // instantiated from. FIXME: Is this necessary? + if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) { + while (!VarTemplate->isMemberSpecialization()) { + auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate(); + if (!NewVT) + break; + VarTemplate = NewVT; + } + + return getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); + } + + if (VD == this) + return nullptr; + return getDefinitionOrSelf(const_cast<VarDecl*>(VD)); +} + +VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return cast<VarDecl>(MSI->getInstantiatedFrom()); + + return nullptr; +} + +TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { + if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) + return Spec->getSpecializationKind(); + + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return MSI->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +TemplateSpecializationKind +VarDecl::getTemplateSpecializationKindForInstantiation() const { + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return MSI->getTemplateSpecializationKind(); + + if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) + return Spec->getSpecializationKind(); + + return TSK_Undeclared; +} + +SourceLocation VarDecl::getPointOfInstantiation() const { + if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) + return Spec->getPointOfInstantiation(); + + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return MSI->getPointOfInstantiation(); + + return SourceLocation(); +} + +VarTemplateDecl *VarDecl::getDescribedVarTemplate() const { + return getASTContext().getTemplateOrSpecializationInfo(this) + .dyn_cast<VarTemplateDecl *>(); +} + +void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) { + getASTContext().setTemplateOrSpecializationInfo(this, Template); +} + +bool VarDecl::isKnownToBeDefined() const { + const auto &LangOpts = getASTContext().getLangOpts(); + // In CUDA mode without relocatable device code, variables of form 'extern + // __shared__ Foo foo[]' are pointers to the base of the GPU core's shared + // memory pool. These are never undefined variables, even if they appear + // inside of an anon namespace or static function. + // + // With CUDA relocatable device code enabled, these variables don't get + // special handling; they're treated like regular extern variables. + if (LangOpts.CUDA && !LangOpts.GPURelocatableDeviceCode && + hasExternalStorage() && hasAttr<CUDASharedAttr>() && + isa<IncompleteArrayType>(getType())) + return true; + + return hasDefinition(); +} + +bool VarDecl::isNoDestroy(const ASTContext &Ctx) const { + return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() || + (!Ctx.getLangOpts().RegisterStaticDestructors && + !hasAttr<AlwaysDestroyAttr>())); +} + +QualType::DestructionKind +VarDecl::needsDestruction(const ASTContext &Ctx) const { + if (EvaluatedStmt *Eval = getEvaluatedStmt()) + if (Eval->HasConstantDestruction) + return QualType::DK_none; + + if (isNoDestroy(Ctx)) + return QualType::DK_none; + + return getType().isDestructedType(); +} + +MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { + if (isStaticDataMember()) + // FIXME: Remove ? + // return getASTContext().getInstantiatedFromStaticDataMember(this); + return getASTContext().getTemplateOrSpecializationInfo(this) + .dyn_cast<MemberSpecializationInfo *>(); + return nullptr; +} + +void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation) { + assert((isa<VarTemplateSpecializationDecl>(this) || + getMemberSpecializationInfo()) && + "not a variable or static data member template specialization"); + + if (VarTemplateSpecializationDecl *Spec = + dyn_cast<VarTemplateSpecializationDecl>(this)) { + Spec->setSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && + PointOfInstantiation.isValid() && + Spec->getPointOfInstantiation().isInvalid()) { + Spec->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } + } else if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { + MSI->setTemplateSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && + MSI->getPointOfInstantiation().isInvalid()) { + MSI->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } + } +} + +void +VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD, + TemplateSpecializationKind TSK) { + assert(getASTContext().getTemplateOrSpecializationInfo(this).isNull() && + "Previous template or instantiation?"); + getASTContext().setInstantiatedFromStaticDataMember(this, VD, TSK); +} + +//===----------------------------------------------------------------------===// +// ParmVarDecl Implementation +//===----------------------------------------------------------------------===// + +ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, + StorageClass S, Expr *DefArg) { + return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo, + S, DefArg); +} + +QualType ParmVarDecl::getOriginalType() const { + TypeSourceInfo *TSI = getTypeSourceInfo(); + QualType T = TSI ? TSI->getType() : getType(); + if (const auto *DT = dyn_cast<DecayedType>(T)) + return DT->getOriginalType(); + return T; +} + +ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) + ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(), + nullptr, QualType(), nullptr, SC_None, nullptr); +} + +SourceRange ParmVarDecl::getSourceRange() const { + if (!hasInheritedDefaultArg()) { + SourceRange ArgRange = getDefaultArgRange(); + if (ArgRange.isValid()) + return SourceRange(getOuterLocStart(), ArgRange.getEnd()); + } + + // DeclaratorDecl considers the range of postfix types as overlapping with the + // declaration name, but this is not the case with parameters in ObjC methods. + if (isa<ObjCMethodDecl>(getDeclContext())) + return SourceRange(DeclaratorDecl::getBeginLoc(), getLocation()); + + return DeclaratorDecl::getSourceRange(); +} + +bool ParmVarDecl::isDestroyedInCallee() const { + if (hasAttr<NSConsumedAttr>()) + return true; + + auto *RT = getType()->getAs<RecordType>(); + if (RT && RT->getDecl()->isParamDestroyedInCallee()) + return true; + + return false; +} + +Expr *ParmVarDecl::getDefaultArg() { + assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!"); + assert(!hasUninstantiatedDefaultArg() && + "Default argument is not yet instantiated!"); + + Expr *Arg = getInit(); + if (auto *E = dyn_cast_or_null<FullExpr>(Arg)) + return E->getSubExpr(); + + return Arg; +} + +void ParmVarDecl::setDefaultArg(Expr *defarg) { + ParmVarDeclBits.DefaultArgKind = DAK_Normal; + Init = defarg; +} + +SourceRange ParmVarDecl::getDefaultArgRange() const { + switch (ParmVarDeclBits.DefaultArgKind) { + case DAK_None: + case DAK_Unparsed: + // Nothing we can do here. + return SourceRange(); + + case DAK_Uninstantiated: + return getUninstantiatedDefaultArg()->getSourceRange(); + + case DAK_Normal: + if (const Expr *E = getInit()) + return E->getSourceRange(); + + // Missing an actual expression, may be invalid. + return SourceRange(); + } + llvm_unreachable("Invalid default argument kind."); +} + +void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) { + ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated; + Init = arg; +} + +Expr *ParmVarDecl::getUninstantiatedDefaultArg() { + assert(hasUninstantiatedDefaultArg() && + "Wrong kind of initialization expression!"); + return cast_or_null<Expr>(Init.get<Stmt *>()); +} + +bool ParmVarDecl::hasDefaultArg() const { + // FIXME: We should just return false for DAK_None here once callers are + // prepared for the case that we encountered an invalid default argument and + // were unable to even build an invalid expression. + return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() || + !Init.isNull(); +} + +void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) { + getASTContext().setParameterIndex(this, parameterIndex); + ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel; +} + +unsigned ParmVarDecl::getParameterIndexLarge() const { + return getASTContext().getParameterIndex(this); +} + +//===----------------------------------------------------------------------===// +// FunctionDecl Implementation +//===----------------------------------------------------------------------===// + +FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, + TypeSourceInfo *TInfo, StorageClass S, + bool isInlineSpecified, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) + : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, + StartLoc), + DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0), + EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) { + assert(T.isNull() || T->isFunctionType()); + FunctionDeclBits.SClass = S; + FunctionDeclBits.IsInline = isInlineSpecified; + FunctionDeclBits.IsInlineSpecified = isInlineSpecified; + FunctionDeclBits.IsVirtualAsWritten = false; + FunctionDeclBits.IsPure = false; + FunctionDeclBits.HasInheritedPrototype = false; + FunctionDeclBits.HasWrittenPrototype = true; + FunctionDeclBits.IsDeleted = false; + FunctionDeclBits.IsTrivial = false; + FunctionDeclBits.IsTrivialForCall = false; + FunctionDeclBits.IsDefaulted = false; + FunctionDeclBits.IsExplicitlyDefaulted = false; + FunctionDeclBits.HasDefaultedFunctionInfo = false; + FunctionDeclBits.HasImplicitReturnZero = false; + FunctionDeclBits.IsLateTemplateParsed = false; + FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind); + FunctionDeclBits.InstantiationIsPending = false; + FunctionDeclBits.UsesSEHTry = false; + FunctionDeclBits.UsesFPIntrin = false; + FunctionDeclBits.HasSkippedBody = false; + FunctionDeclBits.WillHaveBody = false; + FunctionDeclBits.IsMultiVersion = false; + FunctionDeclBits.IsCopyDeductionCandidate = false; + FunctionDeclBits.HasODRHash = false; + if (TrailingRequiresClause) + setTrailingRequiresClause(TrailingRequiresClause); +} + +void FunctionDecl::getNameForDiagnostic( + raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { + NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); + const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); + if (TemplateArgs) + printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy); +} + +bool FunctionDecl::isVariadic() const { + if (const auto *FT = getType()->getAs<FunctionProtoType>()) + return FT->isVariadic(); + return false; +} + +FunctionDecl::DefaultedFunctionInfo * +FunctionDecl::DefaultedFunctionInfo::Create(ASTContext &Context, + ArrayRef<DeclAccessPair> Lookups) { + DefaultedFunctionInfo *Info = new (Context.Allocate( + totalSizeToAlloc<DeclAccessPair>(Lookups.size()), + std::max(alignof(DefaultedFunctionInfo), alignof(DeclAccessPair)))) + DefaultedFunctionInfo; + Info->NumLookups = Lookups.size(); + std::uninitialized_copy(Lookups.begin(), Lookups.end(), + Info->getTrailingObjects<DeclAccessPair>()); + return Info; +} + +void FunctionDecl::setDefaultedFunctionInfo(DefaultedFunctionInfo *Info) { + assert(!FunctionDeclBits.HasDefaultedFunctionInfo && "already have this"); + assert(!Body && "can't replace function body with defaulted function info"); + + FunctionDeclBits.HasDefaultedFunctionInfo = true; + DefaultedInfo = Info; +} + +FunctionDecl::DefaultedFunctionInfo * +FunctionDecl::getDefaultedFunctionInfo() const { + return FunctionDeclBits.HasDefaultedFunctionInfo ? DefaultedInfo : nullptr; +} + +bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { + for (auto I : redecls()) { + if (I->doesThisDeclarationHaveABody()) { + Definition = I; + return true; + } + } + + return false; +} + +bool FunctionDecl::hasTrivialBody() const { + Stmt *S = getBody(); + if (!S) { + // Since we don't have a body for this function, we don't know if it's + // trivial or not. + return false; + } + + if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty()) + return true; + return false; +} + +bool FunctionDecl::isThisDeclarationInstantiatedFromAFriendDefinition() const { + if (!getFriendObjectKind()) + return false; + + // Check for a friend function instantiated from a friend function + // definition in a templated class. + if (const FunctionDecl *InstantiatedFrom = + getInstantiatedFromMemberFunction()) + return InstantiatedFrom->getFriendObjectKind() && + InstantiatedFrom->isThisDeclarationADefinition(); + + // Check for a friend function template instantiated from a friend + // function template definition in a templated class. + if (const FunctionTemplateDecl *Template = getDescribedFunctionTemplate()) { + if (const FunctionTemplateDecl *InstantiatedFrom = + Template->getInstantiatedFromMemberTemplate()) + return InstantiatedFrom->getFriendObjectKind() && + InstantiatedFrom->isThisDeclarationADefinition(); + } + + return false; +} + +bool FunctionDecl::isDefined(const FunctionDecl *&Definition, + bool CheckForPendingFriendDefinition) const { + for (const FunctionDecl *FD : redecls()) { + if (FD->isThisDeclarationADefinition()) { + Definition = FD; + return true; + } + + // If this is a friend function defined in a class template, it does not + // have a body until it is used, nevertheless it is a definition, see + // [temp.inst]p2: + // + // ... for the purpose of determining whether an instantiated redeclaration + // is valid according to [basic.def.odr] and [class.mem], a declaration that + // corresponds to a definition in the template is considered to be a + // definition. + // + // The following code must produce redefinition error: + // + // template<typename T> struct C20 { friend void func_20() {} }; + // C20<int> c20i; + // void func_20() {} + // + if (CheckForPendingFriendDefinition && + FD->isThisDeclarationInstantiatedFromAFriendDefinition()) { + Definition = FD; + return true; + } + } + + return false; +} + +Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { + if (!hasBody(Definition)) + return nullptr; + + assert(!Definition->FunctionDeclBits.HasDefaultedFunctionInfo && + "definition should not have a body"); + if (Definition->Body) + return Definition->Body.get(getASTContext().getExternalSource()); + + return nullptr; +} + +void FunctionDecl::setBody(Stmt *B) { + FunctionDeclBits.HasDefaultedFunctionInfo = false; + Body = LazyDeclStmtPtr(B); + if (B) + EndRangeLoc = B->getEndLoc(); +} + +void FunctionDecl::setPure(bool P) { + FunctionDeclBits.IsPure = P; + if (P) + if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext())) + Parent->markedVirtualFunctionPure(); +} + +template<std::size_t Len> +static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) { + IdentifierInfo *II = ND->getIdentifier(); + return II && II->isStr(Str); +} + +bool FunctionDecl::isMain() const { + const TranslationUnitDecl *tunit = + dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); + return tunit && + !tunit->getASTContext().getLangOpts().Freestanding && + isNamed(this, "main"); +} + +bool FunctionDecl::isMSVCRTEntryPoint() const { + const TranslationUnitDecl *TUnit = + dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()); + if (!TUnit) + return false; + + // Even though we aren't really targeting MSVCRT if we are freestanding, + // semantic analysis for these functions remains the same. + + // MSVCRT entry points only exist on MSVCRT targets. + if (!TUnit->getASTContext().getTargetInfo().getTriple().isOSMSVCRT()) + return false; + + // Nameless functions like constructors cannot be entry points. + if (!getIdentifier()) + return false; + + return llvm::StringSwitch<bool>(getName()) + .Cases("main", // an ANSI console app + "wmain", // a Unicode console App + "WinMain", // an ANSI GUI app + "wWinMain", // a Unicode GUI app + "DllMain", // a DLL + true) + .Default(false); +} + +bool FunctionDecl::isReservedGlobalPlacementOperator() const { + assert(getDeclName().getNameKind() == DeclarationName::CXXOperatorName); + assert(getDeclName().getCXXOverloadedOperator() == OO_New || + getDeclName().getCXXOverloadedOperator() == OO_Delete || + getDeclName().getCXXOverloadedOperator() == OO_Array_New || + getDeclName().getCXXOverloadedOperator() == OO_Array_Delete); + + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; + + const auto *proto = getType()->castAs<FunctionProtoType>(); + if (proto->getNumParams() != 2 || proto->isVariadic()) + return false; + + ASTContext &Context = + cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()) + ->getASTContext(); + + // The result type and first argument type are constant across all + // these operators. The second argument must be exactly void*. + return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy); +} + +bool FunctionDecl::isReplaceableGlobalAllocationFunction( + Optional<unsigned> *AlignmentParam, bool *IsNothrow) const { + if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) + return false; + if (getDeclName().getCXXOverloadedOperator() != OO_New && + getDeclName().getCXXOverloadedOperator() != OO_Delete && + getDeclName().getCXXOverloadedOperator() != OO_Array_New && + getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) + return false; + + if (isa<CXXRecordDecl>(getDeclContext())) + return false; + + // This can only fail for an invalid 'operator new' declaration. + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; + + const auto *FPT = getType()->castAs<FunctionProtoType>(); + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic()) + return false; + + // If this is a single-parameter function, it must be a replaceable global + // allocation or deallocation function. + if (FPT->getNumParams() == 1) + return true; + + unsigned Params = 1; + QualType Ty = FPT->getParamType(Params); + ASTContext &Ctx = getASTContext(); + + auto Consume = [&] { + ++Params; + Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType(); + }; + + // In C++14, the next parameter can be a 'std::size_t' for sized delete. + bool IsSizedDelete = false; + if (Ctx.getLangOpts().SizedDeallocation && + (getDeclName().getCXXOverloadedOperator() == OO_Delete || + getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) && + Ctx.hasSameType(Ty, Ctx.getSizeType())) { + IsSizedDelete = true; + Consume(); + } + + // In C++17, the next parameter can be a 'std::align_val_t' for aligned + // new/delete. + if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) { + Consume(); + if (AlignmentParam) + *AlignmentParam = Params; + } + + // Finally, if this is not a sized delete, the final parameter can + // be a 'const std::nothrow_t&'. + if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) { + Ty = Ty->getPointeeType(); + if (Ty.getCVRQualifiers() != Qualifiers::Const) + return false; + if (Ty->isNothrowT()) { + if (IsNothrow) + *IsNothrow = true; + Consume(); + } + } + + return Params == FPT->getNumParams(); +} + +bool FunctionDecl::isInlineBuiltinDeclaration() const { + if (!getBuiltinID()) + return false; + + const FunctionDecl *Definition; + return hasBody(Definition) && Definition->isInlineSpecified(); +} + +bool FunctionDecl::isDestroyingOperatorDelete() const { + // C++ P0722: + // Within a class C, a single object deallocation function with signature + // (T, std::destroying_delete_t, <more params>) + // is a destroying operator delete. + if (!isa<CXXMethodDecl>(this) || getOverloadedOperator() != OO_Delete || + getNumParams() < 2) + return false; + + auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl(); + return RD && RD->isInStdNamespace() && RD->getIdentifier() && + RD->getIdentifier()->isStr("destroying_delete_t"); +} + +LanguageLinkage FunctionDecl::getLanguageLinkage() const { + return getDeclLanguageLinkage(*this); +} + +bool FunctionDecl::isExternC() const { + return isDeclExternC(*this); +} + +bool FunctionDecl::isInExternCContext() const { + if (hasAttr<OpenCLKernelAttr>()) + return true; + return getLexicalDeclContext()->isExternCContext(); +} + +bool FunctionDecl::isInExternCXXContext() const { + return getLexicalDeclContext()->isExternCXXContext(); +} + +bool FunctionDecl::isGlobal() const { + if (const auto *Method = dyn_cast<CXXMethodDecl>(this)) + return Method->isStatic(); + + if (getCanonicalDecl()->getStorageClass() == SC_Static) + return false; + + for (const DeclContext *DC = getDeclContext(); + DC->isNamespace(); + DC = DC->getParent()) { + if (const auto *Namespace = cast<NamespaceDecl>(DC)) { + if (!Namespace->getDeclName()) + return false; + break; + } + } + + return true; +} + +bool FunctionDecl::isNoReturn() const { + if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() || + hasAttr<C11NoReturnAttr>()) + return true; + + if (auto *FnTy = getType()->getAs<FunctionType>()) + return FnTy->getNoReturnAttr(); + + return false; +} + + +MultiVersionKind FunctionDecl::getMultiVersionKind() const { + if (hasAttr<TargetAttr>()) + return MultiVersionKind::Target; + if (hasAttr<CPUDispatchAttr>()) + return MultiVersionKind::CPUDispatch; + if (hasAttr<CPUSpecificAttr>()) + return MultiVersionKind::CPUSpecific; + return MultiVersionKind::None; +} + +bool FunctionDecl::isCPUDispatchMultiVersion() const { + return isMultiVersion() && hasAttr<CPUDispatchAttr>(); +} + +bool FunctionDecl::isCPUSpecificMultiVersion() const { + return isMultiVersion() && hasAttr<CPUSpecificAttr>(); +} + +bool FunctionDecl::isTargetMultiVersion() const { + return isMultiVersion() && hasAttr<TargetAttr>(); +} + +void +FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { + redeclarable_base::setPreviousDecl(PrevDecl); + + if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { + FunctionTemplateDecl *PrevFunTmpl + = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr; + assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); + FunTmpl->setPreviousDecl(PrevFunTmpl); + } + + if (PrevDecl && PrevDecl->isInlined()) + setImplicitlyInline(true); +} + +FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } + +/// Returns a value indicating whether this function corresponds to a builtin +/// function. +/// +/// The function corresponds to a built-in function if it is declared at +/// translation scope or within an extern "C" block and its name matches with +/// the name of a builtin. The returned value will be 0 for functions that do +/// not correspond to a builtin, a value of type \c Builtin::ID if in the +/// target-independent range \c [1,Builtin::First), or a target-specific builtin +/// value. +/// +/// \param ConsiderWrapperFunctions If true, we should consider wrapper +/// functions as their wrapped builtins. This shouldn't be done in general, but +/// it's useful in Sema to diagnose calls to wrappers based on their semantics. +unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const { + unsigned BuiltinID = 0; + + if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) { + BuiltinID = ABAA->getBuiltinName()->getBuiltinID(); + } else if (const auto *A = getAttr<BuiltinAttr>()) { + BuiltinID = A->getID(); + } + + if (!BuiltinID) + return 0; + + // If the function is marked "overloadable", it has a different mangled name + // and is not the C library function. + if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() && + !hasAttr<ArmBuiltinAliasAttr>()) + return 0; + + ASTContext &Context = getASTContext(); + if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return BuiltinID; + + // This function has the name of a known C library + // function. Determine whether it actually refers to the C library + // function or whether it just has the same name. + + // If this is a static function, it's not a builtin. + if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static) + return 0; + + // OpenCL v1.2 s6.9.f - The library functions defined in + // the C99 standard headers are not available. + if (Context.getLangOpts().OpenCL && + Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return 0; + + // CUDA does not have device-side standard library. printf and malloc are the + // only special cases that are supported by device-side runtime. + if (Context.getLangOpts().CUDA && hasAttr<CUDADeviceAttr>() && + !hasAttr<CUDAHostAttr>() && + !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc)) + return 0; + + // As AMDGCN implementation of OpenMP does not have a device-side standard + // library, none of the predefined library functions except printf and malloc + // should be treated as a builtin i.e. 0 should be returned for them. + if (Context.getTargetInfo().getTriple().isAMDGCN() && + Context.getLangOpts().OpenMPIsDevice && + Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) && + !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc)) + return 0; + + return BuiltinID; +} + +/// getNumParams - Return the number of parameters this function must have +/// based on its FunctionType. This is the length of the ParamInfo array +/// after it has been created. +unsigned FunctionDecl::getNumParams() const { + const auto *FPT = getType()->getAs<FunctionProtoType>(); + return FPT ? FPT->getNumParams() : 0; +} + +void FunctionDecl::setParams(ASTContext &C, + ArrayRef<ParmVarDecl *> NewParamInfo) { + assert(!ParamInfo && "Already has param info!"); + assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!"); + + // Zero params -> null pointer. + if (!NewParamInfo.empty()) { + ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()]; + std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo); + } +} + +/// getMinRequiredArguments - Returns the minimum number of arguments +/// needed to call this function. This may be fewer than the number of +/// function parameters, if some of the parameters have default +/// arguments (in C++) or are parameter packs (C++11). +unsigned FunctionDecl::getMinRequiredArguments() const { + if (!getASTContext().getLangOpts().CPlusPlus) + return getNumParams(); + + // Note that it is possible for a parameter with no default argument to + // follow a parameter with a default argument. + unsigned NumRequiredArgs = 0; + unsigned MinParamsSoFar = 0; + for (auto *Param : parameters()) { + if (!Param->isParameterPack()) { + ++MinParamsSoFar; + if (!Param->hasDefaultArg()) + NumRequiredArgs = MinParamsSoFar; + } + } + return NumRequiredArgs; +} + +bool FunctionDecl::hasOneParamOrDefaultArgs() const { + return getNumParams() == 1 || + (getNumParams() > 1 && + std::all_of(param_begin() + 1, param_end(), + [](ParmVarDecl *P) { return P->hasDefaultArg(); })); +} + +/// The combination of the extern and inline keywords under MSVC forces +/// the function to be required. +/// +/// Note: This function assumes that we will only get called when isInlined() +/// would return true for this FunctionDecl. +bool FunctionDecl::isMSExternInline() const { + assert(isInlined() && "expected to get called on an inlined function!"); + + const ASTContext &Context = getASTContext(); + if (!Context.getTargetInfo().getCXXABI().isMicrosoft() && + !hasAttr<DLLExportAttr>()) + return false; + + for (const FunctionDecl *FD = getMostRecentDecl(); FD; + FD = FD->getPreviousDecl()) + if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern) + return true; + + return false; +} + +static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) { + if (Redecl->getStorageClass() != SC_Extern) + return false; + + for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD; + FD = FD->getPreviousDecl()) + if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern) + return false; + + return true; +} + +static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { + // Only consider file-scope declarations in this test. + if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) + return false; + + // Only consider explicit declarations; the presence of a builtin for a + // libcall shouldn't affect whether a definition is externally visible. + if (Redecl->isImplicit()) + return false; + + if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern) + return true; // Not an inline definition + + return false; +} + +/// For a function declaration in C or C++, determine whether this +/// declaration causes the definition to be externally visible. +/// +/// For instance, this determines if adding the current declaration to the set +/// of redeclarations of the given functions causes +/// isInlineDefinitionExternallyVisible to change from false to true. +bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { + assert(!doesThisDeclarationHaveABody() && + "Must have a declaration without a body."); + + ASTContext &Context = getASTContext(); + + if (Context.getLangOpts().MSVCCompat) { + const FunctionDecl *Definition; + if (hasBody(Definition) && Definition->isInlined() && + redeclForcesDefMSVC(this)) + return true; + } + + if (Context.getLangOpts().CPlusPlus) + return false; + + if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) { + // With GNU inlining, a declaration with 'inline' but not 'extern', forces + // an externally visible definition. + // + // FIXME: What happens if gnu_inline gets added on after the first + // declaration? + if (!isInlineSpecified() || getStorageClass() == SC_Extern) + return false; + + const FunctionDecl *Prev = this; + bool FoundBody = false; + while ((Prev = Prev->getPreviousDecl())) { + FoundBody |= Prev->doesThisDeclarationHaveABody(); + + if (Prev->doesThisDeclarationHaveABody()) { + // If it's not the case that both 'inline' and 'extern' are + // specified on the definition, then it is always externally visible. + if (!Prev->isInlineSpecified() || + Prev->getStorageClass() != SC_Extern) + return false; + } else if (Prev->isInlineSpecified() && + Prev->getStorageClass() != SC_Extern) { + return false; + } + } + return FoundBody; + } + + // C99 6.7.4p6: + // [...] If all of the file scope declarations for a function in a + // translation unit include the inline function specifier without extern, + // then the definition in that translation unit is an inline definition. + if (isInlineSpecified() && getStorageClass() != SC_Extern) + return false; + const FunctionDecl *Prev = this; + bool FoundBody = false; + while ((Prev = Prev->getPreviousDecl())) { + FoundBody |= Prev->doesThisDeclarationHaveABody(); + if (RedeclForcesDefC99(Prev)) + return false; + } + return FoundBody; +} + +FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const { + const TypeSourceInfo *TSI = getTypeSourceInfo(); + return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>() + : FunctionTypeLoc(); +} + +SourceRange FunctionDecl::getReturnTypeSourceRange() const { + FunctionTypeLoc FTL = getFunctionTypeLoc(); + if (!FTL) + return SourceRange(); + + // Skip self-referential return types. + const SourceManager &SM = getASTContext().getSourceManager(); + SourceRange RTRange = FTL.getReturnLoc().getSourceRange(); + SourceLocation Boundary = getNameInfo().getBeginLoc(); + if (RTRange.isInvalid() || Boundary.isInvalid() || + !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary)) + return SourceRange(); + + return RTRange; +} + +SourceRange FunctionDecl::getParametersSourceRange() const { + unsigned NP = getNumParams(); + SourceLocation EllipsisLoc = getEllipsisLoc(); + + if (NP == 0 && EllipsisLoc.isInvalid()) + return SourceRange(); + + SourceLocation Begin = + NP > 0 ? ParamInfo[0]->getSourceRange().getBegin() : EllipsisLoc; + SourceLocation End = EllipsisLoc.isValid() + ? EllipsisLoc + : ParamInfo[NP - 1]->getSourceRange().getEnd(); + + return SourceRange(Begin, End); +} + +SourceRange FunctionDecl::getExceptionSpecSourceRange() const { + FunctionTypeLoc FTL = getFunctionTypeLoc(); + return FTL ? FTL.getExceptionSpecRange() : SourceRange(); +} + +/// For an inline function definition in C, or for a gnu_inline function +/// in C++, determine whether the definition will be externally visible. +/// +/// Inline function definitions are always available for inlining optimizations. +/// However, depending on the language dialect, declaration specifiers, and +/// attributes, the definition of an inline function may or may not be +/// "externally" visible to other translation units in the program. +/// +/// In C99, inline definitions are not externally visible by default. However, +/// if even one of the global-scope declarations is marked "extern inline", the +/// inline definition becomes externally visible (C99 6.7.4p6). +/// +/// In GNU89 mode, or if the gnu_inline attribute is attached to the function +/// definition, we use the GNU semantics for inline, which are nearly the +/// opposite of C99 semantics. In particular, "inline" by itself will create +/// an externally visible symbol, but "extern inline" will not create an +/// externally visible symbol. +bool FunctionDecl::isInlineDefinitionExternallyVisible() const { + assert((doesThisDeclarationHaveABody() || willHaveBody() || + hasAttr<AliasAttr>()) && + "Must be a function definition"); + assert(isInlined() && "Function must be inline"); + ASTContext &Context = getASTContext(); + + if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) { + // Note: If you change the logic here, please change + // doesDeclarationForceExternallyVisibleDefinition as well. + // + // If it's not the case that both 'inline' and 'extern' are + // specified on the definition, then this inline definition is + // externally visible. + if (Context.getLangOpts().CPlusPlus) + return false; + if (!(isInlineSpecified() && getStorageClass() == SC_Extern)) + return true; + + // If any declaration is 'inline' but not 'extern', then this definition + // is externally visible. + for (auto Redecl : redecls()) { + if (Redecl->isInlineSpecified() && + Redecl->getStorageClass() != SC_Extern) + return true; + } + + return false; + } + + // The rest of this function is C-only. + assert(!Context.getLangOpts().CPlusPlus && + "should not use C inline rules in C++"); + + // C99 6.7.4p6: + // [...] If all of the file scope declarations for a function in a + // translation unit include the inline function specifier without extern, + // then the definition in that translation unit is an inline definition. + for (auto Redecl : redecls()) { + if (RedeclForcesDefC99(Redecl)) + return true; + } + + // C99 6.7.4p6: + // An inline definition does not provide an external definition for the + // function, and does not forbid an external definition in another + // translation unit. + return false; +} + +/// getOverloadedOperator - Which C++ overloaded operator this +/// function represents, if any. +OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { + if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName) + return getDeclName().getCXXOverloadedOperator(); + return OO_None; +} + +/// getLiteralIdentifier - The literal suffix identifier this function +/// represents, if any. +const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const { + if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName) + return getDeclName().getCXXLiteralIdentifier(); + return nullptr; +} + +FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { + if (TemplateOrSpecialization.isNull()) + return TK_NonTemplate; + if (TemplateOrSpecialization.is<FunctionTemplateDecl *>()) + return TK_FunctionTemplate; + if (TemplateOrSpecialization.is<MemberSpecializationInfo *>()) + return TK_MemberSpecialization; + if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>()) + return TK_FunctionTemplateSpecialization; + if (TemplateOrSpecialization.is + <DependentFunctionTemplateSpecializationInfo*>()) + return TK_DependentFunctionTemplateSpecialization; + + llvm_unreachable("Did we miss a TemplateOrSpecialization type?"); +} + +FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { + if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) + return cast<FunctionDecl>(Info->getInstantiatedFrom()); + + return nullptr; +} + +MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { + if (auto *MSI = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) + return MSI; + if (auto *FTSI = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) + return FTSI->getMemberSpecializationInfo(); + return nullptr; +} + +void +FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, + FunctionDecl *FD, + TemplateSpecializationKind TSK) { + assert(TemplateOrSpecialization.isNull() && + "Member function is already a specialization"); + MemberSpecializationInfo *Info + = new (C) MemberSpecializationInfo(FD, TSK); + TemplateOrSpecialization = Info; +} + +FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const { + return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>(); +} + +void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { + assert(TemplateOrSpecialization.isNull() && + "Member function is already a specialization"); + TemplateOrSpecialization = Template; +} + +bool FunctionDecl::isImplicitlyInstantiable() const { + // If the function is invalid, it can't be implicitly instantiated. + if (isInvalidDecl()) + return false; + + switch (getTemplateSpecializationKindForInstantiation()) { + case TSK_Undeclared: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + return false; + + case TSK_ImplicitInstantiation: + return true; + + case TSK_ExplicitInstantiationDeclaration: + // Handled below. + break; + } + + // Find the actual template from which we will instantiate. + const FunctionDecl *PatternDecl = getTemplateInstantiationPattern(); + bool HasPattern = false; + if (PatternDecl) + HasPattern = PatternDecl->hasBody(PatternDecl); + + // C++0x [temp.explicit]p9: + // Except for inline functions, other explicit instantiation declarations + // have the effect of suppressing the implicit instantiation of the entity + // to which they refer. + if (!HasPattern || !PatternDecl) + return true; + + return PatternDecl->isInlined(); +} + +bool FunctionDecl::isTemplateInstantiation() const { + // FIXME: Remove this, it's not clear what it means. (Which template + // specialization kind?) + return clang::isTemplateInstantiation(getTemplateSpecializationKind()); +} + +FunctionDecl * +FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const { + // If this is a generic lambda call operator specialization, its + // instantiation pattern is always its primary template's pattern + // even if its primary template was instantiated from another + // member template (which happens with nested generic lambdas). + // Since a lambda's call operator's body is transformed eagerly, + // we don't have to go hunting for a prototype definition template + // (i.e. instantiated-from-member-template) to use as an instantiation + // pattern. + + if (isGenericLambdaCallOperatorSpecialization( + dyn_cast<CXXMethodDecl>(this))) { + assert(getPrimaryTemplate() && "not a generic lambda call operator?"); + return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); + } + + // Check for a declaration of this function that was instantiated from a + // friend definition. + const FunctionDecl *FD = nullptr; + if (!isDefined(FD, /*CheckForPendingFriendDefinition=*/true)) + FD = this; + + if (MemberSpecializationInfo *Info = FD->getMemberSpecializationInfo()) { + if (ForDefinition && + !clang::isTemplateInstantiation(Info->getTemplateSpecializationKind())) + return nullptr; + return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom())); + } + + if (ForDefinition && + !clang::isTemplateInstantiation(getTemplateSpecializationKind())) + return nullptr; + + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { + // If we hit a point where the user provided a specialization of this + // template, we're done looking. + while (!ForDefinition || !Primary->isMemberSpecialization()) { + auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate(); + if (!NewPrimary) + break; + Primary = NewPrimary; + } + + return getDefinitionOrSelf(Primary->getTemplatedDecl()); + } + + return nullptr; +} + +FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { + if (FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + return Info->getTemplate(); + } + return nullptr; +} + +FunctionTemplateSpecializationInfo * +FunctionDecl::getTemplateSpecializationInfo() const { + return TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>(); +} + +const TemplateArgumentList * +FunctionDecl::getTemplateSpecializationArgs() const { + if (FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + return Info->TemplateArguments; + } + return nullptr; +} + +const ASTTemplateArgumentListInfo * +FunctionDecl::getTemplateSpecializationArgsAsWritten() const { + if (FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + return Info->TemplateArgumentsAsWritten; + } + return nullptr; +} + +void +FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation) { + assert((TemplateOrSpecialization.isNull() || + TemplateOrSpecialization.is<MemberSpecializationInfo *>()) && + "Member function is already a specialization"); + assert(TSK != TSK_Undeclared && + "Must specify the type of function template specialization"); + assert((TemplateOrSpecialization.isNull() || + TSK == TSK_ExplicitSpecialization) && + "Member specialization must be an explicit specialization"); + FunctionTemplateSpecializationInfo *Info = + FunctionTemplateSpecializationInfo::Create( + C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten, + PointOfInstantiation, + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()); + TemplateOrSpecialization = Info; + Template->addSpecialization(Info, InsertPos); +} + +void +FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context, + const UnresolvedSetImpl &Templates, + const TemplateArgumentListInfo &TemplateArgs) { + assert(TemplateOrSpecialization.isNull()); + DependentFunctionTemplateSpecializationInfo *Info = + DependentFunctionTemplateSpecializationInfo::Create(Context, Templates, + TemplateArgs); + TemplateOrSpecialization = Info; +} + +DependentFunctionTemplateSpecializationInfo * +FunctionDecl::getDependentSpecializationInfo() const { + return TemplateOrSpecialization + .dyn_cast<DependentFunctionTemplateSpecializationInfo *>(); +} + +DependentFunctionTemplateSpecializationInfo * +DependentFunctionTemplateSpecializationInfo::Create( + ASTContext &Context, const UnresolvedSetImpl &Ts, + const TemplateArgumentListInfo &TArgs) { + void *Buffer = Context.Allocate( + totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>( + TArgs.size(), Ts.size())); + return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs); +} + +DependentFunctionTemplateSpecializationInfo:: +DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts, + const TemplateArgumentListInfo &TArgs) + : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) { + NumTemplates = Ts.size(); + NumArgs = TArgs.size(); + + FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>(); + for (unsigned I = 0, E = Ts.size(); I != E; ++I) + TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl()); + + TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>(); + for (unsigned I = 0, E = TArgs.size(); I != E; ++I) + new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]); +} + +TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const { + // For a function template specialization, query the specialization + // information object. + if (FunctionTemplateSpecializationInfo *FTSInfo = + TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) + return FTSInfo->getTemplateSpecializationKind(); + + if (MemberSpecializationInfo *MSInfo = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) + return MSInfo->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +TemplateSpecializationKind +FunctionDecl::getTemplateSpecializationKindForInstantiation() const { + // This is the same as getTemplateSpecializationKind(), except that for a + // function that is both a function template specialization and a member + // specialization, we prefer the member specialization information. Eg: + // + // template<typename T> struct A { + // template<typename U> void f() {} + // template<> void f<int>() {} + // }; + // + // For A<int>::f<int>(): + // * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization + // * getTemplateSpecializationKindForInstantiation() will return + // TSK_ImplicitInstantiation + // + // This reflects the facts that A<int>::f<int> is an explicit specialization + // of A<int>::f, and that A<int>::f<int> should be implicitly instantiated + // from A::f<int> if a definition is needed. + if (FunctionTemplateSpecializationInfo *FTSInfo = + TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) { + if (auto *MSInfo = FTSInfo->getMemberSpecializationInfo()) + return MSInfo->getTemplateSpecializationKind(); + return FTSInfo->getTemplateSpecializationKind(); + } + + if (MemberSpecializationInfo *MSInfo = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) + return MSInfo->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +void +FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation) { + if (FunctionTemplateSpecializationInfo *FTSInfo + = TemplateOrSpecialization.dyn_cast< + FunctionTemplateSpecializationInfo*>()) { + FTSInfo->setTemplateSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && + PointOfInstantiation.isValid() && + FTSInfo->getPointOfInstantiation().isInvalid()) { + FTSInfo->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } + } else if (MemberSpecializationInfo *MSInfo + = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) { + MSInfo->setTemplateSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && + PointOfInstantiation.isValid() && + MSInfo->getPointOfInstantiation().isInvalid()) { + MSInfo->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } + } else + llvm_unreachable("Function cannot have a template specialization kind"); +} + +SourceLocation FunctionDecl::getPointOfInstantiation() const { + if (FunctionTemplateSpecializationInfo *FTSInfo + = TemplateOrSpecialization.dyn_cast< + FunctionTemplateSpecializationInfo*>()) + return FTSInfo->getPointOfInstantiation(); + if (MemberSpecializationInfo *MSInfo = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) + return MSInfo->getPointOfInstantiation(); + + return SourceLocation(); +} + +bool FunctionDecl::isOutOfLine() const { + if (Decl::isOutOfLine()) + return true; + + // If this function was instantiated from a member function of a + // class template, check whether that member function was defined out-of-line. + if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) { + const FunctionDecl *Definition; + if (FD->hasBody(Definition)) + return Definition->isOutOfLine(); + } + + // If this function was instantiated from a function template, + // check whether that function template was defined out-of-line. + if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) { + const FunctionDecl *Definition; + if (FunTmpl->getTemplatedDecl()->hasBody(Definition)) + return Definition->isOutOfLine(); + } + + return false; +} + +SourceRange FunctionDecl::getSourceRange() const { + return SourceRange(getOuterLocStart(), EndRangeLoc); +} + +unsigned FunctionDecl::getMemoryFunctionKind() const { + IdentifierInfo *FnInfo = getIdentifier(); + + if (!FnInfo) + return 0; + + // Builtin handling. + switch (getBuiltinID()) { + case Builtin::BI__builtin_memset: + case Builtin::BI__builtin___memset_chk: + case Builtin::BImemset: + return Builtin::BImemset; + + case Builtin::BI__builtin_memcpy: + case Builtin::BI__builtin___memcpy_chk: + case Builtin::BImemcpy: + return Builtin::BImemcpy; + + case Builtin::BI__builtin_mempcpy: + case Builtin::BI__builtin___mempcpy_chk: + case Builtin::BImempcpy: + return Builtin::BImempcpy; + + case Builtin::BI__builtin_memmove: + case Builtin::BI__builtin___memmove_chk: + case Builtin::BImemmove: + return Builtin::BImemmove; + + case Builtin::BIstrlcpy: + case Builtin::BI__builtin___strlcpy_chk: + return Builtin::BIstrlcpy; + + case Builtin::BIstrlcat: + case Builtin::BI__builtin___strlcat_chk: + return Builtin::BIstrlcat; + + case Builtin::BI__builtin_memcmp: + case Builtin::BImemcmp: + return Builtin::BImemcmp; + + case Builtin::BI__builtin_bcmp: + case Builtin::BIbcmp: + return Builtin::BIbcmp; + + case Builtin::BI__builtin_strncpy: + case Builtin::BI__builtin___strncpy_chk: + case Builtin::BIstrncpy: + return Builtin::BIstrncpy; + + case Builtin::BI__builtin_strncmp: + case Builtin::BIstrncmp: + return Builtin::BIstrncmp; + + case Builtin::BI__builtin_strncasecmp: + case Builtin::BIstrncasecmp: + return Builtin::BIstrncasecmp; + + case Builtin::BI__builtin_strncat: + case Builtin::BI__builtin___strncat_chk: + case Builtin::BIstrncat: + return Builtin::BIstrncat; + + case Builtin::BI__builtin_strndup: + case Builtin::BIstrndup: + return Builtin::BIstrndup; + + case Builtin::BI__builtin_strlen: + case Builtin::BIstrlen: + return Builtin::BIstrlen; + + case Builtin::BI__builtin_bzero: + case Builtin::BIbzero: + return Builtin::BIbzero; + + case Builtin::BIfree: + return Builtin::BIfree; + + default: + if (isExternC()) { + if (FnInfo->isStr("memset")) + return Builtin::BImemset; + if (FnInfo->isStr("memcpy")) + return Builtin::BImemcpy; + if (FnInfo->isStr("mempcpy")) + return Builtin::BImempcpy; + if (FnInfo->isStr("memmove")) + return Builtin::BImemmove; + if (FnInfo->isStr("memcmp")) + return Builtin::BImemcmp; + if (FnInfo->isStr("bcmp")) + return Builtin::BIbcmp; + if (FnInfo->isStr("strncpy")) + return Builtin::BIstrncpy; + if (FnInfo->isStr("strncmp")) + return Builtin::BIstrncmp; + if (FnInfo->isStr("strncasecmp")) + return Builtin::BIstrncasecmp; + if (FnInfo->isStr("strncat")) + return Builtin::BIstrncat; + if (FnInfo->isStr("strndup")) + return Builtin::BIstrndup; + if (FnInfo->isStr("strlen")) + return Builtin::BIstrlen; + if (FnInfo->isStr("bzero")) + return Builtin::BIbzero; + } else if (isInStdNamespace()) { + if (FnInfo->isStr("free")) + return Builtin::BIfree; + } + break; + } + return 0; +} + +unsigned FunctionDecl::getODRHash() const { + assert(hasODRHash()); + return ODRHash; +} + +unsigned FunctionDecl::getODRHash() { + if (hasODRHash()) + return ODRHash; + + if (auto *FT = getInstantiatedFromMemberFunction()) { + setHasODRHash(true); + ODRHash = FT->getODRHash(); + return ODRHash; + } + + class ODRHash Hash; + Hash.AddFunctionDecl(this); + setHasODRHash(true); + ODRHash = Hash.CalculateHash(); + return ODRHash; +} + +//===----------------------------------------------------------------------===// +// FieldDecl Implementation +//===----------------------------------------------------------------------===// + +FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, Expr *BW, bool Mutable, + InClassInitStyle InitStyle) { + return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, + BW, Mutable, InitStyle); +} + +FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(), + SourceLocation(), nullptr, QualType(), nullptr, + nullptr, false, ICIS_NoInit); +} + +bool FieldDecl::isAnonymousStructOrUnion() const { + if (!isImplicit() || getDeclName()) + return false; + + if (const auto *Record = getType()->getAs<RecordType>()) + return Record->getDecl()->isAnonymousStructOrUnion(); + + return false; +} + +unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const { + assert(isBitField() && "not a bitfield"); + return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue(); +} + +bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const { + return isUnnamedBitfield() && !getBitWidth()->isValueDependent() && + getBitWidthValue(Ctx) == 0; +} + +bool FieldDecl::isZeroSize(const ASTContext &Ctx) const { + if (isZeroLengthBitField(Ctx)) + return true; + + // C++2a [intro.object]p7: + // An object has nonzero size if it + // -- is not a potentially-overlapping subobject, or + if (!hasAttr<NoUniqueAddressAttr>()) + return false; + + // -- is not of class type, or + const auto *RT = getType()->getAs<RecordType>(); + if (!RT) + return false; + const RecordDecl *RD = RT->getDecl()->getDefinition(); + if (!RD) { + assert(isInvalidDecl() && "valid field has incomplete type"); + return false; + } + + // -- [has] virtual member functions or virtual base classes, or + // -- has subobjects of nonzero size or bit-fields of nonzero length + const auto *CXXRD = cast<CXXRecordDecl>(RD); + if (!CXXRD->isEmpty()) + return false; + + // Otherwise, [...] the circumstances under which the object has zero size + // are implementation-defined. + // FIXME: This might be Itanium ABI specific; we don't yet know what the MS + // ABI will do. + return true; +} + +unsigned FieldDecl::getFieldIndex() const { + const FieldDecl *Canonical = getCanonicalDecl(); + if (Canonical != this) + return Canonical->getFieldIndex(); + + if (CachedFieldIndex) return CachedFieldIndex - 1; + + unsigned Index = 0; + const RecordDecl *RD = getParent()->getDefinition(); + assert(RD && "requested index for field of struct with no definition"); + + for (auto *Field : RD->fields()) { + Field->getCanonicalDecl()->CachedFieldIndex = Index + 1; + ++Index; + } + + assert(CachedFieldIndex && "failed to find field in parent"); + return CachedFieldIndex - 1; +} + +SourceRange FieldDecl::getSourceRange() const { + const Expr *FinalExpr = getInClassInitializer(); + if (!FinalExpr) + FinalExpr = getBitWidth(); + if (FinalExpr) + return SourceRange(getInnerLocStart(), FinalExpr->getEndLoc()); + return DeclaratorDecl::getSourceRange(); +} + +void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { + assert((getParent()->isLambda() || getParent()->isCapturedRecord()) && + "capturing type in non-lambda or captured record."); + assert(InitStorage.getInt() == ISK_NoInit && + InitStorage.getPointer() == nullptr && + "bit width, initializer or captured type already set"); + InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType), + ISK_CapturedVLAType); +} + +//===----------------------------------------------------------------------===// +// TagDecl Implementation +//===----------------------------------------------------------------------===// + +TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, + SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl, + SourceLocation StartL) + : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C), + TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) { + assert((DK != Enum || TK == TTK_Enum) && + "EnumDecl not matched with TTK_Enum"); + setPreviousDecl(PrevDecl); + setTagKind(TK); + setCompleteDefinition(false); + setBeingDefined(false); + setEmbeddedInDeclarator(false); + setFreeStanding(false); + setCompleteDefinitionRequired(false); +} + +SourceLocation TagDecl::getOuterLocStart() const { + return getTemplateOrInnerLocStart(this); +} + +SourceRange TagDecl::getSourceRange() const { + SourceLocation RBraceLoc = BraceRange.getEnd(); + SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation(); + return SourceRange(getOuterLocStart(), E); +} + +TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); } + +void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { + TypedefNameDeclOrQualifier = TDD; + if (const Type *T = getTypeForDecl()) { + (void)T; + assert(T->isLinkageValid()); + } + assert(isLinkageValid()); +} + +void TagDecl::startDefinition() { + setBeingDefined(true); + + if (auto *D = dyn_cast<CXXRecordDecl>(this)) { + struct CXXRecordDecl::DefinitionData *Data = + new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); + for (auto I : redecls()) + cast<CXXRecordDecl>(I)->DefinitionData = Data; + } +} + +void TagDecl::completeDefinition() { + assert((!isa<CXXRecordDecl>(this) || + cast<CXXRecordDecl>(this)->hasDefinition()) && + "definition completed but not started"); + + setCompleteDefinition(true); + setBeingDefined(false); + + if (ASTMutationListener *L = getASTMutationListener()) + L->CompletedTagDefinition(this); +} + +TagDecl *TagDecl::getDefinition() const { + if (isCompleteDefinition()) + return const_cast<TagDecl *>(this); + + // If it's possible for us to have an out-of-date definition, check now. + if (mayHaveOutOfDateDef()) { + if (IdentifierInfo *II = getIdentifier()) { + if (II->isOutOfDate()) { + updateOutOfDate(*II); + } + } + } + + if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this)) + return CXXRD->getDefinition(); + + for (auto R : redecls()) + if (R->isCompleteDefinition()) + return R; + + return nullptr; +} + +void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { + if (QualifierLoc) { + // Make sure the extended qualifier info is allocated. + if (!hasExtInfo()) + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; + // Set qualifier info. + getExtInfo()->QualifierLoc = QualifierLoc; + } else { + // Here Qualifier == 0, i.e., we are removing the qualifier (if any). + if (hasExtInfo()) { + if (getExtInfo()->NumTemplParamLists == 0) { + getASTContext().Deallocate(getExtInfo()); + TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr; + } + else + getExtInfo()->QualifierLoc = QualifierLoc; + } + } +} + +void TagDecl::setTemplateParameterListsInfo( + ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) { + assert(!TPLists.empty()); + // Make sure the extended decl info is allocated. + if (!hasExtInfo()) + // Allocate external info struct. + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; + // Set the template parameter lists info. + getExtInfo()->setTemplateParameterListsInfo(Context, TPLists); +} + +//===----------------------------------------------------------------------===// +// EnumDecl Implementation +//===----------------------------------------------------------------------===// + +EnumDecl::EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, + bool Scoped, bool ScopedUsingClassTag, bool Fixed) + : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) { + assert(Scoped || !ScopedUsingClassTag); + IntegerType = nullptr; + setNumPositiveBits(0); + setNumNegativeBits(0); + setScoped(Scoped); + setScopedUsingClassTag(ScopedUsingClassTag); + setFixed(Fixed); + setHasODRHash(false); + ODRHash = 0; +} + +void EnumDecl::anchor() {} + +EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, + EnumDecl *PrevDecl, bool IsScoped, + bool IsScopedUsingClassTag, bool IsFixed) { + auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl, + IsScoped, IsScopedUsingClassTag, IsFixed); + Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules); + C.getTypeDeclType(Enum, PrevDecl); + return Enum; +} + +EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + EnumDecl *Enum = + new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr, false, false, false); + Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules); + return Enum; +} + +SourceRange EnumDecl::getIntegerTypeRange() const { + if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo()) + return TI->getTypeLoc().getSourceRange(); + return SourceRange(); +} + +void EnumDecl::completeDefinition(QualType NewType, + QualType NewPromotionType, + unsigned NumPositiveBits, + unsigned NumNegativeBits) { + assert(!isCompleteDefinition() && "Cannot redefine enums!"); + if (!IntegerType) + IntegerType = NewType.getTypePtr(); + PromotionType = NewPromotionType; + setNumPositiveBits(NumPositiveBits); + setNumNegativeBits(NumNegativeBits); + TagDecl::completeDefinition(); +} + +bool EnumDecl::isClosed() const { + if (const auto *A = getAttr<EnumExtensibilityAttr>()) + return A->getExtensibility() == EnumExtensibilityAttr::Closed; + return true; +} + +bool EnumDecl::isClosedFlag() const { + return isClosed() && hasAttr<FlagEnumAttr>(); +} + +bool EnumDecl::isClosedNonFlag() const { + return isClosed() && !hasAttr<FlagEnumAttr>(); +} + +TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const { + if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) + return MSI->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation) { + MemberSpecializationInfo *MSI = getMemberSpecializationInfo(); + assert(MSI && "Not an instantiated member enumeration?"); + MSI->setTemplateSpecializationKind(TSK); + if (TSK != TSK_ExplicitSpecialization && + PointOfInstantiation.isValid() && + MSI->getPointOfInstantiation().isInvalid()) + MSI->setPointOfInstantiation(PointOfInstantiation); +} + +EnumDecl *EnumDecl::getTemplateInstantiationPattern() const { + if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) { + EnumDecl *ED = getInstantiatedFromMemberEnum(); + while (auto *NewED = ED->getInstantiatedFromMemberEnum()) + ED = NewED; + return getDefinitionOrSelf(ED); + } + } + + assert(!isTemplateInstantiation(getTemplateSpecializationKind()) && + "couldn't find pattern for enum instantiation"); + return nullptr; +} + +EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const { + if (SpecializationInfo) + return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom()); + + return nullptr; +} + +void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, + TemplateSpecializationKind TSK) { + assert(!SpecializationInfo && "Member enum is already a specialization"); + SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK); +} + +unsigned EnumDecl::getODRHash() { + if (hasODRHash()) + return ODRHash; + + class ODRHash Hash; + Hash.AddEnumDecl(this); + setHasODRHash(true); + ODRHash = Hash.CalculateHash(); + return ODRHash; +} + +//===----------------------------------------------------------------------===// +// RecordDecl Implementation +//===----------------------------------------------------------------------===// + +RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + RecordDecl *PrevDecl) + : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) { + assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!"); + setHasFlexibleArrayMember(false); + setAnonymousStructOrUnion(false); + setHasObjectMember(false); + setHasVolatileMember(false); + setHasLoadedFieldsFromExternalStorage(false); + setNonTrivialToPrimitiveDefaultInitialize(false); + setNonTrivialToPrimitiveCopy(false); + setNonTrivialToPrimitiveDestroy(false); + setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false); + setHasNonTrivialToPrimitiveDestructCUnion(false); + setHasNonTrivialToPrimitiveCopyCUnion(false); + setParamDestroyedInCallee(false); + setArgPassingRestrictions(APK_CanPassInRegs); +} + +RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl* PrevDecl) { + RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC, + StartLoc, IdLoc, Id, PrevDecl); + R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); + + C.getTypeDeclType(R, PrevDecl); + return R; +} + +RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { + RecordDecl *R = + new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); + R->setMayHaveOutOfDateDef(C.getLangOpts().Modules); + return R; +} + +bool RecordDecl::isInjectedClassName() const { + return isImplicit() && getDeclName() && getDeclContext()->isRecord() && + cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName(); +} + +bool RecordDecl::isLambda() const { + if (auto RD = dyn_cast<CXXRecordDecl>(this)) + return RD->isLambda(); + return false; +} + +bool RecordDecl::isCapturedRecord() const { + return hasAttr<CapturedRecordAttr>(); +} + +void RecordDecl::setCapturedRecord() { + addAttr(CapturedRecordAttr::CreateImplicit(getASTContext())); +} + +bool RecordDecl::isOrContainsUnion() const { + if (isUnion()) + return true; + + if (const RecordDecl *Def = getDefinition()) { + for (const FieldDecl *FD : Def->fields()) { + const RecordType *RT = FD->getType()->getAs<RecordType>(); + if (RT && RT->getDecl()->isOrContainsUnion()) + return true; + } + } + + return false; +} + +RecordDecl::field_iterator RecordDecl::field_begin() const { + if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage()) + LoadFieldsFromExternalStorage(); + + return field_iterator(decl_iterator(FirstDecl)); +} + +/// completeDefinition - Notes that the definition of this type is now +/// complete. +void RecordDecl::completeDefinition() { + assert(!isCompleteDefinition() && "Cannot redefine record!"); + TagDecl::completeDefinition(); +} + +/// isMsStruct - Get whether or not this record uses ms_struct layout. +/// This which can be turned on with an attribute, pragma, or the +/// -mms-bitfields command-line option. +bool RecordDecl::isMsStruct(const ASTContext &C) const { + return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1; +} + +void RecordDecl::LoadFieldsFromExternalStorage() const { + ExternalASTSource *Source = getASTContext().getExternalSource(); + assert(hasExternalLexicalStorage() && Source && "No external storage?"); + + // Notify that we have a RecordDecl doing some initialization. + ExternalASTSource::Deserializing TheFields(Source); + + SmallVector<Decl*, 64> Decls; + setHasLoadedFieldsFromExternalStorage(true); + Source->FindExternalLexicalDecls(this, [](Decl::Kind K) { + return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K); + }, Decls); + +#ifndef NDEBUG + // Check that all decls we got were FieldDecls. + for (unsigned i=0, e=Decls.size(); i != e; ++i) + assert(isa<FieldDecl>(Decls[i]) || isa<IndirectFieldDecl>(Decls[i])); +#endif + + if (Decls.empty()) + return; + + std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + /*FieldsAlreadyLoaded=*/false); +} + +bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const { + ASTContext &Context = getASTContext(); + const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask & + (SanitizerKind::Address | SanitizerKind::KernelAddress); + if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding) + return false; + const auto &Blacklist = Context.getSanitizerBlacklist(); + const auto *CXXRD = dyn_cast<CXXRecordDecl>(this); + // We may be able to relax some of these requirements. + int ReasonToReject = -1; + if (!CXXRD || CXXRD->isExternCContext()) + ReasonToReject = 0; // is not C++. + else if (CXXRD->hasAttr<PackedAttr>()) + ReasonToReject = 1; // is packed. + else if (CXXRD->isUnion()) + ReasonToReject = 2; // is a union. + else if (CXXRD->isTriviallyCopyable()) + ReasonToReject = 3; // is trivially copyable. + else if (CXXRD->hasTrivialDestructor()) + ReasonToReject = 4; // has trivial destructor. + else if (CXXRD->isStandardLayout()) + ReasonToReject = 5; // is standard layout. + else if (Blacklist.isBlacklistedLocation(EnabledAsanMask, getLocation(), + "field-padding")) + ReasonToReject = 6; // is in an excluded file. + else if (Blacklist.isBlacklistedType(EnabledAsanMask, + getQualifiedNameAsString(), + "field-padding")) + ReasonToReject = 7; // The type is excluded. + + if (EmitRemark) { + if (ReasonToReject >= 0) + Context.getDiagnostics().Report( + getLocation(), + diag::remark_sanitize_address_insert_extra_padding_rejected) + << getQualifiedNameAsString() << ReasonToReject; + else + Context.getDiagnostics().Report( + getLocation(), + diag::remark_sanitize_address_insert_extra_padding_accepted) + << getQualifiedNameAsString(); + } + return ReasonToReject < 0; +} + +const FieldDecl *RecordDecl::findFirstNamedDataMember() const { + for (const auto *I : fields()) { + if (I->getIdentifier()) + return I; + + if (const auto *RT = I->getType()->getAs<RecordType>()) + if (const FieldDecl *NamedDataMember = + RT->getDecl()->findFirstNamedDataMember()) + return NamedDataMember; + } + + // We didn't find a named data member. + return nullptr; +} + +//===----------------------------------------------------------------------===// +// BlockDecl Implementation +//===----------------------------------------------------------------------===// + +BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc) + : Decl(Block, DC, CaretLoc), DeclContext(Block) { + setIsVariadic(false); + setCapturesCXXThis(false); + setBlockMissingReturnType(true); + setIsConversionFromLambda(false); + setDoesNotEscape(false); + setCanAvoidCopyToHeap(false); +} + +void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { + assert(!ParamInfo && "Already has param info!"); + + // Zero params -> null pointer. + if (!NewParamInfo.empty()) { + NumParams = NewParamInfo.size(); + ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()]; + std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo); + } +} + +void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures, + bool CapturesCXXThis) { + this->setCapturesCXXThis(CapturesCXXThis); + this->NumCaptures = Captures.size(); + + if (Captures.empty()) { + this->Captures = nullptr; + return; + } + + this->Captures = Captures.copy(Context).data(); +} + +bool BlockDecl::capturesVariable(const VarDecl *variable) const { + for (const auto &I : captures()) + // Only auto vars can be captured, so no redeclaration worries. + if (I.getVariable() == variable) + return true; + + return false; +} + +SourceRange BlockDecl::getSourceRange() const { + return SourceRange(getLocation(), Body ? Body->getEndLoc() : getLocation()); +} + +//===----------------------------------------------------------------------===// +// Other Decl Allocation/Deallocation Method Implementations +//===----------------------------------------------------------------------===// + +void TranslationUnitDecl::anchor() {} + +TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { + return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C); +} + +void PragmaCommentDecl::anchor() {} + +PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C, + TranslationUnitDecl *DC, + SourceLocation CommentLoc, + PragmaMSCommentKind CommentKind, + StringRef Arg) { + PragmaCommentDecl *PCD = + new (C, DC, additionalSizeToAlloc<char>(Arg.size() + 1)) + PragmaCommentDecl(DC, CommentLoc, CommentKind); + memcpy(PCD->getTrailingObjects<char>(), Arg.data(), Arg.size()); + PCD->getTrailingObjects<char>()[Arg.size()] = '\0'; + return PCD; +} + +PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C, + unsigned ID, + unsigned ArgSize) { + return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1)) + PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown); +} + +void PragmaDetectMismatchDecl::anchor() {} + +PragmaDetectMismatchDecl * +PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC, + SourceLocation Loc, StringRef Name, + StringRef Value) { + size_t ValueStart = Name.size() + 1; + PragmaDetectMismatchDecl *PDMD = + new (C, DC, additionalSizeToAlloc<char>(ValueStart + Value.size() + 1)) + PragmaDetectMismatchDecl(DC, Loc, ValueStart); + memcpy(PDMD->getTrailingObjects<char>(), Name.data(), Name.size()); + PDMD->getTrailingObjects<char>()[Name.size()] = '\0'; + memcpy(PDMD->getTrailingObjects<char>() + ValueStart, Value.data(), + Value.size()); + PDMD->getTrailingObjects<char>()[ValueStart + Value.size()] = '\0'; + return PDMD; +} + +PragmaDetectMismatchDecl * +PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NameValueSize) { + return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1)) + PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0); +} + +void ExternCContextDecl::anchor() {} + +ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C, + TranslationUnitDecl *DC) { + return new (C, DC) ExternCContextDecl(DC); +} + +void LabelDecl::anchor() {} + +LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation IdentL, IdentifierInfo *II) { + return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL); +} + +LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation IdentL, IdentifierInfo *II, + SourceLocation GnuLabelL) { + assert(GnuLabelL != IdentL && "Use this only for GNU local labels"); + return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL); +} + +LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr, + SourceLocation()); +} + +void LabelDecl::setMSAsmLabel(StringRef Name) { +char *Buffer = new (getASTContext(), 1) char[Name.size() + 1]; + memcpy(Buffer, Name.data(), Name.size()); + Buffer[Name.size()] = '\0'; + MSAsmName = Buffer; +} + +void ValueDecl::anchor() {} + +bool ValueDecl::isWeak() const { + auto *MostRecent = getMostRecentDecl(); + return MostRecent->hasAttr<WeakAttr>() || + MostRecent->hasAttr<WeakRefAttr>() || isWeakImported(); +} + +void ImplicitParamDecl::anchor() {} + +ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation IdLoc, + IdentifierInfo *Id, QualType Type, + ImplicitParamKind ParamKind) { + return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind); +} + +ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type, + ImplicitParamKind ParamKind) { + return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind); +} + +ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other); +} + +FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, + QualType T, TypeSourceInfo *TInfo, + StorageClass SC, bool isInlineSpecified, + bool hasWrittenPrototype, + ConstexprSpecKind ConstexprKind, + Expr *TrailingRequiresClause) { + FunctionDecl *New = + new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo, + SC, isInlineSpecified, ConstexprKind, + TrailingRequiresClause); + New->setHasWrittenPrototype(hasWrittenPrototype); + return New; +} + +FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) FunctionDecl( + Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), + nullptr, SC_None, false, ConstexprSpecKind::Unspecified, nullptr); +} + +BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { + return new (C, DC) BlockDecl(DC, L); +} + +BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) BlockDecl(nullptr, SourceLocation()); +} + +CapturedDecl::CapturedDecl(DeclContext *DC, unsigned NumParams) + : Decl(Captured, DC, SourceLocation()), DeclContext(Captured), + NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) {} + +CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC, + unsigned NumParams) { + return new (C, DC, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams)) + CapturedDecl(DC, NumParams); +} + +CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumParams) { + return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams)) + CapturedDecl(nullptr, NumParams); +} + +Stmt *CapturedDecl::getBody() const { return BodyAndNothrow.getPointer(); } +void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); } + +bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); } +void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); } + +EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, + SourceLocation L, + IdentifierInfo *Id, QualType T, + Expr *E, const llvm::APSInt &V) { + return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V); +} + +EnumConstantDecl * +EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr, + QualType(), nullptr, llvm::APSInt()); +} + +void IndirectFieldDecl::anchor() {} + +IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName N, + QualType T, + MutableArrayRef<NamedDecl *> CH) + : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH.data()), + ChainingSize(CH.size()) { + // In C++, indirect field declarations conflict with tag declarations in the + // same scope, so add them to IDNS_Tag so that tag redeclaration finds them. + if (C.getLangOpts().CPlusPlus) + IdentifierNamespace |= IDNS_Tag; +} + +IndirectFieldDecl * +IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, QualType T, + llvm::MutableArrayRef<NamedDecl *> CH) { + return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH); +} + +IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(), + DeclarationName(), QualType(), None); +} + +SourceRange EnumConstantDecl::getSourceRange() const { + SourceLocation End = getLocation(); + if (Init) + End = Init->getEndLoc(); + return SourceRange(getLocation(), End); +} + +void TypeDecl::anchor() {} + +TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) { + return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo); +} + +void TypedefNameDecl::anchor() {} + +TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const { + if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) { + auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl(); + auto *ThisTypedef = this; + if (AnyRedecl && OwningTypedef) { + OwningTypedef = OwningTypedef->getCanonicalDecl(); + ThisTypedef = ThisTypedef->getCanonicalDecl(); + } + if (OwningTypedef == ThisTypedef) + return TT->getDecl(); + } + + return nullptr; +} + +bool TypedefNameDecl::isTransparentTagSlow() const { + auto determineIsTransparent = [&]() { + if (auto *TT = getUnderlyingType()->getAs<TagType>()) { + if (auto *TD = TT->getDecl()) { + if (TD->getName() != getName()) + return false; + SourceLocation TTLoc = getLocation(); + SourceLocation TDLoc = TD->getLocation(); + if (!TTLoc.isMacroID() || !TDLoc.isMacroID()) + return false; + SourceManager &SM = getASTContext().getSourceManager(); + return SM.getSpellingLoc(TTLoc) == SM.getSpellingLoc(TDLoc); + } + } + return false; + }; + + bool isTransparent = determineIsTransparent(); + MaybeModedTInfo.setInt((isTransparent << 1) | 1); + return isTransparent; +} + +TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr); +} + +TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + TypeSourceInfo *TInfo) { + return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo); +} + +TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); +} + +SourceRange TypedefDecl::getSourceRange() const { + SourceLocation RangeEnd = getLocation(); + if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { + if (typeIsPostfix(TInfo->getType())) + RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); + } + return SourceRange(getBeginLoc(), RangeEnd); +} + +SourceRange TypeAliasDecl::getSourceRange() const { + SourceLocation RangeEnd = getBeginLoc(); + if (TypeSourceInfo *TInfo = getTypeSourceInfo()) + RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); + return SourceRange(getBeginLoc(), RangeEnd); +} + +void FileScopeAsmDecl::anchor() {} + +FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, + StringLiteral *Str, + SourceLocation AsmLoc, + SourceLocation RParenLoc) { + return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); +} + +FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(), + SourceLocation()); +} + +void EmptyDecl::anchor() {} + +EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { + return new (C, DC) EmptyDecl(DC, L); +} + +EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) EmptyDecl(nullptr, SourceLocation()); +} + +//===----------------------------------------------------------------------===// +// ImportDecl Implementation +//===----------------------------------------------------------------------===// + +/// Retrieve the number of module identifiers needed to name the given +/// module. +static unsigned getNumModuleIdentifiers(Module *Mod) { + unsigned Result = 1; + while (Mod->Parent) { + Mod = Mod->Parent; + ++Result; + } + return Result; +} + +ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, + Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs) + : Decl(Import, DC, StartLoc), ImportedModule(Imported), + NextLocalImportAndComplete(nullptr, true) { + assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size()); + auto *StoredLocs = getTrailingObjects<SourceLocation>(); + std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(), + StoredLocs); +} + +ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, + Module *Imported, SourceLocation EndLoc) + : Decl(Import, DC, StartLoc), ImportedModule(Imported), + NextLocalImportAndComplete(nullptr, false) { + *getTrailingObjects<SourceLocation>() = EndLoc; +} + +ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs) { + return new (C, DC, + additionalSizeToAlloc<SourceLocation>(IdentifierLocs.size())) + ImportDecl(DC, StartLoc, Imported, IdentifierLocs); +} + +ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + Module *Imported, + SourceLocation EndLoc) { + ImportDecl *Import = new (C, DC, additionalSizeToAlloc<SourceLocation>(1)) + ImportDecl(DC, StartLoc, Imported, EndLoc); + Import->setImplicit(); + return Import; +} + +ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumLocations) { + return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations)) + ImportDecl(EmptyShell()); +} + +ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { + if (!isImportComplete()) + return None; + + const auto *StoredLocs = getTrailingObjects<SourceLocation>(); + return llvm::makeArrayRef(StoredLocs, + getNumModuleIdentifiers(getImportedModule())); +} + +SourceRange ImportDecl::getSourceRange() const { + if (!isImportComplete()) + return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>()); + + return SourceRange(getLocation(), getIdentifierLocs().back()); +} + +//===----------------------------------------------------------------------===// +// ExportDecl Implementation +//===----------------------------------------------------------------------===// + +void ExportDecl::anchor() {} + +ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation ExportLoc) { + return new (C, DC) ExportDecl(DC, ExportLoc); +} + +ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) ExportDecl(nullptr, SourceLocation()); +} |