diff options
author | Jordan Rupprecht <[email protected]> | 2019-05-14 21:58:59 +0000 |
---|---|---|
committer | Jordan Rupprecht <[email protected]> | 2019-05-14 21:58:59 +0000 |
commit | b35a2aa71f76a334a9c98c0a3c3995b5d902d2b9 (patch) | |
tree | cdff4a5d1a715d4ad622fd8f190128b54bebe440 /lib/AST/Decl.cpp | |
parent | 3748d41833787fcbf59cc5624e8d2b042a8991bc (diff) | |
parent | 741e05796da92b46d4f7bcbee00702ff37df6489 (diff) |
Creating branches/google/stable and tags/google/stable/2019-05-14 from r360103upstream/google/stable
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/google/stable@360714 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 380 |
1 files changed, 239 insertions, 141 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 5536358b1e..19fd3882bd 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1,9 +1,8 @@ //===- Decl.cpp - Declaration AST Node Implementation ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -568,7 +567,14 @@ static bool isSingleLineLanguageLinkage(const Decl &D) { return false; } -static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { +/// 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: @@ -576,8 +582,7 @@ static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) { return false; case Decl::ModuleOwnershipKind::Visible: case Decl::ModuleOwnershipKind::VisibleWhenImported: - if (auto *M = D->getOwningModule()) - return M->Kind == Module::ModuleInterfaceUnit; + return isInModulePurview(D); } llvm_unreachable("unexpected module ownership kind"); } @@ -587,9 +592,8 @@ static LinkageInfo getInternalLinkageFor(const NamedDecl *D) { // 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 (auto *M = D->getOwningModule()) - if (M->Kind == Module::ModuleInterfaceUnit) - return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); + if (isInModulePurview(D)) + return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false); return LinkageInfo::internal(); } @@ -599,15 +603,25 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) { // - 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 (auto *M = D->getOwningModule()) - if (M->Kind == Module::ModuleInterfaceUnit) - if (!isExportedFromModuleIntefaceUnit( - cast<NamedDecl>(D->getCanonicalDecl()))) - return LinkageInfo(ModuleLinkage, DefaultVisibility, false); + 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, @@ -619,24 +633,28 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // C++ [basic.link]p3: // A name having namespace scope (3.3.6) has internal linkage if it // is the name of - // - an object, reference, function or function template that is - // explicitly declared static; or, - // (This bullet corresponds to C99 6.2.2p3.) + + 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)) { - // Explicitly declared static. - if (Var->getStorageClass() == SC_Static) - return getInternalLinkageFor(Var); - - // - a non-inline, non-volatile object or reference that is explicitly - // declared const or constexpr and neither explicitly declared extern - // nor previously declared to have external linkage; or (there is no - // equivalent in C99) - // The C++ modules TS adds "non-exported" to this list. + // - 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() && - !isExportedFromModuleIntefaceUnit(Var)) { + !isExportedFromModuleInterfaceUnit(Var) && + !isa<VarTemplateSpecializationDecl>(Var) && + !Var->getDescribedVarTemplate()) { const VarDecl *PrevVar = Var->getPreviousDecl(); if (PrevVar) return getLVForDecl(PrevVar, computation); @@ -656,14 +674,6 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, if (PrevVar->getStorageClass() == SC_Static) return getInternalLinkageFor(Var); } - } else if (const FunctionDecl *Function = D->getAsFunction()) { - // C++ [temp]p4: - // A non-member function template can have internal linkage; any - // other template name shall have external linkage. - - // Explicitly declared static. - if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) - return getInternalLinkageFor(Function); } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) { // - a data member of an anonymous union. const VarDecl *VD = IFD->getVarDecl(); @@ -672,6 +682,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, } 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); @@ -731,10 +743,20 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, // C++ [basic.link]p4: - // A name having namespace scope has external linkage if it is the - // name of + // 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. // - // - an object or reference, unless it has internal linkage; or + // 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: @@ -780,7 +802,7 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, mergeTemplateLV(LV, spec, computation); } - // - a function, unless it has internal linkage; or + // - 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 @@ -834,7 +856,8 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, mergeTemplateLV(LV, spec, computation); } - // - an enumerator belonging to an enumeration with external linkage; + // 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); @@ -842,16 +865,16 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D, return LinkageInfo::none(); LV.merge(EnumLV); - // - a template, unless it is a function template that has - // internal linkage (Clause 14); + // - 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); - // - a namespace (7.3), unless it is declared within an unnamed - // namespace. + // 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)) { @@ -1508,6 +1531,11 @@ Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { } 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"); @@ -1532,10 +1560,16 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); - // For ObjC methods, look through categories and use the interface as context. + // 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; + if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) { + if (auto *MD = PD->getGetterMethodDecl()) + if (auto *ID = MD->getClassInterface()) + Ctx = ID; + } if (Ctx->isFunctionOrMethod()) { printName(OS); @@ -2380,48 +2414,61 @@ bool VarDecl::isNonEscapingByref() const { } VarDecl *VarDecl::getTemplateInstantiationPattern() const { - // If it's a variable template specialization, find the template or partial - // specialization from which it was instantiated. - if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(this)) { - auto From = VDTemplSpec->getInstantiatedFrom(); - if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) { - while (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate()) { - if (NewVTD->isMemberSpecialization()) - break; - VTD = NewVTD; - } - return getDefinitionOrSelf(VTD->getTemplatedDecl()); - } - if (auto *VTPSD = - From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { - while (auto *NewVTPSD = VTPSD->getInstantiatedFromMember()) { - if (NewVTPSD->isMemberSpecialization()) - break; - VTPSD = NewVTPSD; - } - return getDefinitionOrSelf<VarDecl>(VTPSD); - } - } + const VarDecl *VD = this; - if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { + // 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())) { - VarDecl *VD = getInstantiatedFromStaticDataMember(); + VD = VD->getInstantiatedFromStaticDataMember(); while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) VD = NewVD; - return getDefinitionOrSelf(VD); } } - if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { - while (VarTemplate->getInstantiatedFromMemberTemplate()) { - if (VarTemplate->isMemberSpecialization()) + // 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 = VarTemplate->getInstantiatedFromMemberTemplate(); + VarTemplate = NewVT; } return getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); } - return nullptr; + + if (VD == this) + return nullptr; + return getDefinitionOrSelf(const_cast<VarDecl*>(VD)); } VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { @@ -2441,6 +2488,17 @@ TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { 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(); @@ -2501,15 +2559,14 @@ void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, if (VarTemplateSpecializationDecl *Spec = dyn_cast<VarTemplateSpecializationDecl>(this)) { Spec->setSpecializationKind(TSK); - if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && + if (TSK != TSK_ExplicitSpecialization && + PointOfInstantiation.isValid() && Spec->getPointOfInstantiation().isInvalid()) { Spec->setPointOfInstantiation(PointOfInstantiation); if (ASTMutationListener *L = getASTContext().getASTMutationListener()) L->InstantiationRequested(this); } - } - - if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { + } else if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { MSI->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && MSI->getPointOfInstantiation().isInvalid()) { @@ -2982,16 +3039,20 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); } -/// Returns a value indicating whether this function -/// corresponds to a builtin function. +/// 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. -unsigned FunctionDecl::getBuiltinID() const { +/// 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 { if (!getIdentifier()) return 0; @@ -3019,7 +3080,7 @@ unsigned FunctionDecl::getBuiltinID() const { // If the function is marked "overloadable", it has a different mangled name // and is not the C library function. - if (hasAttr<OverloadableAttr>()) + if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>()) return 0; if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) @@ -3030,7 +3091,7 @@ unsigned FunctionDecl::getBuiltinID() const { // function or whether it just has the same name. // If this is a static function, it's not a builtin. - if (getStorageClass() == SC_Static) + if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static) return 0; // OpenCL v1.2 s6.9.f - The library functions defined in @@ -3337,7 +3398,13 @@ FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { } MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { - return TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>(); + if (auto *MSI = + TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>()) + return MSI; + if (auto *FTSI = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) + return FTSI->getMemberSpecializationInfo(); + return nullptr; } void @@ -3356,6 +3423,8 @@ FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const { } void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { + assert(TemplateOrSpecialization.isNull() && + "Member function is already a specialization"); TemplateOrSpecialization = Template; } @@ -3364,19 +3433,15 @@ bool FunctionDecl::isImplicitlyInstantiable() const { if (isInvalidDecl()) return false; - switch (getTemplateSpecializationKind()) { + switch (getTemplateSpecializationKindForInstantiation()) { case TSK_Undeclared: case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: return false; case TSK_ImplicitInstantiation: return true; - // It is possible to instantiate TSK_ExplicitSpecialization kind - // if the FunctionDecl has a class scope specialization pattern. - case TSK_ExplicitSpecialization: - return getClassScopeSpecializationPattern() != nullptr; - case TSK_ExplicitInstantiationDeclaration: // Handled below. break; @@ -3399,26 +3464,12 @@ bool FunctionDecl::isImplicitlyInstantiable() const { } bool FunctionDecl::isTemplateInstantiation() const { - switch (getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - return false; - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - return true; - } - llvm_unreachable("All TSK values handled."); + // FIXME: Remove this, it's not clear what it means. (Which template + // specialization kind?) + return clang::isTemplateInstantiation(getTemplateSpecializationKind()); } FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { - // Handle class scope explicit specialization special case. - if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { - if (auto *Spec = getClassScopeSpecializationPattern()) - return getDefinitionOrSelf(Spec); - return nullptr; - } - // 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 @@ -3434,21 +3485,28 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); } + if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) { + if (!clang::isTemplateInstantiation(Info->getTemplateSpecializationKind())) + return nullptr; + return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom())); + } + + if (!clang::isTemplateInstantiation(getTemplateSpecializationKind())) + return nullptr; + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { - while (Primary->getInstantiatedFromMemberTemplate()) { - // If we have hit a point where the user provided a specialization of - // this template, we're done looking. - if (Primary->isMemberSpecialization()) + // If we hit a point where the user provided a specialization of this + // template, we're done looking. + while (!Primary->isMemberSpecialization()) { + auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate(); + if (!NewPrimary) break; - Primary = Primary->getInstantiatedFromMemberTemplate(); + Primary = NewPrimary; } return getDefinitionOrSelf(Primary->getTemplatedDecl()); } - if (auto *MFD = getInstantiatedFromMemberFunction()) - return getDefinitionOrSelf(MFD); - return nullptr; } @@ -3456,15 +3514,11 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { if (FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization .dyn_cast<FunctionTemplateSpecializationInfo*>()) { - return Info->Template.getPointer(); + return Info->getTemplate(); } return nullptr; } -FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { - return getASTContext().getClassScopeSpecializationPattern(this); -} - FunctionTemplateSpecializationInfo * FunctionDecl::getTemplateSpecializationInfo() const { return TemplateOrSpecialization @@ -3499,15 +3553,19 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, 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"); - FunctionTemplateSpecializationInfo *Info - = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); - if (!Info) - Info = FunctionTemplateSpecializationInfo::Create(C, this, Template, TSK, - TemplateArgs, - TemplateArgsAsWritten, - PointOfInstantiation); + 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); } @@ -3558,14 +3616,47 @@ DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts, TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const { // For a function template specialization, query the specialization // information object. - FunctionTemplateSpecializationInfo *FTSInfo - = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); - if (FTSInfo) + if (FunctionTemplateSpecializationInfo *FTSInfo = + TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) return FTSInfo->getTemplateSpecializationKind(); - MemberSpecializationInfo *MSInfo - = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>(); - if (MSInfo) + 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; @@ -3673,6 +3764,10 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { 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: @@ -3713,6 +3808,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BImemmove; else if (FnInfo->isStr("memcmp")) return Builtin::BImemcmp; + else if (FnInfo->isStr("bcmp")) + return Builtin::BIbcmp; else if (FnInfo->isStr("strncpy")) return Builtin::BIstrncpy; else if (FnInfo->isStr("strncmp")) @@ -4260,6 +4357,7 @@ BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc) setBlockMissingReturnType(true); setIsConversionFromLambda(false); setDoesNotEscape(false); + setCanAvoidCopyToHeap(false); } void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { |