diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
| commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
| tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | |
| parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5604 |
1 files changed, 0 insertions, 5604 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp deleted file mode 100644 index 67343d11d333..000000000000 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ /dev/null @@ -1,5604 +0,0 @@ -//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/ -// -// 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 C++ template instantiation for declarations. -// -//===----------------------------------------------------------------------===/ -#include "clang/Sema/SemaInternal.h" -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTMutationListener.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/DependentDiagnostic.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/PrettyDeclStackTrace.h" -#include "clang/AST/TypeLoc.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/Template.h" -#include "clang/Sema/TemplateInstCallback.h" -#include "llvm/Support/TimeProfiler.h" - -using namespace clang; - -static bool isDeclWithinFunction(const Decl *D) { - const DeclContext *DC = D->getDeclContext(); - if (DC->isFunctionOrMethod()) - return true; - - if (DC->isRecord()) - return cast<CXXRecordDecl>(DC)->isLocalClass(); - - return false; -} - -template<typename DeclT> -static bool SubstQualifier(Sema &SemaRef, const DeclT *OldDecl, DeclT *NewDecl, - const MultiLevelTemplateArgumentList &TemplateArgs) { - if (!OldDecl->getQualifierLoc()) - return false; - - assert((NewDecl->getFriendObjectKind() || - !OldDecl->getLexicalDeclContext()->isDependentContext()) && - "non-friend with qualified name defined in dependent context"); - Sema::ContextRAII SavedContext( - SemaRef, - const_cast<DeclContext *>(NewDecl->getFriendObjectKind() - ? NewDecl->getLexicalDeclContext() - : OldDecl->getLexicalDeclContext())); - - NestedNameSpecifierLoc NewQualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), - TemplateArgs); - - if (!NewQualifierLoc) - return true; - - NewDecl->setQualifierInfo(NewQualifierLoc); - return false; -} - -bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, - DeclaratorDecl *NewDecl) { - return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs); -} - -bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, - TagDecl *NewDecl) { - return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs); -} - -// Include attribute instantiation code. -#include "clang/Sema/AttrTemplateInstantiate.inc" - -static void instantiateDependentAlignedAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AlignedAttr *Aligned, Decl *New, bool IsPackExpansion) { - if (Aligned->isAlignmentExpr()) { - // The alignment expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs); - if (!Result.isInvalid()) - S.AddAlignedAttr(Aligned->getLocation(), New, Result.getAs<Expr>(), - Aligned->getSpellingListIndex(), IsPackExpansion); - } else { - TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(), - TemplateArgs, Aligned->getLocation(), - DeclarationName()); - if (Result) - S.AddAlignedAttr(Aligned->getLocation(), New, Result, - Aligned->getSpellingListIndex(), IsPackExpansion); - } -} - -static void instantiateDependentAlignedAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AlignedAttr *Aligned, Decl *New) { - if (!Aligned->isPackExpansion()) { - instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); - return; - } - - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - if (Aligned->isAlignmentExpr()) - S.collectUnexpandedParameterPacks(Aligned->getAlignmentExpr(), - Unexpanded); - else - S.collectUnexpandedParameterPacks(Aligned->getAlignmentType()->getTypeLoc(), - Unexpanded); - assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); - - // Determine whether we can expand this attribute pack yet. - bool Expand = true, RetainExpansion = false; - Optional<unsigned> NumExpansions; - // FIXME: Use the actual location of the ellipsis. - SourceLocation EllipsisLoc = Aligned->getLocation(); - if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(), - Unexpanded, TemplateArgs, Expand, - RetainExpansion, NumExpansions)) - return; - - if (!Expand) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, -1); - instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, true); - } else { - for (unsigned I = 0; I != *NumExpansions; ++I) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I); - instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); - } - } -} - -static void instantiateDependentAssumeAlignedAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AssumeAlignedAttr *Aligned, Decl *New) { - // The alignment expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - Expr *E, *OE = nullptr; - ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); - if (Result.isInvalid()) - return; - E = Result.getAs<Expr>(); - - if (Aligned->getOffset()) { - Result = S.SubstExpr(Aligned->getOffset(), TemplateArgs); - if (Result.isInvalid()) - return; - OE = Result.getAs<Expr>(); - } - - S.AddAssumeAlignedAttr(Aligned->getLocation(), New, E, OE, - Aligned->getSpellingListIndex()); -} - -static void instantiateDependentAlignValueAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AlignValueAttr *Aligned, Decl *New) { - // The alignment expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); - if (!Result.isInvalid()) - S.AddAlignValueAttr(Aligned->getLocation(), New, Result.getAs<Expr>(), - Aligned->getSpellingListIndex()); -} - -static void instantiateDependentAllocAlignAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AllocAlignAttr *Align, Decl *New) { - Expr *Param = IntegerLiteral::Create( - S.getASTContext(), - llvm::APInt(64, Align->getParamIndex().getSourceIndex()), - S.getASTContext().UnsignedLongLongTy, Align->getLocation()); - S.AddAllocAlignAttr(Align->getLocation(), New, Param, - Align->getSpellingListIndex()); -} - -static Expr *instantiateDependentFunctionAttrCondition( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const Attr *A, Expr *OldCond, const Decl *Tmpl, FunctionDecl *New) { - Expr *Cond = nullptr; - { - Sema::ContextRAII SwitchContext(S, New); - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(OldCond, TemplateArgs); - if (Result.isInvalid()) - return nullptr; - Cond = Result.getAs<Expr>(); - } - if (!Cond->isTypeDependent()) { - ExprResult Converted = S.PerformContextuallyConvertToBool(Cond); - if (Converted.isInvalid()) - return nullptr; - Cond = Converted.get(); - } - - SmallVector<PartialDiagnosticAt, 8> Diags; - if (OldCond->isValueDependent() && !Cond->isValueDependent() && - !Expr::isPotentialConstantExprUnevaluated(Cond, New, Diags)) { - S.Diag(A->getLocation(), diag::err_attr_cond_never_constant_expr) << A; - for (const auto &P : Diags) - S.Diag(P.first, P.second); - return nullptr; - } - return Cond; -} - -static void instantiateDependentEnableIfAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const EnableIfAttr *EIA, const Decl *Tmpl, FunctionDecl *New) { - Expr *Cond = instantiateDependentFunctionAttrCondition( - S, TemplateArgs, EIA, EIA->getCond(), Tmpl, New); - - if (Cond) - New->addAttr(new (S.getASTContext()) EnableIfAttr( - EIA->getLocation(), S.getASTContext(), Cond, EIA->getMessage(), - EIA->getSpellingListIndex())); -} - -static void instantiateDependentDiagnoseIfAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const DiagnoseIfAttr *DIA, const Decl *Tmpl, FunctionDecl *New) { - Expr *Cond = instantiateDependentFunctionAttrCondition( - S, TemplateArgs, DIA, DIA->getCond(), Tmpl, New); - - if (Cond) - New->addAttr(new (S.getASTContext()) DiagnoseIfAttr( - DIA->getLocation(), S.getASTContext(), Cond, DIA->getMessage(), - DIA->getDiagnosticType(), DIA->getArgDependent(), New, - DIA->getSpellingListIndex())); -} - -// Constructs and adds to New a new instance of CUDALaunchBoundsAttr using -// template A as the base and arguments from TemplateArgs. -static void instantiateDependentCUDALaunchBoundsAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const CUDALaunchBoundsAttr &Attr, Decl *New) { - // The alignment expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult Result = S.SubstExpr(Attr.getMaxThreads(), TemplateArgs); - if (Result.isInvalid()) - return; - Expr *MaxThreads = Result.getAs<Expr>(); - - Expr *MinBlocks = nullptr; - if (Attr.getMinBlocks()) { - Result = S.SubstExpr(Attr.getMinBlocks(), TemplateArgs); - if (Result.isInvalid()) - return; - MinBlocks = Result.getAs<Expr>(); - } - - S.AddLaunchBoundsAttr(Attr.getLocation(), New, MaxThreads, MinBlocks, - Attr.getSpellingListIndex()); -} - -static void -instantiateDependentModeAttr(Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs, - const ModeAttr &Attr, Decl *New) { - S.AddModeAttr(Attr.getRange(), New, Attr.getMode(), - Attr.getSpellingListIndex(), /*InInstantiation=*/true); -} - -/// Instantiation of 'declare simd' attribute and its arguments. -static void instantiateOMPDeclareSimdDeclAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const OMPDeclareSimdDeclAttr &Attr, Decl *New) { - // Allow 'this' in clauses with varlists. - if (auto *FTD = dyn_cast<FunctionTemplateDecl>(New)) - New = FTD->getTemplatedDecl(); - auto *FD = cast<FunctionDecl>(New); - auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(FD->getDeclContext()); - SmallVector<Expr *, 4> Uniforms, Aligneds, Alignments, Linears, Steps; - SmallVector<unsigned, 4> LinModifiers; - - auto SubstExpr = [&](Expr *E) -> ExprResult { - if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) - if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) { - Sema::ContextRAII SavedContext(S, FD); - LocalInstantiationScope Local(S); - if (FD->getNumParams() > PVD->getFunctionScopeIndex()) - Local.InstantiatedLocal( - PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); - return S.SubstExpr(E, TemplateArgs); - } - Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), - FD->isCXXInstanceMember()); - return S.SubstExpr(E, TemplateArgs); - }; - - // Substitute a single OpenMP clause, which is a potentially-evaluated - // full-expression. - auto Subst = [&](Expr *E) -> ExprResult { - EnterExpressionEvaluationContext Evaluated( - S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); - ExprResult Res = SubstExpr(E); - if (Res.isInvalid()) - return Res; - return S.ActOnFinishFullExpr(Res.get(), false); - }; - - ExprResult Simdlen; - if (auto *E = Attr.getSimdlen()) - Simdlen = Subst(E); - - if (Attr.uniforms_size() > 0) { - for(auto *E : Attr.uniforms()) { - ExprResult Inst = Subst(E); - if (Inst.isInvalid()) - continue; - Uniforms.push_back(Inst.get()); - } - } - - auto AI = Attr.alignments_begin(); - for (auto *E : Attr.aligneds()) { - ExprResult Inst = Subst(E); - if (Inst.isInvalid()) - continue; - Aligneds.push_back(Inst.get()); - Inst = ExprEmpty(); - if (*AI) - Inst = S.SubstExpr(*AI, TemplateArgs); - Alignments.push_back(Inst.get()); - ++AI; - } - - auto SI = Attr.steps_begin(); - for (auto *E : Attr.linears()) { - ExprResult Inst = Subst(E); - if (Inst.isInvalid()) - continue; - Linears.push_back(Inst.get()); - Inst = ExprEmpty(); - if (*SI) - Inst = S.SubstExpr(*SI, TemplateArgs); - Steps.push_back(Inst.get()); - ++SI; - } - LinModifiers.append(Attr.modifiers_begin(), Attr.modifiers_end()); - (void)S.ActOnOpenMPDeclareSimdDirective( - S.ConvertDeclToDeclGroup(New), Attr.getBranchState(), Simdlen.get(), - Uniforms, Aligneds, Alignments, Linears, LinModifiers, Steps, - Attr.getRange()); -} - -static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AMDGPUFlatWorkGroupSizeAttr &Attr, Decl *New) { - // Both min and max expression are constant expressions. - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult Result = S.SubstExpr(Attr.getMin(), TemplateArgs); - if (Result.isInvalid()) - return; - Expr *MinExpr = Result.getAs<Expr>(); - - Result = S.SubstExpr(Attr.getMax(), TemplateArgs); - if (Result.isInvalid()) - return; - Expr *MaxExpr = Result.getAs<Expr>(); - - S.addAMDGPUFlatWorkGroupSizeAttr(Attr.getLocation(), New, MinExpr, MaxExpr, - Attr.getSpellingListIndex()); -} - -static ExplicitSpecifier -instantiateExplicitSpecifier(Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs, - ExplicitSpecifier ES, FunctionDecl *New) { - if (!ES.getExpr()) - return ES; - Expr *OldCond = ES.getExpr(); - Expr *Cond = nullptr; - { - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult SubstResult = S.SubstExpr(OldCond, TemplateArgs); - if (SubstResult.isInvalid()) { - return ExplicitSpecifier::Invalid(); - } - Cond = SubstResult.get(); - } - ExplicitSpecifier Result(Cond, ES.getKind()); - if (!Cond->isTypeDependent()) - S.tryResolveExplicitSpecifier(Result); - return Result; -} - -static void instantiateDependentAMDGPUWavesPerEUAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AMDGPUWavesPerEUAttr &Attr, Decl *New) { - // Both min and max expression are constant expressions. - EnterExpressionEvaluationContext Unevaluated( - S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult Result = S.SubstExpr(Attr.getMin(), TemplateArgs); - if (Result.isInvalid()) - return; - Expr *MinExpr = Result.getAs<Expr>(); - - Expr *MaxExpr = nullptr; - if (auto Max = Attr.getMax()) { - Result = S.SubstExpr(Max, TemplateArgs); - if (Result.isInvalid()) - return; - MaxExpr = Result.getAs<Expr>(); - } - - S.addAMDGPUWavesPerEUAttr(Attr.getLocation(), New, MinExpr, MaxExpr, - Attr.getSpellingListIndex()); -} - -void Sema::InstantiateAttrsForDecl( - const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, - Decl *New, LateInstantiatedAttrVec *LateAttrs, - LocalInstantiationScope *OuterMostScope) { - if (NamedDecl *ND = dyn_cast<NamedDecl>(New)) { - for (const auto *TmplAttr : Tmpl->attrs()) { - // FIXME: If any of the special case versions from InstantiateAttrs become - // applicable to template declaration, we'll need to add them here. - CXXThisScopeRAII ThisScope( - *this, dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()), - Qualifiers(), ND->isCXXInstanceMember()); - - Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( - TmplAttr, Context, *this, TemplateArgs); - if (NewAttr) - New->addAttr(NewAttr); - } - } -} - -static Sema::RetainOwnershipKind -attrToRetainOwnershipKind(const Attr *A) { - switch (A->getKind()) { - case clang::attr::CFConsumed: - return Sema::RetainOwnershipKind::CF; - case clang::attr::OSConsumed: - return Sema::RetainOwnershipKind::OS; - case clang::attr::NSConsumed: - return Sema::RetainOwnershipKind::NS; - default: - llvm_unreachable("Wrong argument supplied"); - } -} - -void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Tmpl, Decl *New, - LateInstantiatedAttrVec *LateAttrs, - LocalInstantiationScope *OuterMostScope) { - for (const auto *TmplAttr : Tmpl->attrs()) { - // FIXME: This should be generalized to more than just the AlignedAttr. - const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr); - if (Aligned && Aligned->isAlignmentDependent()) { - instantiateDependentAlignedAttr(*this, TemplateArgs, Aligned, New); - continue; - } - - const AssumeAlignedAttr *AssumeAligned = dyn_cast<AssumeAlignedAttr>(TmplAttr); - if (AssumeAligned) { - instantiateDependentAssumeAlignedAttr(*this, TemplateArgs, AssumeAligned, New); - continue; - } - - const AlignValueAttr *AlignValue = dyn_cast<AlignValueAttr>(TmplAttr); - if (AlignValue) { - instantiateDependentAlignValueAttr(*this, TemplateArgs, AlignValue, New); - continue; - } - - if (const auto *AllocAlign = dyn_cast<AllocAlignAttr>(TmplAttr)) { - instantiateDependentAllocAlignAttr(*this, TemplateArgs, AllocAlign, New); - continue; - } - - - if (const auto *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr)) { - instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, - cast<FunctionDecl>(New)); - continue; - } - - if (const auto *DiagnoseIf = dyn_cast<DiagnoseIfAttr>(TmplAttr)) { - instantiateDependentDiagnoseIfAttr(*this, TemplateArgs, DiagnoseIf, Tmpl, - cast<FunctionDecl>(New)); - continue; - } - - if (const CUDALaunchBoundsAttr *CUDALaunchBounds = - dyn_cast<CUDALaunchBoundsAttr>(TmplAttr)) { - instantiateDependentCUDALaunchBoundsAttr(*this, TemplateArgs, - *CUDALaunchBounds, New); - continue; - } - - if (const ModeAttr *Mode = dyn_cast<ModeAttr>(TmplAttr)) { - instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New); - continue; - } - - if (const auto *OMPAttr = dyn_cast<OMPDeclareSimdDeclAttr>(TmplAttr)) { - instantiateOMPDeclareSimdDeclAttr(*this, TemplateArgs, *OMPAttr, New); - continue; - } - - if (const AMDGPUFlatWorkGroupSizeAttr *AMDGPUFlatWorkGroupSize = - dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(TmplAttr)) { - instantiateDependentAMDGPUFlatWorkGroupSizeAttr( - *this, TemplateArgs, *AMDGPUFlatWorkGroupSize, New); - } - - if (const AMDGPUWavesPerEUAttr *AMDGPUFlatWorkGroupSize = - dyn_cast<AMDGPUWavesPerEUAttr>(TmplAttr)) { - instantiateDependentAMDGPUWavesPerEUAttr(*this, TemplateArgs, - *AMDGPUFlatWorkGroupSize, New); - } - - // Existing DLL attribute on the instantiation takes precedence. - if (TmplAttr->getKind() == attr::DLLExport || - TmplAttr->getKind() == attr::DLLImport) { - if (New->hasAttr<DLLExportAttr>() || New->hasAttr<DLLImportAttr>()) { - continue; - } - } - - if (auto ABIAttr = dyn_cast<ParameterABIAttr>(TmplAttr)) { - AddParameterABIAttr(ABIAttr->getRange(), New, ABIAttr->getABI(), - ABIAttr->getSpellingListIndex()); - continue; - } - - if (isa<NSConsumedAttr>(TmplAttr) || isa<OSConsumedAttr>(TmplAttr) || - isa<CFConsumedAttr>(TmplAttr)) { - AddXConsumedAttr(New, TmplAttr->getRange(), - TmplAttr->getSpellingListIndex(), - attrToRetainOwnershipKind(TmplAttr), - /*template instantiation=*/true); - continue; - } - - assert(!TmplAttr->isPackExpansion()); - if (TmplAttr->isLateParsed() && LateAttrs) { - // Late parsed attributes must be instantiated and attached after the - // enclosing class has been instantiated. See Sema::InstantiateClass. - LocalInstantiationScope *Saved = nullptr; - if (CurrentInstantiationScope) - Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope); - LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New)); - } else { - // Allow 'this' within late-parsed attributes. - NamedDecl *ND = dyn_cast<NamedDecl>(New); - CXXRecordDecl *ThisContext = - dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); - CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), - ND && ND->isCXXInstanceMember()); - - Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, - *this, TemplateArgs); - if (NewAttr) - New->addAttr(NewAttr); - } - } -} - -/// Get the previous declaration of a declaration for the purposes of template -/// instantiation. If this finds a previous declaration, then the previous -/// declaration of the instantiation of D should be an instantiation of the -/// result of this function. -template<typename DeclT> -static DeclT *getPreviousDeclForInstantiation(DeclT *D) { - DeclT *Result = D->getPreviousDecl(); - - // If the declaration is within a class, and the previous declaration was - // merged from a different definition of that class, then we don't have a - // previous declaration for the purpose of template instantiation. - if (Result && isa<CXXRecordDecl>(D->getDeclContext()) && - D->getLexicalDeclContext() != Result->getLexicalDeclContext()) - return nullptr; - - return Result; -} - -Decl * -TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { - llvm_unreachable("Translation units cannot be instantiated"); -} - -Decl * -TemplateDeclInstantiator::VisitPragmaCommentDecl(PragmaCommentDecl *D) { - llvm_unreachable("pragma comment cannot be instantiated"); -} - -Decl *TemplateDeclInstantiator::VisitPragmaDetectMismatchDecl( - PragmaDetectMismatchDecl *D) { - llvm_unreachable("pragma comment cannot be instantiated"); -} - -Decl * -TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) { - llvm_unreachable("extern \"C\" context cannot be instantiated"); -} - -Decl * -TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { - LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getIdentifier()); - Owner->addDecl(Inst); - return Inst; -} - -Decl * -TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { - llvm_unreachable("Namespaces cannot be instantiated"); -} - -Decl * -TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { - NamespaceAliasDecl *Inst - = NamespaceAliasDecl::Create(SemaRef.Context, Owner, - D->getNamespaceLoc(), - D->getAliasLoc(), - D->getIdentifier(), - D->getQualifierLoc(), - D->getTargetNameLoc(), - D->getNamespace()); - Owner->addDecl(Inst); - return Inst; -} - -Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, - bool IsTypeAlias) { - bool Invalid = false; - TypeSourceInfo *DI = D->getTypeSourceInfo(); - if (DI->getType()->isInstantiationDependentType() || - DI->getType()->isVariablyModifiedType()) { - DI = SemaRef.SubstType(DI, TemplateArgs, - D->getLocation(), D->getDeclName()); - if (!DI) { - Invalid = true; - DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy); - } - } else { - SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); - } - - // HACK: g++ has a bug where it gets the value kind of ?: wrong. - // libstdc++ relies upon this bug in its implementation of common_type. - // If we happen to be processing that implementation, fake up the g++ ?: - // semantics. See LWG issue 2141 for more information on the bug. - const DecltypeType *DT = DI->getType()->getAs<DecltypeType>(); - CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()); - if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) && - DT->isReferenceType() && - RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() && - RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") && - D->getIdentifier() && D->getIdentifier()->isStr("type") && - SemaRef.getSourceManager().isInSystemHeader(D->getBeginLoc())) - // Fold it to the (non-reference) type which g++ would have produced. - DI = SemaRef.Context.getTrivialTypeSourceInfo( - DI->getType().getNonReferenceType()); - - // Create the new typedef - TypedefNameDecl *Typedef; - if (IsTypeAlias) - Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(), - D->getLocation(), D->getIdentifier(), DI); - else - Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(), - D->getLocation(), D->getIdentifier(), DI); - if (Invalid) - Typedef->setInvalidDecl(); - - // If the old typedef was the name for linkage purposes of an anonymous - // tag decl, re-establish that relationship for the new typedef. - if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) { - TagDecl *oldTag = oldTagType->getDecl(); - if (oldTag->getTypedefNameForAnonDecl() == D && !Invalid) { - TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl(); - assert(!newTag->hasNameForLinkage()); - newTag->setTypedefNameForAnonDecl(Typedef); - } - } - - if (TypedefNameDecl *Prev = getPreviousDeclForInstantiation(D)) { - NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, - TemplateArgs); - if (!InstPrev) - return nullptr; - - TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev); - - // If the typedef types are not identical, reject them. - SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef); - - Typedef->setPreviousDecl(InstPrevTypedef); - } - - SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); - - Typedef->setAccess(D->getAccess()); - - return Typedef; -} - -Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { - Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); - if (Typedef) - Owner->addDecl(Typedef); - return Typedef; -} - -Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { - Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); - if (Typedef) - Owner->addDecl(Typedef); - return Typedef; -} - -Decl * -TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { - // Create a local instantiation scope for this type alias template, which - // will contain the instantiations of the template parameters. - LocalInstantiationScope Scope(SemaRef); - - TemplateParameterList *TempParams = D->getTemplateParameters(); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - - TypeAliasDecl *Pattern = D->getTemplatedDecl(); - - TypeAliasTemplateDecl *PrevAliasTemplate = nullptr; - if (getPreviousDeclForInstantiation<TypedefNameDecl>(Pattern)) { - DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); - if (!Found.empty()) { - PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Found.front()); - } - } - - TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>( - InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true)); - if (!AliasInst) - return nullptr; - - TypeAliasTemplateDecl *Inst - = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getDeclName(), InstParams, AliasInst); - AliasInst->setDescribedAliasTemplate(Inst); - if (PrevAliasTemplate) - Inst->setPreviousDecl(PrevAliasTemplate); - - Inst->setAccess(D->getAccess()); - - if (!PrevAliasTemplate) - Inst->setInstantiatedFromMemberTemplate(D); - - Owner->addDecl(Inst); - - return Inst; -} - -Decl *TemplateDeclInstantiator::VisitBindingDecl(BindingDecl *D) { - auto *NewBD = BindingDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getIdentifier()); - NewBD->setReferenced(D->isReferenced()); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewBD); - return NewBD; -} - -Decl *TemplateDeclInstantiator::VisitDecompositionDecl(DecompositionDecl *D) { - // Transform the bindings first. - SmallVector<BindingDecl*, 16> NewBindings; - for (auto *OldBD : D->bindings()) - NewBindings.push_back(cast<BindingDecl>(VisitBindingDecl(OldBD))); - ArrayRef<BindingDecl*> NewBindingArray = NewBindings; - - auto *NewDD = cast_or_null<DecompositionDecl>( - VisitVarDecl(D, /*InstantiatingVarTemplate=*/false, &NewBindingArray)); - - if (!NewDD || NewDD->isInvalidDecl()) - for (auto *NewBD : NewBindings) - NewBD->setInvalidDecl(); - - return NewDD; -} - -Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { - return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false); -} - -Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, - bool InstantiatingVarTemplate, - ArrayRef<BindingDecl*> *Bindings) { - - // Do substitution on the type of the declaration - TypeSourceInfo *DI = SemaRef.SubstType( - D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(), - D->getDeclName(), /*AllowDeducedTST*/true); - if (!DI) - return nullptr; - - if (DI->getType()->isFunctionType()) { - SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function) - << D->isStaticDataMember() << DI->getType(); - return nullptr; - } - - DeclContext *DC = Owner; - if (D->isLocalExternDecl()) - SemaRef.adjustContextForLocalExternDecl(DC); - - // Build the instantiated declaration. - VarDecl *Var; - if (Bindings) - Var = DecompositionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), - D->getLocation(), DI->getType(), DI, - D->getStorageClass(), *Bindings); - else - Var = VarDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), - D->getLocation(), D->getIdentifier(), DI->getType(), - DI, D->getStorageClass()); - - // In ARC, infer 'retaining' for variables of retainable type. - if (SemaRef.getLangOpts().ObjCAutoRefCount && - SemaRef.inferObjCARCLifetime(Var)) - Var->setInvalidDecl(); - - // Substitute the nested name specifier, if any. - if (SubstQualifier(D, Var)) - return nullptr; - - SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, - StartingScope, InstantiatingVarTemplate); - - if (D->isNRVOVariable()) { - QualType ReturnType = cast<FunctionDecl>(DC)->getReturnType(); - if (SemaRef.isCopyElisionCandidate(ReturnType, Var, Sema::CES_Strict)) - Var->setNRVOVariable(true); - } - - Var->setImplicit(D->isImplicit()); - - if (Var->isStaticLocal()) - SemaRef.CheckStaticLocalForDllExport(Var); - - return Var; -} - -Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) { - AccessSpecDecl* AD - = AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner, - D->getAccessSpecifierLoc(), D->getColonLoc()); - Owner->addHiddenDecl(AD); - return AD; -} - -Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { - bool Invalid = false; - TypeSourceInfo *DI = D->getTypeSourceInfo(); - if (DI->getType()->isInstantiationDependentType() || - DI->getType()->isVariablyModifiedType()) { - DI = SemaRef.SubstType(DI, TemplateArgs, - D->getLocation(), D->getDeclName()); - if (!DI) { - DI = D->getTypeSourceInfo(); - Invalid = true; - } else if (DI->getType()->isFunctionType()) { - // C++ [temp.arg.type]p3: - // If a declaration acquires a function type through a type - // dependent on a template-parameter and this causes a - // declaration that does not use the syntactic form of a - // function declarator to have function type, the program is - // ill-formed. - SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) - << DI->getType(); - Invalid = true; - } - } else { - SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); - } - - Expr *BitWidth = D->getBitWidth(); - if (Invalid) - BitWidth = nullptr; - else if (BitWidth) { - // The bit-width expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult InstantiatedBitWidth - = SemaRef.SubstExpr(BitWidth, TemplateArgs); - if (InstantiatedBitWidth.isInvalid()) { - Invalid = true; - BitWidth = nullptr; - } else - BitWidth = InstantiatedBitWidth.getAs<Expr>(); - } - - FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), - DI->getType(), DI, - cast<RecordDecl>(Owner), - D->getLocation(), - D->isMutable(), - BitWidth, - D->getInClassInitStyle(), - D->getInnerLocStart(), - D->getAccess(), - nullptr); - if (!Field) { - cast<Decl>(Owner)->setInvalidDecl(); - return nullptr; - } - - SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope); - - if (Field->hasAttrs()) - SemaRef.CheckAlignasUnderalignment(Field); - - if (Invalid) - Field->setInvalidDecl(); - - if (!Field->getDeclName()) { - // Keep track of where this decl came from. - SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D); - } - if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) { - if (Parent->isAnonymousStructOrUnion() && - Parent->getRedeclContext()->isFunctionOrMethod()) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field); - } - - Field->setImplicit(D->isImplicit()); - Field->setAccess(D->getAccess()); - Owner->addDecl(Field); - - return Field; -} - -Decl *TemplateDeclInstantiator::VisitMSPropertyDecl(MSPropertyDecl *D) { - bool Invalid = false; - TypeSourceInfo *DI = D->getTypeSourceInfo(); - - if (DI->getType()->isVariablyModifiedType()) { - SemaRef.Diag(D->getLocation(), diag::err_property_is_variably_modified) - << D; - Invalid = true; - } else if (DI->getType()->isInstantiationDependentType()) { - DI = SemaRef.SubstType(DI, TemplateArgs, - D->getLocation(), D->getDeclName()); - if (!DI) { - DI = D->getTypeSourceInfo(); - Invalid = true; - } else if (DI->getType()->isFunctionType()) { - // C++ [temp.arg.type]p3: - // If a declaration acquires a function type through a type - // dependent on a template-parameter and this causes a - // declaration that does not use the syntactic form of a - // function declarator to have function type, the program is - // ill-formed. - SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) - << DI->getType(); - Invalid = true; - } - } else { - SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); - } - - MSPropertyDecl *Property = MSPropertyDecl::Create( - SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), DI->getType(), - DI, D->getBeginLoc(), D->getGetterId(), D->getSetterId()); - - SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs, - StartingScope); - - if (Invalid) - Property->setInvalidDecl(); - - Property->setAccess(D->getAccess()); - Owner->addDecl(Property); - - return Property; -} - -Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { - NamedDecl **NamedChain = - new (SemaRef.Context)NamedDecl*[D->getChainingSize()]; - - int i = 0; - for (auto *PI : D->chain()) { - NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), PI, - TemplateArgs); - if (!Next) - return nullptr; - - NamedChain[i++] = Next; - } - - QualType T = cast<FieldDecl>(NamedChain[i-1])->getType(); - IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create( - SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), T, - {NamedChain, D->getChainingSize()}); - - for (const auto *Attr : D->attrs()) - IndirectField->addAttr(Attr->clone(SemaRef.Context)); - - IndirectField->setImplicit(D->isImplicit()); - IndirectField->setAccess(D->getAccess()); - Owner->addDecl(IndirectField); - return IndirectField; -} - -Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { - // Handle friend type expressions by simply substituting template - // parameters into the pattern type and checking the result. - if (TypeSourceInfo *Ty = D->getFriendType()) { - TypeSourceInfo *InstTy; - // If this is an unsupported friend, don't bother substituting template - // arguments into it. The actual type referred to won't be used by any - // parts of Clang, and may not be valid for instantiating. Just use the - // same info for the instantiated friend. - if (D->isUnsupportedFriend()) { - InstTy = Ty; - } else { - InstTy = SemaRef.SubstType(Ty, TemplateArgs, - D->getLocation(), DeclarationName()); - } - if (!InstTy) - return nullptr; - - FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getBeginLoc(), - D->getFriendLoc(), InstTy); - if (!FD) - return nullptr; - - FD->setAccess(AS_public); - FD->setUnsupportedFriend(D->isUnsupportedFriend()); - Owner->addDecl(FD); - return FD; - } - - NamedDecl *ND = D->getFriendDecl(); - assert(ND && "friend decl must be a decl or a type!"); - - // All of the Visit implementations for the various potential friend - // declarations have to be carefully written to work for friend - // objects, with the most important detail being that the target - // decl should almost certainly not be placed in Owner. - Decl *NewND = Visit(ND); - if (!NewND) return nullptr; - - FriendDecl *FD = - FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), - cast<NamedDecl>(NewND), D->getFriendLoc()); - FD->setAccess(AS_public); - FD->setUnsupportedFriend(D->isUnsupportedFriend()); - Owner->addDecl(FD); - return FD; -} - -Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { - Expr *AssertExpr = D->getAssertExpr(); - - // The expression in a static assertion is a constant expression. - EnterExpressionEvaluationContext Unevaluated( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult InstantiatedAssertExpr - = SemaRef.SubstExpr(AssertExpr, TemplateArgs); - if (InstantiatedAssertExpr.isInvalid()) - return nullptr; - - return SemaRef.BuildStaticAssertDeclaration(D->getLocation(), - InstantiatedAssertExpr.get(), - D->getMessage(), - D->getRParenLoc(), - D->isFailed()); -} - -Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { - EnumDecl *PrevDecl = nullptr; - if (EnumDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { - NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), - PatternPrev, - TemplateArgs); - if (!Prev) return nullptr; - PrevDecl = cast<EnumDecl>(Prev); - } - - EnumDecl *Enum = - EnumDecl::Create(SemaRef.Context, Owner, D->getBeginLoc(), - D->getLocation(), D->getIdentifier(), PrevDecl, - D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); - if (D->isFixed()) { - if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) { - // If we have type source information for the underlying type, it means it - // has been explicitly set by the user. Perform substitution on it before - // moving on. - SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); - TypeSourceInfo *NewTI = SemaRef.SubstType(TI, TemplateArgs, UnderlyingLoc, - DeclarationName()); - if (!NewTI || SemaRef.CheckEnumUnderlyingType(NewTI)) - Enum->setIntegerType(SemaRef.Context.IntTy); - else - Enum->setIntegerTypeSourceInfo(NewTI); - } else { - assert(!D->getIntegerType()->isDependentType() - && "Dependent type without type source info"); - Enum->setIntegerType(D->getIntegerType()); - } - } - - SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); - - Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation); - Enum->setAccess(D->getAccess()); - // Forward the mangling number from the template to the instantiated decl. - SemaRef.Context.setManglingNumber(Enum, SemaRef.Context.getManglingNumber(D)); - // See if the old tag was defined along with a declarator. - // If it did, mark the new tag as being associated with that declarator. - if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) - SemaRef.Context.addDeclaratorForUnnamedTagDecl(Enum, DD); - // See if the old tag was defined along with a typedef. - // If it did, mark the new tag as being associated with that typedef. - if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) - SemaRef.Context.addTypedefNameForUnnamedTagDecl(Enum, TND); - if (SubstQualifier(D, Enum)) return nullptr; - Owner->addDecl(Enum); - - EnumDecl *Def = D->getDefinition(); - if (Def && Def != D) { - // If this is an out-of-line definition of an enum member template, check - // that the underlying types match in the instantiation of both - // declarations. - if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) { - SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); - QualType DefnUnderlying = - SemaRef.SubstType(TI->getType(), TemplateArgs, - UnderlyingLoc, DeclarationName()); - SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), - DefnUnderlying, /*IsFixed=*/true, Enum); - } - } - - // C++11 [temp.inst]p1: The implicit instantiation of a class template - // specialization causes the implicit instantiation of the declarations, but - // not the definitions of scoped member enumerations. - // - // DR1484 clarifies that enumeration definitions inside of a template - // declaration aren't considered entities that can be separately instantiated - // from the rest of the entity they are declared inside of. - if (isDeclWithinFunction(D) ? D == Def : Def && !Enum->isScoped()) { - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); - InstantiateEnumDefinition(Enum, Def); - } - - return Enum; -} - -void TemplateDeclInstantiator::InstantiateEnumDefinition( - EnumDecl *Enum, EnumDecl *Pattern) { - Enum->startDefinition(); - - // Update the location to refer to the definition. - Enum->setLocation(Pattern->getLocation()); - - SmallVector<Decl*, 4> Enumerators; - - EnumConstantDecl *LastEnumConst = nullptr; - for (auto *EC : Pattern->enumerators()) { - // The specified value for the enumerator. - ExprResult Value((Expr *)nullptr); - if (Expr *UninstValue = EC->getInitExpr()) { - // The enumerator's value expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - - Value = SemaRef.SubstExpr(UninstValue, TemplateArgs); - } - - // Drop the initial value and continue. - bool isInvalid = false; - if (Value.isInvalid()) { - Value = nullptr; - isInvalid = true; - } - - EnumConstantDecl *EnumConst - = SemaRef.CheckEnumConstant(Enum, LastEnumConst, - EC->getLocation(), EC->getIdentifier(), - Value.get()); - - if (isInvalid) { - if (EnumConst) - EnumConst->setInvalidDecl(); - Enum->setInvalidDecl(); - } - - if (EnumConst) { - SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst); - - EnumConst->setAccess(Enum->getAccess()); - Enum->addDecl(EnumConst); - Enumerators.push_back(EnumConst); - LastEnumConst = EnumConst; - - if (Pattern->getDeclContext()->isFunctionOrMethod() && - !Enum->isScoped()) { - // If the enumeration is within a function or method, record the enum - // constant as a local. - SemaRef.CurrentInstantiationScope->InstantiatedLocal(EC, EnumConst); - } - } - } - - SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum, - Enumerators, nullptr, ParsedAttributesView()); -} - -Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { - llvm_unreachable("EnumConstantDecls can only occur within EnumDecls."); -} - -Decl * -TemplateDeclInstantiator::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { - llvm_unreachable("BuiltinTemplateDecls cannot be instantiated."); -} - -Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { - bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); - - // Create a local instantiation scope for this class template, which - // will contain the instantiations of the template parameters. - LocalInstantiationScope Scope(SemaRef); - TemplateParameterList *TempParams = D->getTemplateParameters(); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - - CXXRecordDecl *Pattern = D->getTemplatedDecl(); - - // Instantiate the qualifier. We have to do this first in case - // we're a friend declaration, because if we are then we need to put - // the new declaration in the appropriate context. - NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc(); - if (QualifierLoc) { - QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, - TemplateArgs); - if (!QualifierLoc) - return nullptr; - } - - CXXRecordDecl *PrevDecl = nullptr; - ClassTemplateDecl *PrevClassTemplate = nullptr; - - if (!isFriend && getPreviousDeclForInstantiation(Pattern)) { - DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); - if (!Found.empty()) { - PrevClassTemplate = dyn_cast<ClassTemplateDecl>(Found.front()); - if (PrevClassTemplate) - PrevDecl = PrevClassTemplate->getTemplatedDecl(); - } - } - - // If this isn't a friend, then it's a member template, in which - // case we just want to build the instantiation in the - // specialization. If it is a friend, we want to build it in - // the appropriate context. - DeclContext *DC = Owner; - if (isFriend) { - if (QualifierLoc) { - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - DC = SemaRef.computeDeclContext(SS); - if (!DC) return nullptr; - } else { - DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(), - Pattern->getDeclContext(), - TemplateArgs); - } - - // Look for a previous declaration of the template in the owning - // context. - LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(), - Sema::LookupOrdinaryName, - SemaRef.forRedeclarationInCurContext()); - SemaRef.LookupQualifiedName(R, DC); - - if (R.isSingleResult()) { - PrevClassTemplate = R.getAsSingle<ClassTemplateDecl>(); - if (PrevClassTemplate) - PrevDecl = PrevClassTemplate->getTemplatedDecl(); - } - - if (!PrevClassTemplate && QualifierLoc) { - SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) - << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC - << QualifierLoc.getSourceRange(); - return nullptr; - } - - bool AdoptedPreviousTemplateParams = false; - if (PrevClassTemplate) { - bool Complain = true; - - // HACK: libstdc++ 4.2.1 contains an ill-formed friend class - // template for struct std::tr1::__detail::_Map_base, where the - // template parameters of the friend declaration don't match the - // template parameters of the original declaration. In this one - // case, we don't complain about the ill-formed friend - // declaration. - if (isFriend && Pattern->getIdentifier() && - Pattern->getIdentifier()->isStr("_Map_base") && - DC->isNamespace() && - cast<NamespaceDecl>(DC)->getIdentifier() && - cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) { - DeclContext *DCParent = DC->getParent(); - if (DCParent->isNamespace() && - cast<NamespaceDecl>(DCParent)->getIdentifier() && - cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) { - if (cast<Decl>(DCParent)->isInStdNamespace()) - Complain = false; - } - } - - TemplateParameterList *PrevParams - = PrevClassTemplate->getMostRecentDecl()->getTemplateParameters(); - - // Make sure the parameter lists match. - if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, - Complain, - Sema::TPL_TemplateMatch)) { - if (Complain) - return nullptr; - - AdoptedPreviousTemplateParams = true; - InstParams = PrevParams; - } - - // Do some additional validation, then merge default arguments - // from the existing declarations. - if (!AdoptedPreviousTemplateParams && - SemaRef.CheckTemplateParameterList(InstParams, PrevParams, - Sema::TPC_ClassTemplate)) - return nullptr; - } - } - - CXXRecordDecl *RecordInst = CXXRecordDecl::Create( - SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(), - Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl, - /*DelayTypeCreation=*/true); - - if (QualifierLoc) - RecordInst->setQualifierInfo(QualifierLoc); - - SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, - StartingScope); - - ClassTemplateDecl *Inst - = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), - D->getIdentifier(), InstParams, RecordInst); - assert(!(isFriend && Owner->isDependentContext())); - Inst->setPreviousDecl(PrevClassTemplate); - - RecordInst->setDescribedClassTemplate(Inst); - - if (isFriend) { - if (PrevClassTemplate) - Inst->setAccess(PrevClassTemplate->getAccess()); - else - Inst->setAccess(D->getAccess()); - - Inst->setObjectOfFriendDecl(); - // TODO: do we want to track the instantiation progeny of this - // friend target decl? - } else { - Inst->setAccess(D->getAccess()); - if (!PrevClassTemplate) - Inst->setInstantiatedFromMemberTemplate(D); - } - - // Trigger creation of the type for the instantiation. - SemaRef.Context.getInjectedClassNameType(RecordInst, - Inst->getInjectedClassNameSpecialization()); - - // Finish handling of friends. - if (isFriend) { - DC->makeDeclVisibleInContext(Inst); - Inst->setLexicalDeclContext(Owner); - RecordInst->setLexicalDeclContext(Owner); - return Inst; - } - - if (D->isOutOfLine()) { - Inst->setLexicalDeclContext(D->getLexicalDeclContext()); - RecordInst->setLexicalDeclContext(D->getLexicalDeclContext()); - } - - Owner->addDecl(Inst); - - if (!PrevClassTemplate) { - // Queue up any out-of-line partial specializations of this member - // class template; the client will force their instantiation once - // the enclosing class has been instantiated. - SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; - D->getPartialSpecializations(PartialSpecs); - for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) - if (PartialSpecs[I]->getFirstDecl()->isOutOfLine()) - OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I])); - } - - return Inst; -} - -Decl * -TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D) { - ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); - - // Lookup the already-instantiated declaration in the instantiation - // of the class template and return that. - DeclContext::lookup_result Found - = Owner->lookup(ClassTemplate->getDeclName()); - if (Found.empty()) - return nullptr; - - ClassTemplateDecl *InstClassTemplate - = dyn_cast<ClassTemplateDecl>(Found.front()); - if (!InstClassTemplate) - return nullptr; - - if (ClassTemplatePartialSpecializationDecl *Result - = InstClassTemplate->findPartialSpecInstantiatedFromMember(D)) - return Result; - - return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D); -} - -Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) { - assert(D->getTemplatedDecl()->isStaticDataMember() && - "Only static data member templates are allowed."); - - // Create a local instantiation scope for this variable template, which - // will contain the instantiations of the template parameters. - LocalInstantiationScope Scope(SemaRef); - TemplateParameterList *TempParams = D->getTemplateParameters(); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - - VarDecl *Pattern = D->getTemplatedDecl(); - VarTemplateDecl *PrevVarTemplate = nullptr; - - if (getPreviousDeclForInstantiation(Pattern)) { - DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); - if (!Found.empty()) - PrevVarTemplate = dyn_cast<VarTemplateDecl>(Found.front()); - } - - VarDecl *VarInst = - cast_or_null<VarDecl>(VisitVarDecl(Pattern, - /*InstantiatingVarTemplate=*/true)); - if (!VarInst) return nullptr; - - DeclContext *DC = Owner; - - VarTemplateDecl *Inst = VarTemplateDecl::Create( - SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, - VarInst); - VarInst->setDescribedVarTemplate(Inst); - Inst->setPreviousDecl(PrevVarTemplate); - - Inst->setAccess(D->getAccess()); - if (!PrevVarTemplate) - Inst->setInstantiatedFromMemberTemplate(D); - - if (D->isOutOfLine()) { - Inst->setLexicalDeclContext(D->getLexicalDeclContext()); - VarInst->setLexicalDeclContext(D->getLexicalDeclContext()); - } - - Owner->addDecl(Inst); - - if (!PrevVarTemplate) { - // Queue up any out-of-line partial specializations of this member - // variable template; the client will force their instantiation once - // the enclosing class has been instantiated. - SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs; - D->getPartialSpecializations(PartialSpecs); - for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) - if (PartialSpecs[I]->getFirstDecl()->isOutOfLine()) - OutOfLineVarPartialSpecs.push_back( - std::make_pair(Inst, PartialSpecs[I])); - } - - return Inst; -} - -Decl *TemplateDeclInstantiator::VisitVarTemplatePartialSpecializationDecl( - VarTemplatePartialSpecializationDecl *D) { - assert(D->isStaticDataMember() && - "Only static data member templates are allowed."); - - VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); - - // Lookup the already-instantiated declaration and return that. - DeclContext::lookup_result Found = Owner->lookup(VarTemplate->getDeclName()); - assert(!Found.empty() && "Instantiation found nothing?"); - - VarTemplateDecl *InstVarTemplate = dyn_cast<VarTemplateDecl>(Found.front()); - assert(InstVarTemplate && "Instantiation did not find a variable template?"); - - if (VarTemplatePartialSpecializationDecl *Result = - InstVarTemplate->findPartialSpecInstantiatedFromMember(D)) - return Result; - - return InstantiateVarTemplatePartialSpecialization(InstVarTemplate, D); -} - -Decl * -TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - // Create a local instantiation scope for this function template, which - // will contain the instantiations of the template parameters and then get - // merged with the local instantiation scope for the function template - // itself. - LocalInstantiationScope Scope(SemaRef); - - TemplateParameterList *TempParams = D->getTemplateParameters(); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - - FunctionDecl *Instantiated = nullptr; - if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl())) - Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod, - InstParams)); - else - Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl( - D->getTemplatedDecl(), - InstParams)); - - if (!Instantiated) - return nullptr; - - // Link the instantiated function template declaration to the function - // template from which it was instantiated. - FunctionTemplateDecl *InstTemplate - = Instantiated->getDescribedFunctionTemplate(); - InstTemplate->setAccess(D->getAccess()); - assert(InstTemplate && - "VisitFunctionDecl/CXXMethodDecl didn't create a template!"); - - bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None); - - // Link the instantiation back to the pattern *unless* this is a - // non-definition friend declaration. - if (!InstTemplate->getInstantiatedFromMemberTemplate() && - !(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition())) - InstTemplate->setInstantiatedFromMemberTemplate(D); - - // Make declarations visible in the appropriate context. - if (!isFriend) { - Owner->addDecl(InstTemplate); - } else if (InstTemplate->getDeclContext()->isRecord() && - !getPreviousDeclForInstantiation(D)) { - SemaRef.CheckFriendAccess(InstTemplate); - } - - return InstTemplate; -} - -Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { - CXXRecordDecl *PrevDecl = nullptr; - if (D->isInjectedClassName()) - PrevDecl = cast<CXXRecordDecl>(Owner); - else if (CXXRecordDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { - NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), - PatternPrev, - TemplateArgs); - if (!Prev) return nullptr; - PrevDecl = cast<CXXRecordDecl>(Prev); - } - - CXXRecordDecl *Record = CXXRecordDecl::Create( - SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), - D->getLocation(), D->getIdentifier(), PrevDecl); - - // Substitute the nested name specifier, if any. - if (SubstQualifier(D, Record)) - return nullptr; - - SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, - StartingScope); - - Record->setImplicit(D->isImplicit()); - // FIXME: Check against AS_none is an ugly hack to work around the issue that - // the tag decls introduced by friend class declarations don't have an access - // specifier. Remove once this area of the code gets sorted out. - if (D->getAccess() != AS_none) - Record->setAccess(D->getAccess()); - if (!D->isInjectedClassName()) - Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); - - // If the original function was part of a friend declaration, - // inherit its namespace state. - if (D->getFriendObjectKind()) - Record->setObjectOfFriendDecl(); - - // Make sure that anonymous structs and unions are recorded. - if (D->isAnonymousStructOrUnion()) - Record->setAnonymousStructOrUnion(true); - - if (D->isLocalClass()) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record); - - // Forward the mangling number from the template to the instantiated decl. - SemaRef.Context.setManglingNumber(Record, - SemaRef.Context.getManglingNumber(D)); - - // See if the old tag was defined along with a declarator. - // If it did, mark the new tag as being associated with that declarator. - if (DeclaratorDecl *DD = SemaRef.Context.getDeclaratorForUnnamedTagDecl(D)) - SemaRef.Context.addDeclaratorForUnnamedTagDecl(Record, DD); - - // See if the old tag was defined along with a typedef. - // If it did, mark the new tag as being associated with that typedef. - if (TypedefNameDecl *TND = SemaRef.Context.getTypedefNameForUnnamedTagDecl(D)) - SemaRef.Context.addTypedefNameForUnnamedTagDecl(Record, TND); - - Owner->addDecl(Record); - - // DR1484 clarifies that the members of a local class are instantiated as part - // of the instantiation of their enclosing entity. - if (D->isCompleteDefinition() && D->isLocalClass()) { - Sema::LocalEagerInstantiationScope LocalInstantiations(SemaRef); - - SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs, - TSK_ImplicitInstantiation, - /*Complain=*/true); - - // For nested local classes, we will instantiate the members when we - // reach the end of the outermost (non-nested) local class. - if (!D->isCXXClassMember()) - SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs, - TSK_ImplicitInstantiation); - - // This class may have local implicit instantiations that need to be - // performed within this scope. - LocalInstantiations.perform(); - } - - SemaRef.DiagnoseUnusedNestedTypedefs(Record); - - return Record; -} - -/// Adjust the given function type for an instantiation of the -/// given declaration, to cope with modifications to the function's type that -/// aren't reflected in the type-source information. -/// -/// \param D The declaration we're instantiating. -/// \param TInfo The already-instantiated type. -static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, - FunctionDecl *D, - TypeSourceInfo *TInfo) { - const FunctionProtoType *OrigFunc - = D->getType()->castAs<FunctionProtoType>(); - const FunctionProtoType *NewFunc - = TInfo->getType()->castAs<FunctionProtoType>(); - if (OrigFunc->getExtInfo() == NewFunc->getExtInfo()) - return TInfo->getType(); - - FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo(); - NewEPI.ExtInfo = OrigFunc->getExtInfo(); - return Context.getFunctionType(NewFunc->getReturnType(), - NewFunc->getParamTypes(), NewEPI); -} - -/// Normal class members are of more specific types and therefore -/// don't make it here. This function serves three purposes: -/// 1) instantiating function templates -/// 2) substituting friend declarations -/// 3) substituting deduction guide declarations for nested class templates -Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, - TemplateParameterList *TemplateParams) { - // Check whether there is already a function template specialization for - // this declaration. - FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); - if (FunctionTemplate && !TemplateParams) { - ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost(); - - void *InsertPos = nullptr; - FunctionDecl *SpecFunc - = FunctionTemplate->findSpecialization(Innermost, InsertPos); - - // If we already have a function template specialization, return it. - if (SpecFunc) - return SpecFunc; - } - - bool isFriend; - if (FunctionTemplate) - isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None); - else - isFriend = (D->getFriendObjectKind() != Decl::FOK_None); - - bool MergeWithParentScope = (TemplateParams != nullptr) || - Owner->isFunctionOrMethod() || - !(isa<Decl>(Owner) && - cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); - LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); - - ExplicitSpecifier InstantiatedExplicitSpecifier; - if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { - InstantiatedExplicitSpecifier = instantiateExplicitSpecifier( - SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; - } - - SmallVector<ParmVarDecl *, 4> Params; - TypeSourceInfo *TInfo = SubstFunctionType(D, Params); - if (!TInfo) - return nullptr; - QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); - - NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); - if (QualifierLoc) { - QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, - TemplateArgs); - if (!QualifierLoc) - return nullptr; - } - - // If we're instantiating a local function declaration, put the result - // in the enclosing namespace; otherwise we need to find the instantiated - // context. - DeclContext *DC; - if (D->isLocalExternDecl()) { - DC = Owner; - SemaRef.adjustContextForLocalExternDecl(DC); - } else if (isFriend && QualifierLoc) { - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - DC = SemaRef.computeDeclContext(SS); - if (!DC) return nullptr; - } else { - DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), - TemplateArgs); - } - - DeclarationNameInfo NameInfo - = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); - - FunctionDecl *Function; - if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { - Function = CXXDeductionGuideDecl::Create( - SemaRef.Context, DC, D->getInnerLocStart(), - InstantiatedExplicitSpecifier, NameInfo, T, TInfo, - D->getSourceRange().getEnd()); - if (DGuide->isCopyDeductionCandidate()) - cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate(); - Function->setAccess(D->getAccess()); - } else { - Function = FunctionDecl::Create( - SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo, - D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->getConstexprKind()); - Function->setRangeEnd(D->getSourceRange().getEnd()); - } - - if (D->isInlined()) - Function->setImplicitlyInline(); - - if (QualifierLoc) - Function->setQualifierInfo(QualifierLoc); - - if (D->isLocalExternDecl()) - Function->setLocalExternDecl(); - - DeclContext *LexicalDC = Owner; - if (!isFriend && D->isOutOfLine() && !D->isLocalExternDecl()) { - assert(D->getDeclContext()->isFileContext()); - LexicalDC = D->getDeclContext(); - } - - Function->setLexicalDeclContext(LexicalDC); - - // Attach the parameters - for (unsigned P = 0; P < Params.size(); ++P) - if (Params[P]) - Params[P]->setOwningFunction(Function); - Function->setParams(Params); - - if (TemplateParams) { - // Our resulting instantiation is actually a function template, since we - // are substituting only the outer template parameters. For example, given - // - // template<typename T> - // struct X { - // template<typename U> friend void f(T, U); - // }; - // - // X<int> x; - // - // We are instantiating the friend function template "f" within X<int>, - // which means substituting int for T, but leaving "f" as a friend function - // template. - // Build the function template itself. - FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, DC, - Function->getLocation(), - Function->getDeclName(), - TemplateParams, Function); - Function->setDescribedFunctionTemplate(FunctionTemplate); - - FunctionTemplate->setLexicalDeclContext(LexicalDC); - - if (isFriend && D->isThisDeclarationADefinition()) { - FunctionTemplate->setInstantiatedFromMemberTemplate( - D->getDescribedFunctionTemplate()); - } - } else if (FunctionTemplate) { - // Record this function template specialization. - ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost(); - Function->setFunctionTemplateSpecialization(FunctionTemplate, - TemplateArgumentList::CreateCopy(SemaRef.Context, - Innermost), - /*InsertPos=*/nullptr); - } else if (isFriend && D->isThisDeclarationADefinition()) { - // Do not connect the friend to the template unless it's actually a - // definition. We don't want non-template functions to be marked as being - // template instantiations. - Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); - } - - if (isFriend) - Function->setObjectOfFriendDecl(); - - if (InitFunctionInstantiation(Function, D)) - Function->setInvalidDecl(); - - bool IsExplicitSpecialization = false; - - LookupResult Previous( - SemaRef, Function->getDeclName(), SourceLocation(), - D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage - : Sema::LookupOrdinaryName, - D->isLocalExternDecl() ? Sema::ForExternalRedeclaration - : SemaRef.forRedeclarationInCurContext()); - - if (DependentFunctionTemplateSpecializationInfo *Info - = D->getDependentSpecializationInfo()) { - assert(isFriend && "non-friend has dependent specialization info?"); - - // Instantiate the explicit template arguments. - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) - return nullptr; - - // Map the candidate templates to their instantiations. - for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { - Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), - Info->getTemplate(I), - TemplateArgs); - if (!Temp) return nullptr; - - Previous.addDecl(cast<FunctionTemplateDecl>(Temp)); - } - - if (SemaRef.CheckFunctionTemplateSpecialization(Function, - &ExplicitArgs, - Previous)) - Function->setInvalidDecl(); - - IsExplicitSpecialization = true; - } else if (const ASTTemplateArgumentListInfo *Info = - D->getTemplateSpecializationArgsAsWritten()) { - // The name of this function was written as a template-id. - SemaRef.LookupQualifiedName(Previous, DC); - - // Instantiate the explicit template arguments. - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) - return nullptr; - - if (SemaRef.CheckFunctionTemplateSpecialization(Function, - &ExplicitArgs, - Previous)) - Function->setInvalidDecl(); - - IsExplicitSpecialization = true; - } else if (TemplateParams || !FunctionTemplate) { - // Look only into the namespace where the friend would be declared to - // find a previous declaration. This is the innermost enclosing namespace, - // as described in ActOnFriendFunctionDecl. - SemaRef.LookupQualifiedName(Previous, DC); - - // In C++, the previous declaration we find might be a tag type - // (class or enum). In this case, the new declaration will hide the - // tag type. Note that this does does not apply if we're declaring a - // typedef (C++ [dcl.typedef]p4). - if (Previous.isSingleTagDecl()) - Previous.clear(); - } - - SemaRef.CheckFunctionDeclaration(/*Scope*/ nullptr, Function, Previous, - IsExplicitSpecialization); - - NamedDecl *PrincipalDecl = (TemplateParams - ? cast<NamedDecl>(FunctionTemplate) - : Function); - - // If the original function was part of a friend declaration, - // inherit its namespace state and add it to the owner. - if (isFriend) { - Function->setObjectOfFriendDecl(); - if (FunctionTemplateDecl *FT = Function->getDescribedFunctionTemplate()) - FT->setObjectOfFriendDecl(); - DC->makeDeclVisibleInContext(PrincipalDecl); - - bool QueuedInstantiation = false; - - // C++11 [temp.friend]p4 (DR329): - // When a function is defined in a friend function declaration in a class - // template, the function is instantiated when the function is odr-used. - // The same restrictions on multiple declarations and definitions that - // apply to non-template function declarations and definitions also apply - // to these implicit definitions. - if (D->isThisDeclarationADefinition()) { - SemaRef.CheckForFunctionRedefinition(Function); - if (!Function->isInvalidDecl()) { - for (auto R : Function->redecls()) { - if (R == Function) - continue; - - // If some prior declaration of this function has been used, we need - // to instantiate its definition. - if (!QueuedInstantiation && R->isUsed(false)) { - if (MemberSpecializationInfo *MSInfo = - Function->getMemberSpecializationInfo()) { - if (MSInfo->getPointOfInstantiation().isInvalid()) { - SourceLocation Loc = R->getLocation(); // FIXME - MSInfo->setPointOfInstantiation(Loc); - SemaRef.PendingLocalImplicitInstantiations.push_back( - std::make_pair(Function, Loc)); - QueuedInstantiation = true; - } - } - } - } - } - } - - // Check the template parameter list against the previous declaration. The - // goal here is to pick up default arguments added since the friend was - // declared; we know the template parameter lists match, since otherwise - // we would not have picked this template as the previous declaration. - if (TemplateParams && FunctionTemplate->getPreviousDecl()) { - SemaRef.CheckTemplateParameterList( - TemplateParams, - FunctionTemplate->getPreviousDecl()->getTemplateParameters(), - Function->isThisDeclarationADefinition() - ? Sema::TPC_FriendFunctionTemplateDefinition - : Sema::TPC_FriendFunctionTemplate); - } - } - - if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) - DC->makeDeclVisibleInContext(PrincipalDecl); - - if (Function->isOverloadedOperator() && !DC->isRecord() && - PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) - PrincipalDecl->setNonMemberOperator(); - - assert(!D->isDefaulted() && "only methods should be defaulted"); - return Function; -} - -Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( - CXXMethodDecl *D, TemplateParameterList *TemplateParams, - Optional<const ASTTemplateArgumentListInfo *> - ClassScopeSpecializationArgs) { - FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); - if (FunctionTemplate && !TemplateParams) { - // We are creating a function template specialization from a function - // template. Check whether there is already a function template - // specialization for this particular set of template arguments. - ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost(); - - void *InsertPos = nullptr; - FunctionDecl *SpecFunc - = FunctionTemplate->findSpecialization(Innermost, InsertPos); - - // If we already have a function template specialization, return it. - if (SpecFunc) - return SpecFunc; - } - - bool isFriend; - if (FunctionTemplate) - isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None); - else - isFriend = (D->getFriendObjectKind() != Decl::FOK_None); - - bool MergeWithParentScope = (TemplateParams != nullptr) || - !(isa<Decl>(Owner) && - cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); - LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); - - // Instantiate enclosing template arguments for friends. - SmallVector<TemplateParameterList *, 4> TempParamLists; - unsigned NumTempParamLists = 0; - if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) { - TempParamLists.resize(NumTempParamLists); - for (unsigned I = 0; I != NumTempParamLists; ++I) { - TemplateParameterList *TempParams = D->getTemplateParameterList(I); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - TempParamLists[I] = InstParams; - } - } - - ExplicitSpecifier InstantiatedExplicitSpecifier = - instantiateExplicitSpecifier(SemaRef, TemplateArgs, - ExplicitSpecifier::getFromDecl(D), D); - if (InstantiatedExplicitSpecifier.isInvalid()) - return nullptr; - - SmallVector<ParmVarDecl *, 4> Params; - TypeSourceInfo *TInfo = SubstFunctionType(D, Params); - if (!TInfo) - return nullptr; - QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); - - NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); - if (QualifierLoc) { - QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, - TemplateArgs); - if (!QualifierLoc) - return nullptr; - } - - DeclContext *DC = Owner; - if (isFriend) { - if (QualifierLoc) { - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - DC = SemaRef.computeDeclContext(SS); - - if (DC && SemaRef.RequireCompleteDeclContext(SS, DC)) - return nullptr; - } else { - DC = SemaRef.FindInstantiatedContext(D->getLocation(), - D->getDeclContext(), - TemplateArgs); - } - if (!DC) return nullptr; - } - - // Build the instantiated method declaration. - CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); - CXXMethodDecl *Method = nullptr; - - SourceLocation StartLoc = D->getInnerLocStart(); - DeclarationNameInfo NameInfo - = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); - if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { - Method = CXXConstructorDecl::Create( - SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false, - Constructor->getConstexprKind()); - Method->setRangeEnd(Constructor->getEndLoc()); - } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { - Method = CXXDestructorDecl::Create(SemaRef.Context, Record, - StartLoc, NameInfo, T, TInfo, - Destructor->isInlineSpecified(), - false); - Method->setRangeEnd(Destructor->getEndLoc()); - } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { - Method = CXXConversionDecl::Create( - SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier, - Conversion->getConstexprKind(), Conversion->getEndLoc()); - } else { - StorageClass SC = D->isStatic() ? SC_Static : SC_None; - Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, - T, TInfo, SC, D->isInlineSpecified(), - D->getConstexprKind(), D->getEndLoc()); - } - - if (D->isInlined()) - Method->setImplicitlyInline(); - - if (QualifierLoc) - Method->setQualifierInfo(QualifierLoc); - - if (TemplateParams) { - // Our resulting instantiation is actually a function template, since we - // are substituting only the outer template parameters. For example, given - // - // template<typename T> - // struct X { - // template<typename U> void f(T, U); - // }; - // - // X<int> x; - // - // We are instantiating the member template "f" within X<int>, which means - // substituting int for T, but leaving "f" as a member function template. - // Build the function template itself. - FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record, - Method->getLocation(), - Method->getDeclName(), - TemplateParams, Method); - if (isFriend) { - FunctionTemplate->setLexicalDeclContext(Owner); - FunctionTemplate->setObjectOfFriendDecl(); - } else if (D->isOutOfLine()) - FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); - Method->setDescribedFunctionTemplate(FunctionTemplate); - } else if (FunctionTemplate) { - // Record this function template specialization. - ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost(); - Method->setFunctionTemplateSpecialization(FunctionTemplate, - TemplateArgumentList::CreateCopy(SemaRef.Context, - Innermost), - /*InsertPos=*/nullptr); - } else if (!isFriend) { - // Record that this is an instantiation of a member function. - Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); - } - - // If we are instantiating a member function defined - // out-of-line, the instantiation will have the same lexical - // context (which will be a namespace scope) as the template. - if (isFriend) { - if (NumTempParamLists) - Method->setTemplateParameterListsInfo( - SemaRef.Context, - llvm::makeArrayRef(TempParamLists.data(), NumTempParamLists)); - - Method->setLexicalDeclContext(Owner); - Method->setObjectOfFriendDecl(); - } else if (D->isOutOfLine()) - Method->setLexicalDeclContext(D->getLexicalDeclContext()); - - // Attach the parameters - for (unsigned P = 0; P < Params.size(); ++P) - Params[P]->setOwningFunction(Method); - Method->setParams(Params); - - if (InitMethodInstantiation(Method, D)) - Method->setInvalidDecl(); - - LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, - Sema::ForExternalRedeclaration); - - bool IsExplicitSpecialization = false; - - // If the name of this function was written as a template-id, instantiate - // the explicit template arguments. - if (DependentFunctionTemplateSpecializationInfo *Info - = D->getDependentSpecializationInfo()) { - assert(isFriend && "non-friend has dependent specialization info?"); - - // Instantiate the explicit template arguments. - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) - return nullptr; - - // Map the candidate templates to their instantiations. - for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { - Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), - Info->getTemplate(I), - TemplateArgs); - if (!Temp) return nullptr; - - Previous.addDecl(cast<FunctionTemplateDecl>(Temp)); - } - - if (SemaRef.CheckFunctionTemplateSpecialization(Method, - &ExplicitArgs, - Previous)) - Method->setInvalidDecl(); - - IsExplicitSpecialization = true; - } else if (const ASTTemplateArgumentListInfo *Info = - ClassScopeSpecializationArgs.getValueOr( - D->getTemplateSpecializationArgsAsWritten())) { - SemaRef.LookupQualifiedName(Previous, DC); - - TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), - Info->getRAngleLoc()); - if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), - ExplicitArgs, TemplateArgs)) - return nullptr; - - if (SemaRef.CheckFunctionTemplateSpecialization(Method, - &ExplicitArgs, - Previous)) - Method->setInvalidDecl(); - - IsExplicitSpecialization = true; - } else if (ClassScopeSpecializationArgs) { - // Class-scope explicit specialization written without explicit template - // arguments. - SemaRef.LookupQualifiedName(Previous, DC); - if (SemaRef.CheckFunctionTemplateSpecialization(Method, nullptr, Previous)) - Method->setInvalidDecl(); - - IsExplicitSpecialization = true; - } else if (!FunctionTemplate || TemplateParams || isFriend) { - SemaRef.LookupQualifiedName(Previous, Record); - - // In C++, the previous declaration we find might be a tag type - // (class or enum). In this case, the new declaration will hide the - // tag type. Note that this does does not apply if we're declaring a - // typedef (C++ [dcl.typedef]p4). - if (Previous.isSingleTagDecl()) - Previous.clear(); - } - - SemaRef.CheckFunctionDeclaration(nullptr, Method, Previous, - IsExplicitSpecialization); - - if (D->isPure()) - SemaRef.CheckPureMethod(Method, SourceRange()); - - // Propagate access. For a non-friend declaration, the access is - // whatever we're propagating from. For a friend, it should be the - // previous declaration we just found. - if (isFriend && Method->getPreviousDecl()) - Method->setAccess(Method->getPreviousDecl()->getAccess()); - else - Method->setAccess(D->getAccess()); - if (FunctionTemplate) - FunctionTemplate->setAccess(Method->getAccess()); - - SemaRef.CheckOverrideControl(Method); - - // If a function is defined as defaulted or deleted, mark it as such now. - if (D->isExplicitlyDefaulted()) - SemaRef.SetDeclDefaulted(Method, Method->getLocation()); - if (D->isDeletedAsWritten()) - SemaRef.SetDeclDeleted(Method, Method->getLocation()); - - // If this is an explicit specialization, mark the implicitly-instantiated - // template specialization as being an explicit specialization too. - // FIXME: Is this necessary? - if (IsExplicitSpecialization && !isFriend) - SemaRef.CompleteMemberSpecialization(Method, Previous); - - // If there's a function template, let our caller handle it. - if (FunctionTemplate) { - // do nothing - - // Don't hide a (potentially) valid declaration with an invalid one. - } else if (Method->isInvalidDecl() && !Previous.empty()) { - // do nothing - - // Otherwise, check access to friends and make them visible. - } else if (isFriend) { - // We only need to re-check access for methods which we didn't - // manage to match during parsing. - if (!D->getPreviousDecl()) - SemaRef.CheckFriendAccess(Method); - - Record->makeDeclVisibleInContext(Method); - - // Otherwise, add the declaration. We don't need to do this for - // class-scope specializations because we'll have matched them with - // the appropriate template. - } else { - Owner->addDecl(Method); - } - - // PR17480: Honor the used attribute to instantiate member function - // definitions - if (Method->hasAttr<UsedAttr>()) { - if (const auto *A = dyn_cast<CXXRecordDecl>(Owner)) { - SourceLocation Loc; - if (const MemberSpecializationInfo *MSInfo = - A->getMemberSpecializationInfo()) - Loc = MSInfo->getPointOfInstantiation(); - else if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(A)) - Loc = Spec->getPointOfInstantiation(); - SemaRef.MarkFunctionReferenced(Loc, Method); - } - } - - return Method; -} - -Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) { - return VisitCXXMethodDecl(D); -} - -Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) { - return VisitCXXMethodDecl(D); -} - -Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { - return VisitCXXMethodDecl(D); -} - -Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None, - /*ExpectParameterPack=*/ false); -} - -Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( - TemplateTypeParmDecl *D) { - // TODO: don't always clone when decls are refcounted. - assert(D->getTypeForDecl()->isTemplateTypeParmType()); - - TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create( - SemaRef.Context, Owner, D->getBeginLoc(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(), - D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); - Inst->setAccess(AS_public); - - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { - TypeSourceInfo *InstantiatedDefaultArg = - SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs, - D->getDefaultArgumentLoc(), D->getDeclName()); - if (InstantiatedDefaultArg) - Inst->setDefaultArgument(InstantiatedDefaultArg); - } - - // Introduce this template parameter's instantiation into the instantiation - // scope. - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst); - - return Inst; -} - -Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( - NonTypeTemplateParmDecl *D) { - // Substitute into the type of the non-type template parameter. - TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc(); - SmallVector<TypeSourceInfo *, 4> ExpandedParameterPackTypesAsWritten; - SmallVector<QualType, 4> ExpandedParameterPackTypes; - bool IsExpandedParameterPack = false; - TypeSourceInfo *DI; - QualType T; - bool Invalid = false; - - if (D->isExpandedParameterPack()) { - // The non-type template parameter pack is an already-expanded pack - // expansion of types. Substitute into each of the expanded types. - ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes()); - ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes()); - for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { - TypeSourceInfo *NewDI = - SemaRef.SubstType(D->getExpansionTypeSourceInfo(I), TemplateArgs, - D->getLocation(), D->getDeclName()); - if (!NewDI) - return nullptr; - - QualType NewT = - SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation()); - if (NewT.isNull()) - return nullptr; - - ExpandedParameterPackTypesAsWritten.push_back(NewDI); - ExpandedParameterPackTypes.push_back(NewT); - } - - IsExpandedParameterPack = true; - DI = D->getTypeSourceInfo(); - T = DI->getType(); - } else if (D->isPackExpansion()) { - // The non-type template parameter pack's type is a pack expansion of types. - // Determine whether we need to expand this parameter pack into separate - // types. - PackExpansionTypeLoc Expansion = TL.castAs<PackExpansionTypeLoc>(); - TypeLoc Pattern = Expansion.getPatternLoc(); - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); - - // Determine whether the set of unexpanded parameter packs can and should - // be expanded. - bool Expand = true; - bool RetainExpansion = false; - Optional<unsigned> OrigNumExpansions - = Expansion.getTypePtr()->getNumExpansions(); - Optional<unsigned> NumExpansions = OrigNumExpansions; - if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(), - Pattern.getSourceRange(), - Unexpanded, - TemplateArgs, - Expand, RetainExpansion, - NumExpansions)) - return nullptr; - - if (Expand) { - for (unsigned I = 0; I != *NumExpansions; ++I) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); - TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs, - D->getLocation(), - D->getDeclName()); - if (!NewDI) - return nullptr; - - QualType NewT = - SemaRef.CheckNonTypeTemplateParameterType(NewDI, D->getLocation()); - if (NewT.isNull()) - return nullptr; - - ExpandedParameterPackTypesAsWritten.push_back(NewDI); - ExpandedParameterPackTypes.push_back(NewT); - } - - // Note that we have an expanded parameter pack. The "type" of this - // expanded parameter pack is the original expansion type, but callers - // will end up using the expanded parameter pack types for type-checking. - IsExpandedParameterPack = true; - DI = D->getTypeSourceInfo(); - T = DI->getType(); - } else { - // We cannot fully expand the pack expansion now, so substitute into the - // pattern and create a new pack expansion type. - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); - TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs, - D->getLocation(), - D->getDeclName()); - if (!NewPattern) - return nullptr; - - SemaRef.CheckNonTypeTemplateParameterType(NewPattern, D->getLocation()); - DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(), - NumExpansions); - if (!DI) - return nullptr; - - T = DI->getType(); - } - } else { - // Simple case: substitution into a parameter that is not a parameter pack. - DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, - D->getLocation(), D->getDeclName()); - if (!DI) - return nullptr; - - // Check that this type is acceptable for a non-type template parameter. - T = SemaRef.CheckNonTypeTemplateParameterType(DI, D->getLocation()); - if (T.isNull()) { - T = SemaRef.Context.IntTy; - Invalid = true; - } - } - - NonTypeTemplateParmDecl *Param; - if (IsExpandedParameterPack) - Param = NonTypeTemplateParmDecl::Create( - SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), - D->getPosition(), D->getIdentifier(), T, DI, ExpandedParameterPackTypes, - ExpandedParameterPackTypesAsWritten); - else - Param = NonTypeTemplateParmDecl::Create( - SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), - D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); - - Param->setAccess(AS_public); - if (Invalid) - Param->setInvalidDecl(); - - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { - EnterExpressionEvaluationContext ConstantEvaluated( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs); - if (!Value.isInvalid()) - Param->setDefaultArgument(Value.get()); - } - - // Introduce this template parameter's instantiation into the instantiation - // scope. - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); - return Param; -} - -static void collectUnexpandedParameterPacks( - Sema &S, - TemplateParameterList *Params, - SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { - for (const auto &P : *Params) { - if (P->isTemplateParameterPack()) - continue; - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) - S.collectUnexpandedParameterPacks(NTTP->getTypeSourceInfo()->getTypeLoc(), - Unexpanded); - if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) - collectUnexpandedParameterPacks(S, TTP->getTemplateParameters(), - Unexpanded); - } -} - -Decl * -TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( - TemplateTemplateParmDecl *D) { - // Instantiate the template parameter list of the template template parameter. - TemplateParameterList *TempParams = D->getTemplateParameters(); - TemplateParameterList *InstParams; - SmallVector<TemplateParameterList*, 8> ExpandedParams; - - bool IsExpandedParameterPack = false; - - if (D->isExpandedParameterPack()) { - // The template template parameter pack is an already-expanded pack - // expansion of template parameters. Substitute into each of the expanded - // parameters. - ExpandedParams.reserve(D->getNumExpansionTemplateParameters()); - for (unsigned I = 0, N = D->getNumExpansionTemplateParameters(); - I != N; ++I) { - LocalInstantiationScope Scope(SemaRef); - TemplateParameterList *Expansion = - SubstTemplateParams(D->getExpansionTemplateParameters(I)); - if (!Expansion) - return nullptr; - ExpandedParams.push_back(Expansion); - } - - IsExpandedParameterPack = true; - InstParams = TempParams; - } else if (D->isPackExpansion()) { - // The template template parameter pack expands to a pack of template - // template parameters. Determine whether we need to expand this parameter - // pack into separate parameters. - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - collectUnexpandedParameterPacks(SemaRef, D->getTemplateParameters(), - Unexpanded); - - // Determine whether the set of unexpanded parameter packs can and should - // be expanded. - bool Expand = true; - bool RetainExpansion = false; - Optional<unsigned> NumExpansions; - if (SemaRef.CheckParameterPacksForExpansion(D->getLocation(), - TempParams->getSourceRange(), - Unexpanded, - TemplateArgs, - Expand, RetainExpansion, - NumExpansions)) - return nullptr; - - if (Expand) { - for (unsigned I = 0; I != *NumExpansions; ++I) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); - LocalInstantiationScope Scope(SemaRef); - TemplateParameterList *Expansion = SubstTemplateParams(TempParams); - if (!Expansion) - return nullptr; - ExpandedParams.push_back(Expansion); - } - - // Note that we have an expanded parameter pack. The "type" of this - // expanded parameter pack is the original expansion type, but callers - // will end up using the expanded parameter pack types for type-checking. - IsExpandedParameterPack = true; - InstParams = TempParams; - } else { - // We cannot fully expand the pack expansion now, so just substitute - // into the pattern. - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); - - LocalInstantiationScope Scope(SemaRef); - InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - } - } else { - // Perform the actual substitution of template parameters within a new, - // local instantiation scope. - LocalInstantiationScope Scope(SemaRef); - InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - } - - // Build the template template parameter. - TemplateTemplateParmDecl *Param; - if (IsExpandedParameterPack) - Param = TemplateTemplateParmDecl::Create( - SemaRef.Context, Owner, D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), - D->getPosition(), D->getIdentifier(), InstParams, ExpandedParams); - else - Param = TemplateTemplateParmDecl::Create( - SemaRef.Context, Owner, D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), - D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams); - if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { - NestedNameSpecifierLoc QualifierLoc = - D->getDefaultArgument().getTemplateQualifierLoc(); - QualifierLoc = - SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); - TemplateName TName = SemaRef.SubstTemplateName( - QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(), - D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs); - if (!TName.isNull()) - Param->setDefaultArgument( - SemaRef.Context, - TemplateArgumentLoc(TemplateArgument(TName), - D->getDefaultArgument().getTemplateQualifierLoc(), - D->getDefaultArgument().getTemplateNameLoc())); - } - Param->setAccess(AS_public); - - // Introduce this template parameter's instantiation into the instantiation - // scope. - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); - - return Param; -} - -Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - // Using directives are never dependent (and never contain any types or - // expressions), so they require no explicit instantiation work. - - UsingDirectiveDecl *Inst - = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getNamespaceKeyLocation(), - D->getQualifierLoc(), - D->getIdentLocation(), - D->getNominatedNamespace(), - D->getCommonAncestor()); - - // Add the using directive to its declaration context - // only if this is not a function or method. - if (!Owner->isFunctionOrMethod()) - Owner->addDecl(Inst); - - return Inst; -} - -Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { - - // The nested name specifier may be dependent, for example - // template <typename T> struct t { - // struct s1 { T f1(); }; - // struct s2 : s1 { using s1::f1; }; - // }; - // template struct t<int>; - // Here, in using s1::f1, s1 refers to t<T>::s1; - // we need to substitute for t<int>::s1. - NestedNameSpecifierLoc QualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), - TemplateArgs); - if (!QualifierLoc) - return nullptr; - - // For an inheriting constructor declaration, the name of the using - // declaration is the name of a constructor in this class, not in the - // base class. - DeclarationNameInfo NameInfo = D->getNameInfo(); - if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) - if (auto *RD = dyn_cast<CXXRecordDecl>(SemaRef.CurContext)) - NameInfo.setName(SemaRef.Context.DeclarationNames.getCXXConstructorName( - SemaRef.Context.getCanonicalType(SemaRef.Context.getRecordType(RD)))); - - // We only need to do redeclaration lookups if we're in a class - // scope (in fact, it's not really even possible in non-class - // scopes). - bool CheckRedeclaration = Owner->isRecord(); - - LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName, - Sema::ForVisibleRedeclaration); - - UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, - D->getUsingLoc(), - QualifierLoc, - NameInfo, - D->hasTypename()); - - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - if (CheckRedeclaration) { - Prev.setHideTags(false); - SemaRef.LookupQualifiedName(Prev, Owner); - - // Check for invalid redeclarations. - if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLoc(), - D->hasTypename(), SS, - D->getLocation(), Prev)) - NewUD->setInvalidDecl(); - - } - - if (!NewUD->isInvalidDecl() && - SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), - SS, NameInfo, D->getLocation())) - NewUD->setInvalidDecl(); - - SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D); - NewUD->setAccess(D->getAccess()); - Owner->addDecl(NewUD); - - // Don't process the shadow decls for an invalid decl. - if (NewUD->isInvalidDecl()) - return NewUD; - - if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) - SemaRef.CheckInheritingConstructorUsingDecl(NewUD); - - bool isFunctionScope = Owner->isFunctionOrMethod(); - - // Process the shadow decls. - for (auto *Shadow : D->shadows()) { - // FIXME: UsingShadowDecl doesn't preserve its immediate target, so - // reconstruct it in the case where it matters. - NamedDecl *OldTarget = Shadow->getTargetDecl(); - if (auto *CUSD = dyn_cast<ConstructorUsingShadowDecl>(Shadow)) - if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl()) - OldTarget = BaseShadow; - - NamedDecl *InstTarget = - cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), OldTarget, TemplateArgs)); - if (!InstTarget) - return nullptr; - - UsingShadowDecl *PrevDecl = nullptr; - if (CheckRedeclaration) { - if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl)) - continue; - } else if (UsingShadowDecl *OldPrev = - getPreviousDeclForInstantiation(Shadow)) { - PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), OldPrev, TemplateArgs)); - } - - UsingShadowDecl *InstShadow = - SemaRef.BuildUsingShadowDecl(/*Scope*/nullptr, NewUD, InstTarget, - PrevDecl); - SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); - - if (isFunctionScope) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); - } - - return NewUD; -} - -Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { - // Ignore these; we handle them in bulk when processing the UsingDecl. - return nullptr; -} - -Decl *TemplateDeclInstantiator::VisitConstructorUsingShadowDecl( - ConstructorUsingShadowDecl *D) { - // Ignore these; we handle them in bulk when processing the UsingDecl. - return nullptr; -} - -template <typename T> -Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( - T *D, bool InstantiatingPackElement) { - // If this is a pack expansion, expand it now. - if (D->isPackExpansion() && !InstantiatingPackElement) { - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - SemaRef.collectUnexpandedParameterPacks(D->getQualifierLoc(), Unexpanded); - SemaRef.collectUnexpandedParameterPacks(D->getNameInfo(), Unexpanded); - - // Determine whether the set of unexpanded parameter packs can and should - // be expanded. - bool Expand = true; - bool RetainExpansion = false; - Optional<unsigned> NumExpansions; - if (SemaRef.CheckParameterPacksForExpansion( - D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, TemplateArgs, - Expand, RetainExpansion, NumExpansions)) - return nullptr; - - // This declaration cannot appear within a function template signature, - // so we can't have a partial argument list for a parameter pack. - assert(!RetainExpansion && - "should never need to retain an expansion for UsingPackDecl"); - - if (!Expand) { - // We cannot fully expand the pack expansion now, so substitute into the - // pattern and create a new pack expansion. - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); - return instantiateUnresolvedUsingDecl(D, true); - } - - // Within a function, we don't have any normal way to check for conflicts - // between shadow declarations from different using declarations in the - // same pack expansion, but this is always ill-formed because all expansions - // must produce (conflicting) enumerators. - // - // Sadly we can't just reject this in the template definition because it - // could be valid if the pack is empty or has exactly one expansion. - if (D->getDeclContext()->isFunctionOrMethod() && *NumExpansions > 1) { - SemaRef.Diag(D->getEllipsisLoc(), - diag::err_using_decl_redeclaration_expansion); - return nullptr; - } - - // Instantiate the slices of this pack and build a UsingPackDecl. - SmallVector<NamedDecl*, 8> Expansions; - for (unsigned I = 0; I != *NumExpansions; ++I) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); - Decl *Slice = instantiateUnresolvedUsingDecl(D, true); - if (!Slice) - return nullptr; - // Note that we can still get unresolved using declarations here, if we - // had arguments for all packs but the pattern also contained other - // template arguments (this only happens during partial substitution, eg - // into the body of a generic lambda in a function template). - Expansions.push_back(cast<NamedDecl>(Slice)); - } - - auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions); - if (isDeclWithinFunction(D)) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD); - return NewD; - } - - UnresolvedUsingTypenameDecl *TD = dyn_cast<UnresolvedUsingTypenameDecl>(D); - SourceLocation TypenameLoc = TD ? TD->getTypenameLoc() : SourceLocation(); - - NestedNameSpecifierLoc QualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), - TemplateArgs); - if (!QualifierLoc) - return nullptr; - - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); - - DeclarationNameInfo NameInfo - = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); - - // Produce a pack expansion only if we're not instantiating a particular - // slice of a pack expansion. - bool InstantiatingSlice = D->getEllipsisLoc().isValid() && - SemaRef.ArgumentPackSubstitutionIndex != -1; - SourceLocation EllipsisLoc = - InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc(); - - NamedDecl *UD = SemaRef.BuildUsingDeclaration( - /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), - /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, - ParsedAttributesView(), - /*IsInstantiation*/ true); - if (UD) - SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); - - return UD; -} - -Decl *TemplateDeclInstantiator::VisitUnresolvedUsingTypenameDecl( - UnresolvedUsingTypenameDecl *D) { - return instantiateUnresolvedUsingDecl(D); -} - -Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl( - UnresolvedUsingValueDecl *D) { - return instantiateUnresolvedUsingDecl(D); -} - -Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { - SmallVector<NamedDecl*, 8> Expansions; - for (auto *UD : D->expansions()) { - if (NamedDecl *NewUD = - SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs)) - Expansions.push_back(NewUD); - else - return nullptr; - } - - auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions); - if (isDeclWithinFunction(D)) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD); - return NewD; -} - -Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *Decl) { - CXXMethodDecl *OldFD = Decl->getSpecialization(); - return cast_or_null<CXXMethodDecl>( - VisitCXXMethodDecl(OldFD, nullptr, Decl->getTemplateArgsAsWritten())); -} - -Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( - OMPThreadPrivateDecl *D) { - SmallVector<Expr *, 5> Vars; - for (auto *I : D->varlists()) { - Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get(); - assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr"); - Vars.push_back(Var); - } - - OMPThreadPrivateDecl *TD = - SemaRef.CheckOMPThreadPrivateDecl(D->getLocation(), Vars); - - TD->setAccess(AS_public); - Owner->addDecl(TD); - - return TD; -} - -Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) { - SmallVector<Expr *, 5> Vars; - for (auto *I : D->varlists()) { - Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get(); - assert(isa<DeclRefExpr>(Var) && "allocate arg is not a DeclRefExpr"); - Vars.push_back(Var); - } - SmallVector<OMPClause *, 4> Clauses; - // Copy map clauses from the original mapper. - for (OMPClause *C : D->clauselists()) { - auto *AC = cast<OMPAllocatorClause>(C); - ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs); - if (!NewE.isUsable()) - continue; - OMPClause *IC = SemaRef.ActOnOpenMPAllocatorClause( - NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc()); - Clauses.push_back(IC); - } - - Sema::DeclGroupPtrTy Res = SemaRef.ActOnOpenMPAllocateDirective( - D->getLocation(), Vars, Clauses, Owner); - if (Res.get().isNull()) - return nullptr; - return Res.get().getSingleDecl(); -} - -Decl *TemplateDeclInstantiator::VisitOMPRequiresDecl(OMPRequiresDecl *D) { - llvm_unreachable( - "Requires directive cannot be instantiated within a dependent context"); -} - -Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( - OMPDeclareReductionDecl *D) { - // Instantiate type and check if it is allowed. - const bool RequiresInstantiation = - D->getType()->isDependentType() || - D->getType()->isInstantiationDependentType() || - D->getType()->containsUnexpandedParameterPack(); - QualType SubstReductionType; - if (RequiresInstantiation) { - SubstReductionType = SemaRef.ActOnOpenMPDeclareReductionType( - D->getLocation(), - ParsedType::make(SemaRef.SubstType( - D->getType(), TemplateArgs, D->getLocation(), DeclarationName()))); - } else { - SubstReductionType = D->getType(); - } - if (SubstReductionType.isNull()) - return nullptr; - bool IsCorrect = !SubstReductionType.isNull(); - // Create instantiated copy. - std::pair<QualType, SourceLocation> ReductionTypes[] = { - std::make_pair(SubstReductionType, D->getLocation())}; - auto *PrevDeclInScope = D->getPrevDeclInScope(); - if (PrevDeclInScope && !PrevDeclInScope->isInvalidDecl()) { - PrevDeclInScope = cast<OMPDeclareReductionDecl>( - SemaRef.CurrentInstantiationScope->findInstantiationOf(PrevDeclInScope) - ->get<Decl *>()); - } - auto DRD = SemaRef.ActOnOpenMPDeclareReductionDirectiveStart( - /*S=*/nullptr, Owner, D->getDeclName(), ReductionTypes, D->getAccess(), - PrevDeclInScope); - auto *NewDRD = cast<OMPDeclareReductionDecl>(DRD.get().getSingleDecl()); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD); - if (!RequiresInstantiation) { - if (Expr *Combiner = D->getCombiner()) { - NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut()); - NewDRD->setCombiner(Combiner); - if (Expr *Init = D->getInitializer()) { - NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv()); - NewDRD->setInitializer(Init, D->getInitializerKind()); - } - } - (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd( - /*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl()); - return NewDRD; - } - Expr *SubstCombiner = nullptr; - Expr *SubstInitializer = nullptr; - // Combiners instantiation sequence. - if (D->getCombiner()) { - SemaRef.ActOnOpenMPDeclareReductionCombinerStart( - /*S=*/nullptr, NewDRD); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getCombinerIn())->getDecl(), - cast<DeclRefExpr>(NewDRD->getCombinerIn())->getDecl()); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getCombinerOut())->getDecl(), - cast<DeclRefExpr>(NewDRD->getCombinerOut())->getDecl()); - auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); - Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), - ThisContext); - SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get(); - SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner); - // Initializers instantiation sequence. - if (D->getInitializer()) { - VarDecl *OmpPrivParm = - SemaRef.ActOnOpenMPDeclareReductionInitializerStart( - /*S=*/nullptr, NewDRD); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getInitOrig())->getDecl(), - cast<DeclRefExpr>(NewDRD->getInitOrig())->getDecl()); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getInitPriv())->getDecl(), - cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl()); - if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) { - SubstInitializer = - SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get(); - } else { - IsCorrect = IsCorrect && OmpPrivParm->hasInit(); - } - SemaRef.ActOnOpenMPDeclareReductionInitializerEnd( - NewDRD, SubstInitializer, OmpPrivParm); - } - IsCorrect = - IsCorrect && SubstCombiner && - (!D->getInitializer() || - (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit && - SubstInitializer) || - (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit && - !SubstInitializer && !SubstInitializer)); - } else { - IsCorrect = false; - } - - (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(/*S=*/nullptr, DRD, - IsCorrect); - - return NewDRD; -} - -Decl * -TemplateDeclInstantiator::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { - // Instantiate type and check if it is allowed. - const bool RequiresInstantiation = - D->getType()->isDependentType() || - D->getType()->isInstantiationDependentType() || - D->getType()->containsUnexpandedParameterPack(); - QualType SubstMapperTy; - DeclarationName VN = D->getVarName(); - if (RequiresInstantiation) { - SubstMapperTy = SemaRef.ActOnOpenMPDeclareMapperType( - D->getLocation(), - ParsedType::make(SemaRef.SubstType(D->getType(), TemplateArgs, - D->getLocation(), VN))); - } else { - SubstMapperTy = D->getType(); - } - if (SubstMapperTy.isNull()) - return nullptr; - // Create an instantiated copy of mapper. - auto *PrevDeclInScope = D->getPrevDeclInScope(); - if (PrevDeclInScope && !PrevDeclInScope->isInvalidDecl()) { - PrevDeclInScope = cast<OMPDeclareMapperDecl>( - SemaRef.CurrentInstantiationScope->findInstantiationOf(PrevDeclInScope) - ->get<Decl *>()); - } - OMPDeclareMapperDecl *NewDMD = SemaRef.ActOnOpenMPDeclareMapperDirectiveStart( - /*S=*/nullptr, Owner, D->getDeclName(), SubstMapperTy, D->getLocation(), - VN, D->getAccess(), PrevDeclInScope); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDMD); - SmallVector<OMPClause *, 6> Clauses; - bool IsCorrect = true; - if (!RequiresInstantiation) { - // Copy the mapper variable. - NewDMD->setMapperVarRef(D->getMapperVarRef()); - // Copy map clauses from the original mapper. - for (OMPClause *C : D->clauselists()) - Clauses.push_back(C); - } else { - // Instantiate the mapper variable. - DeclarationNameInfo DirName; - SemaRef.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, /*S=*/nullptr, - (*D->clauselist_begin())->getBeginLoc()); - SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl( - NewDMD, /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getMapperVarRef())->getDecl(), - cast<DeclRefExpr>(NewDMD->getMapperVarRef())->getDecl()); - auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); - Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), - ThisContext); - // Instantiate map clauses. - for (OMPClause *C : D->clauselists()) { - auto *OldC = cast<OMPMapClause>(C); - SmallVector<Expr *, 4> NewVars; - for (Expr *OE : OldC->varlists()) { - Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get(); - if (!NE) { - IsCorrect = false; - break; - } - NewVars.push_back(NE); - } - if (!IsCorrect) - break; - NestedNameSpecifierLoc NewQualifierLoc = - SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(), - TemplateArgs); - CXXScopeSpec SS; - SS.Adopt(NewQualifierLoc); - DeclarationNameInfo NewNameInfo = SemaRef.SubstDeclarationNameInfo( - OldC->getMapperIdInfo(), TemplateArgs); - OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(), - OldC->getEndLoc()); - OMPClause *NewC = SemaRef.ActOnOpenMPMapClause( - OldC->getMapTypeModifiers(), OldC->getMapTypeModifiersLoc(), SS, - NewNameInfo, OldC->getMapType(), OldC->isImplicitMapType(), - OldC->getMapLoc(), OldC->getColonLoc(), NewVars, Locs); - Clauses.push_back(NewC); - } - SemaRef.EndOpenMPDSABlock(nullptr); - } - (void)SemaRef.ActOnOpenMPDeclareMapperDirectiveEnd(NewDMD, /*S=*/nullptr, - Clauses); - if (!IsCorrect) - return nullptr; - return NewDMD; -} - -Decl *TemplateDeclInstantiator::VisitOMPCapturedExprDecl( - OMPCapturedExprDecl * /*D*/) { - llvm_unreachable("Should not be met in templates"); -} - -Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { - return VisitFunctionDecl(D, nullptr); -} - -Decl * -TemplateDeclInstantiator::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { - Decl *Inst = VisitFunctionDecl(D, nullptr); - if (Inst && !D->getDescribedFunctionTemplate()) - Owner->addDecl(Inst); - return Inst; -} - -Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) { - return VisitCXXMethodDecl(D, nullptr); -} - -Decl *TemplateDeclInstantiator::VisitRecordDecl(RecordDecl *D) { - llvm_unreachable("There are only CXXRecordDecls in C++"); -} - -Decl * -TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - // As a MS extension, we permit class-scope explicit specialization - // of member class templates. - ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); - assert(ClassTemplate->getDeclContext()->isRecord() && - D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && - "can only instantiate an explicit specialization " - "for a member class template"); - - // Lookup the already-instantiated declaration in the instantiation - // of the class template. - ClassTemplateDecl *InstClassTemplate = - cast_or_null<ClassTemplateDecl>(SemaRef.FindInstantiatedDecl( - D->getLocation(), ClassTemplate, TemplateArgs)); - if (!InstClassTemplate) - return nullptr; - - // Substitute into the template arguments of the class template explicit - // specialization. - TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc(). - castAs<TemplateSpecializationTypeLoc>(); - TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(), - Loc.getRAngleLoc()); - SmallVector<TemplateArgumentLoc, 4> ArgLocs; - for (unsigned I = 0; I != Loc.getNumArgs(); ++I) - ArgLocs.push_back(Loc.getArgLoc(I)); - if (SemaRef.Subst(ArgLocs.data(), ArgLocs.size(), - InstTemplateArgs, TemplateArgs)) - return nullptr; - - // Check that the template argument list is well-formed for this - // class template. - SmallVector<TemplateArgument, 4> Converted; - if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, - D->getLocation(), - InstTemplateArgs, - false, - Converted)) - return nullptr; - - // Figure out where to insert this class template explicit specialization - // in the member template's set of class template explicit specializations. - void *InsertPos = nullptr; - ClassTemplateSpecializationDecl *PrevDecl = - InstClassTemplate->findSpecialization(Converted, InsertPos); - - // Check whether we've already seen a conflicting instantiation of this - // declaration (for instance, if there was a prior implicit instantiation). - bool Ignored; - if (PrevDecl && - SemaRef.CheckSpecializationInstantiationRedecl(D->getLocation(), - D->getSpecializationKind(), - PrevDecl, - PrevDecl->getSpecializationKind(), - PrevDecl->getPointOfInstantiation(), - Ignored)) - return nullptr; - - // If PrevDecl was a definition and D is also a definition, diagnose. - // This happens in cases like: - // - // template<typename T, typename U> - // struct Outer { - // template<typename X> struct Inner; - // template<> struct Inner<T> {}; - // template<> struct Inner<U> {}; - // }; - // - // Outer<int, int> outer; // error: the explicit specializations of Inner - // // have the same signature. - if (PrevDecl && PrevDecl->getDefinition() && - D->isThisDeclarationADefinition()) { - SemaRef.Diag(D->getLocation(), diag::err_redefinition) << PrevDecl; - SemaRef.Diag(PrevDecl->getDefinition()->getLocation(), - diag::note_previous_definition); - return nullptr; - } - - // Create the class template partial specialization declaration. - ClassTemplateSpecializationDecl *InstD = - ClassTemplateSpecializationDecl::Create( - SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), - D->getLocation(), InstClassTemplate, Converted, PrevDecl); - - // Add this partial specialization to the set of class template partial - // specializations. - if (!PrevDecl) - InstClassTemplate->AddSpecialization(InstD, InsertPos); - - // Substitute the nested name specifier, if any. - if (SubstQualifier(D, InstD)) - return nullptr; - - // Build the canonical type that describes the converted template - // arguments of the class template explicit specialization. - QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(InstClassTemplate), Converted, - SemaRef.Context.getRecordType(InstD)); - - // Build the fully-sugared type for this class template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( - TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs, - CanonType); - - InstD->setAccess(D->getAccess()); - InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); - InstD->setSpecializationKind(D->getSpecializationKind()); - InstD->setTypeAsWritten(WrittenTy); - InstD->setExternLoc(D->getExternLoc()); - InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc()); - - Owner->addDecl(InstD); - - // Instantiate the members of the class-scope explicit specialization eagerly. - // We don't have support for lazy instantiation of an explicit specialization - // yet, and MSVC eagerly instantiates in this case. - // FIXME: This is wrong in standard C++. - if (D->isThisDeclarationADefinition() && - SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs, - TSK_ImplicitInstantiation, - /*Complain=*/true)) - return nullptr; - - return InstD; -} - -Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( - VarTemplateSpecializationDecl *D) { - - TemplateArgumentListInfo VarTemplateArgsInfo; - VarTemplateDecl *VarTemplate = D->getSpecializedTemplate(); - assert(VarTemplate && - "A template specialization without specialized template?"); - - VarTemplateDecl *InstVarTemplate = - cast_or_null<VarTemplateDecl>(SemaRef.FindInstantiatedDecl( - D->getLocation(), VarTemplate, TemplateArgs)); - if (!InstVarTemplate) - return nullptr; - - // Substitute the current template arguments. - const TemplateArgumentListInfo &TemplateArgsInfo = D->getTemplateArgsInfo(); - VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo.getLAngleLoc()); - VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc()); - - if (SemaRef.Subst(TemplateArgsInfo.getArgumentArray(), - TemplateArgsInfo.size(), VarTemplateArgsInfo, TemplateArgs)) - return nullptr; - - // Check that the template argument list is well-formed for this template. - SmallVector<TemplateArgument, 4> Converted; - if (SemaRef.CheckTemplateArgumentList(InstVarTemplate, D->getLocation(), - VarTemplateArgsInfo, false, Converted)) - return nullptr; - - // Check whether we've already seen a declaration of this specialization. - void *InsertPos = nullptr; - VarTemplateSpecializationDecl *PrevDecl = - InstVarTemplate->findSpecialization(Converted, InsertPos); - - // Check whether we've already seen a conflicting instantiation of this - // declaration (for instance, if there was a prior implicit instantiation). - bool Ignored; - if (PrevDecl && SemaRef.CheckSpecializationInstantiationRedecl( - D->getLocation(), D->getSpecializationKind(), PrevDecl, - PrevDecl->getSpecializationKind(), - PrevDecl->getPointOfInstantiation(), Ignored)) - return nullptr; - - return VisitVarTemplateSpecializationDecl( - InstVarTemplate, D, InsertPos, VarTemplateArgsInfo, Converted, PrevDecl); -} - -Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( - VarTemplateDecl *VarTemplate, VarDecl *D, void *InsertPos, - const TemplateArgumentListInfo &TemplateArgsInfo, - ArrayRef<TemplateArgument> Converted, - VarTemplateSpecializationDecl *PrevDecl) { - - // Do substitution on the type of the declaration - TypeSourceInfo *DI = - SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, - D->getTypeSpecStartLoc(), D->getDeclName()); - if (!DI) - return nullptr; - - if (DI->getType()->isFunctionType()) { - SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function) - << D->isStaticDataMember() << DI->getType(); - return nullptr; - } - - // Build the instantiated declaration - VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( - SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), - VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); - Var->setTemplateArgsInfo(TemplateArgsInfo); - if (InsertPos) - VarTemplate->AddSpecialization(Var, InsertPos); - - // Substitute the nested name specifier, if any. - if (SubstQualifier(D, Var)) - return nullptr; - - SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, - StartingScope, false, PrevDecl); - - return Var; -} - -Decl *TemplateDeclInstantiator::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { - llvm_unreachable("@defs is not supported in Objective-C++"); -} - -Decl *TemplateDeclInstantiator::VisitFriendTemplateDecl(FriendTemplateDecl *D) { - // FIXME: We need to be able to instantiate FriendTemplateDecls. - unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID( - DiagnosticsEngine::Error, - "cannot instantiate %0 yet"); - SemaRef.Diag(D->getLocation(), DiagID) - << D->getDeclKindName(); - - return nullptr; -} - -Decl *TemplateDeclInstantiator::VisitConceptDecl(ConceptDecl *D) { - llvm_unreachable("Concept definitions cannot reside inside a template"); -} - -Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) { - llvm_unreachable("Unexpected decl"); -} - -Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); - if (D->isInvalidDecl()) - return nullptr; - - return Instantiator.Visit(D); -} - -/// Instantiates a nested template parameter list in the current -/// instantiation context. -/// -/// \param L The parameter list to instantiate -/// -/// \returns NULL if there was an error -TemplateParameterList * -TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { - // Get errors for all the parameters before bailing out. - bool Invalid = false; - - unsigned N = L->size(); - typedef SmallVector<NamedDecl *, 8> ParamVector; - ParamVector Params; - Params.reserve(N); - for (auto &P : *L) { - NamedDecl *D = cast_or_null<NamedDecl>(Visit(P)); - Params.push_back(D); - Invalid = Invalid || !D || D->isInvalidDecl(); - } - - // Clean up if we had an error. - if (Invalid) - return nullptr; - - // Note: we substitute into associated constraints later - Expr *const UninstantiatedRequiresClause = L->getRequiresClause(); - - TemplateParameterList *InstL - = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(), - L->getLAngleLoc(), Params, - L->getRAngleLoc(), - UninstantiatedRequiresClause); - return InstL; -} - -TemplateParameterList * -Sema::SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); - return Instantiator.SubstTemplateParams(Params); -} - -/// Instantiate the declaration of a class template partial -/// specialization. -/// -/// \param ClassTemplate the (instantiated) class template that is partially -// specialized by the instantiation of \p PartialSpec. -/// -/// \param PartialSpec the (uninstantiated) class template partial -/// specialization that we are instantiating. -/// -/// \returns The instantiated partial specialization, if successful; otherwise, -/// NULL to indicate an error. -ClassTemplatePartialSpecializationDecl * -TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( - ClassTemplateDecl *ClassTemplate, - ClassTemplatePartialSpecializationDecl *PartialSpec) { - // Create a local instantiation scope for this class template partial - // specialization, which will contain the instantiations of the template - // parameters. - LocalInstantiationScope Scope(SemaRef); - - // Substitute into the template parameters of the class template partial - // specialization. - TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - - // Substitute into the template arguments of the class template partial - // specialization. - const ASTTemplateArgumentListInfo *TemplArgInfo - = PartialSpec->getTemplateArgsAsWritten(); - TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, - TemplArgInfo->RAngleLoc); - if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), - TemplArgInfo->NumTemplateArgs, - InstTemplateArgs, TemplateArgs)) - return nullptr; - - // Check that the template argument list is well-formed for this - // class template. - SmallVector<TemplateArgument, 4> Converted; - if (SemaRef.CheckTemplateArgumentList(ClassTemplate, - PartialSpec->getLocation(), - InstTemplateArgs, - false, - Converted)) - return nullptr; - - // Check these arguments are valid for a template partial specialization. - if (SemaRef.CheckTemplatePartialSpecializationArgs( - PartialSpec->getLocation(), ClassTemplate, InstTemplateArgs.size(), - Converted)) - return nullptr; - - // Figure out where to insert this class template partial specialization - // in the member template's set of class template partial specializations. - void *InsertPos = nullptr; - ClassTemplateSpecializationDecl *PrevDecl - = ClassTemplate->findPartialSpecialization(Converted, InsertPos); - - // Build the canonical type that describes the converted template - // arguments of the class template partial specialization. - QualType CanonType - = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), - Converted); - - // Build the fully-sugared type for this class template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy - = SemaRef.Context.getTemplateSpecializationTypeInfo( - TemplateName(ClassTemplate), - PartialSpec->getLocation(), - InstTemplateArgs, - CanonType); - - if (PrevDecl) { - // We've already seen a partial specialization with the same template - // parameters and template arguments. This can happen, for example, when - // substituting the outer template arguments ends up causing two - // class template partial specializations of a member class template - // to have identical forms, e.g., - // - // template<typename T, typename U> - // struct Outer { - // template<typename X, typename Y> struct Inner; - // template<typename Y> struct Inner<T, Y>; - // template<typename Y> struct Inner<U, Y>; - // }; - // - // Outer<int, int> outer; // error: the partial specializations of Inner - // // have the same signature. - SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) - << WrittenTy->getType(); - SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) - << SemaRef.Context.getTypeDeclType(PrevDecl); - return nullptr; - } - - - // Create the class template partial specialization declaration. - ClassTemplatePartialSpecializationDecl *InstPartialSpec = - ClassTemplatePartialSpecializationDecl::Create( - SemaRef.Context, PartialSpec->getTagKind(), Owner, - PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, - ClassTemplate, Converted, InstTemplateArgs, CanonType, nullptr); - // Substitute the nested name specifier, if any. - if (SubstQualifier(PartialSpec, InstPartialSpec)) - return nullptr; - - InstPartialSpec->setInstantiatedFromMember(PartialSpec); - InstPartialSpec->setTypeAsWritten(WrittenTy); - - // Check the completed partial specialization. - SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); - - // Add this partial specialization to the set of class template partial - // specializations. - ClassTemplate->AddPartialSpecialization(InstPartialSpec, - /*InsertPos=*/nullptr); - return InstPartialSpec; -} - -/// Instantiate the declaration of a variable template partial -/// specialization. -/// -/// \param VarTemplate the (instantiated) variable template that is partially -/// specialized by the instantiation of \p PartialSpec. -/// -/// \param PartialSpec the (uninstantiated) variable template partial -/// specialization that we are instantiating. -/// -/// \returns The instantiated partial specialization, if successful; otherwise, -/// NULL to indicate an error. -VarTemplatePartialSpecializationDecl * -TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( - VarTemplateDecl *VarTemplate, - VarTemplatePartialSpecializationDecl *PartialSpec) { - // Create a local instantiation scope for this variable template partial - // specialization, which will contain the instantiations of the template - // parameters. - LocalInstantiationScope Scope(SemaRef); - - // Substitute into the template parameters of the variable template partial - // specialization. - TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); - if (!InstParams) - return nullptr; - - // Substitute into the template arguments of the variable template partial - // specialization. - const ASTTemplateArgumentListInfo *TemplArgInfo - = PartialSpec->getTemplateArgsAsWritten(); - TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, - TemplArgInfo->RAngleLoc); - if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), - TemplArgInfo->NumTemplateArgs, - InstTemplateArgs, TemplateArgs)) - return nullptr; - - // Check that the template argument list is well-formed for this - // class template. - SmallVector<TemplateArgument, 4> Converted; - if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(), - InstTemplateArgs, false, Converted)) - return nullptr; - - // Check these arguments are valid for a template partial specialization. - if (SemaRef.CheckTemplatePartialSpecializationArgs( - PartialSpec->getLocation(), VarTemplate, InstTemplateArgs.size(), - Converted)) - return nullptr; - - // Figure out where to insert this variable template partial specialization - // in the member template's set of variable template partial specializations. - void *InsertPos = nullptr; - VarTemplateSpecializationDecl *PrevDecl = - VarTemplate->findPartialSpecialization(Converted, InsertPos); - - // Build the canonical type that describes the converted template - // arguments of the variable template partial specialization. - QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(VarTemplate), Converted); - - // Build the fully-sugared type for this variable template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( - TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs, - CanonType); - - if (PrevDecl) { - // We've already seen a partial specialization with the same template - // parameters and template arguments. This can happen, for example, when - // substituting the outer template arguments ends up causing two - // variable template partial specializations of a member variable template - // to have identical forms, e.g., - // - // template<typename T, typename U> - // struct Outer { - // template<typename X, typename Y> pair<X,Y> p; - // template<typename Y> pair<T, Y> p; - // template<typename Y> pair<U, Y> p; - // }; - // - // Outer<int, int> outer; // error: the partial specializations of Inner - // // have the same signature. - SemaRef.Diag(PartialSpec->getLocation(), - diag::err_var_partial_spec_redeclared) - << WrittenTy->getType(); - SemaRef.Diag(PrevDecl->getLocation(), - diag::note_var_prev_partial_spec_here); - return nullptr; - } - - // Do substitution on the type of the declaration - TypeSourceInfo *DI = SemaRef.SubstType( - PartialSpec->getTypeSourceInfo(), TemplateArgs, - PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName()); - if (!DI) - return nullptr; - - if (DI->getType()->isFunctionType()) { - SemaRef.Diag(PartialSpec->getLocation(), - diag::err_variable_instantiates_to_function) - << PartialSpec->isStaticDataMember() << DI->getType(); - return nullptr; - } - - // Create the variable template partial specialization declaration. - VarTemplatePartialSpecializationDecl *InstPartialSpec = - VarTemplatePartialSpecializationDecl::Create( - SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), - PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), - DI, PartialSpec->getStorageClass(), Converted, InstTemplateArgs); - - // Substitute the nested name specifier, if any. - if (SubstQualifier(PartialSpec, InstPartialSpec)) - return nullptr; - - InstPartialSpec->setInstantiatedFromMember(PartialSpec); - InstPartialSpec->setTypeAsWritten(WrittenTy); - - // Check the completed partial specialization. - SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); - - // Add this partial specialization to the set of variable template partial - // specializations. The instantiation of the initializer is not necessary. - VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/nullptr); - - SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs, - LateAttrs, Owner, StartingScope); - - return InstPartialSpec; -} - -TypeSourceInfo* -TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, - SmallVectorImpl<ParmVarDecl *> &Params) { - TypeSourceInfo *OldTInfo = D->getTypeSourceInfo(); - assert(OldTInfo && "substituting function without type source info"); - assert(Params.empty() && "parameter vector is non-empty at start"); - - CXXRecordDecl *ThisContext = nullptr; - Qualifiers ThisTypeQuals; - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { - ThisContext = cast<CXXRecordDecl>(Owner); - ThisTypeQuals = Method->getMethodQualifiers(); - } - - TypeSourceInfo *NewTInfo - = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs, - D->getTypeSpecStartLoc(), - D->getDeclName(), - ThisContext, ThisTypeQuals); - if (!NewTInfo) - return nullptr; - - TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); - if (FunctionProtoTypeLoc OldProtoLoc = OldTL.getAs<FunctionProtoTypeLoc>()) { - if (NewTInfo != OldTInfo) { - // Get parameters from the new type info. - TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens(); - FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs<FunctionProtoTypeLoc>(); - unsigned NewIdx = 0; - for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumParams(); - OldIdx != NumOldParams; ++OldIdx) { - ParmVarDecl *OldParam = OldProtoLoc.getParam(OldIdx); - LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope; - - Optional<unsigned> NumArgumentsInExpansion; - if (OldParam->isParameterPack()) - NumArgumentsInExpansion = - SemaRef.getNumArgumentsInExpansion(OldParam->getType(), - TemplateArgs); - if (!NumArgumentsInExpansion) { - // Simple case: normal parameter, or a parameter pack that's - // instantiated to a (still-dependent) parameter pack. - ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++); - Params.push_back(NewParam); - Scope->InstantiatedLocal(OldParam, NewParam); - } else { - // Parameter pack expansion: make the instantiation an argument pack. - Scope->MakeInstantiatedLocalArgPack(OldParam); - for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) { - ParmVarDecl *NewParam = NewProtoLoc.getParam(NewIdx++); - Params.push_back(NewParam); - Scope->InstantiatedLocalPackArg(OldParam, NewParam); - } - } - } - } else { - // The function type itself was not dependent and therefore no - // substitution occurred. However, we still need to instantiate - // the function parameters themselves. - const FunctionProtoType *OldProto = - cast<FunctionProtoType>(OldProtoLoc.getType()); - for (unsigned i = 0, i_end = OldProtoLoc.getNumParams(); i != i_end; - ++i) { - ParmVarDecl *OldParam = OldProtoLoc.getParam(i); - if (!OldParam) { - Params.push_back(SemaRef.BuildParmVarDeclForTypedef( - D, D->getLocation(), OldProto->getParamType(i))); - continue; - } - - ParmVarDecl *Parm = - cast_or_null<ParmVarDecl>(VisitParmVarDecl(OldParam)); - if (!Parm) - return nullptr; - Params.push_back(Parm); - } - } - } else { - // If the type of this function, after ignoring parentheses, is not - // *directly* a function type, then we're instantiating a function that - // was declared via a typedef or with attributes, e.g., - // - // typedef int functype(int, int); - // functype func; - // int __cdecl meth(int, int); - // - // In this case, we'll just go instantiate the ParmVarDecls that we - // synthesized in the method declaration. - SmallVector<QualType, 4> ParamTypes; - Sema::ExtParameterInfoBuilder ExtParamInfos; - if (SemaRef.SubstParmTypes(D->getLocation(), D->parameters(), nullptr, - TemplateArgs, ParamTypes, &Params, - ExtParamInfos)) - return nullptr; - } - - return NewTInfo; -} - -/// Introduce the instantiated function parameters into the local -/// instantiation scope, and set the parameter names to those used -/// in the template. -static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, - const FunctionDecl *PatternDecl, - LocalInstantiationScope &Scope, - const MultiLevelTemplateArgumentList &TemplateArgs) { - unsigned FParamIdx = 0; - for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { - const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); - if (!PatternParam->isParameterPack()) { - // Simple case: not a parameter pack. - assert(FParamIdx < Function->getNumParams()); - ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); - FunctionParam->setDeclName(PatternParam->getDeclName()); - // If the parameter's type is not dependent, update it to match the type - // in the pattern. They can differ in top-level cv-qualifiers, and we want - // the pattern's type here. If the type is dependent, they can't differ, - // per core issue 1668. Substitute into the type from the pattern, in case - // it's instantiation-dependent. - // FIXME: Updating the type to work around this is at best fragile. - if (!PatternDecl->getType()->isDependentType()) { - QualType T = S.SubstType(PatternParam->getType(), TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); - if (T.isNull()) - return true; - FunctionParam->setType(T); - } - - Scope.InstantiatedLocal(PatternParam, FunctionParam); - ++FParamIdx; - continue; - } - - // Expand the parameter pack. - Scope.MakeInstantiatedLocalArgPack(PatternParam); - Optional<unsigned> NumArgumentsInExpansion - = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); - if (NumArgumentsInExpansion) { - QualType PatternType = - PatternParam->getType()->castAs<PackExpansionType>()->getPattern(); - for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) { - ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); - FunctionParam->setDeclName(PatternParam->getDeclName()); - if (!PatternDecl->getType()->isDependentType()) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg); - QualType T = S.SubstType(PatternType, TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); - if (T.isNull()) - return true; - FunctionParam->setType(T); - } - - Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); - ++FParamIdx; - } - } - } - - return false; -} - -void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, - FunctionDecl *Decl) { - const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>(); - if (Proto->getExceptionSpecType() != EST_Uninstantiated) - return; - - InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl, - InstantiatingTemplate::ExceptionSpecification()); - if (Inst.isInvalid()) { - // We hit the instantiation depth limit. Clear the exception specification - // so that our callers don't have to cope with EST_Uninstantiated. - UpdateExceptionSpec(Decl, EST_None); - return; - } - if (Inst.isAlreadyInstantiating()) { - // This exception specification indirectly depends on itself. Reject. - // FIXME: Corresponding rule in the standard? - Diag(PointOfInstantiation, diag::err_exception_spec_cycle) << Decl; - UpdateExceptionSpec(Decl, EST_None); - return; - } - - // Enter the scope of this instantiation. We don't use - // PushDeclContext because we don't have a scope. - Sema::ContextRAII savedContext(*this, Decl); - LocalInstantiationScope Scope(*this); - - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); - - FunctionDecl *Template = Proto->getExceptionSpecTemplate(); - if (addInstantiatedParametersToScope(*this, Decl, Template, Scope, - TemplateArgs)) { - UpdateExceptionSpec(Decl, EST_None); - return; - } - - SubstExceptionSpec(Decl, Template->getType()->castAs<FunctionProtoType>(), - TemplateArgs); -} - -/// Initializes the common fields of an instantiation function -/// declaration (New) from the corresponding fields of its template (Tmpl). -/// -/// \returns true if there was an error -bool -TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, - FunctionDecl *Tmpl) { - if (Tmpl->isDeleted()) - New->setDeletedAsWritten(); - - New->setImplicit(Tmpl->isImplicit()); - - // Forward the mangling number from the template to the instantiated decl. - SemaRef.Context.setManglingNumber(New, - SemaRef.Context.getManglingNumber(Tmpl)); - - // If we are performing substituting explicitly-specified template arguments - // or deduced template arguments into a function template and we reach this - // point, we are now past the point where SFINAE applies and have committed - // to keeping the new function template specialization. We therefore - // convert the active template instantiation for the function template - // into a template instantiation for this specific function template - // specialization, which is not a SFINAE context, so that we diagnose any - // further errors in the declaration itself. - typedef Sema::CodeSynthesisContext ActiveInstType; - ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back(); - if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || - ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { - if (FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(ActiveInst.Entity)) { - assert(FunTmpl->getTemplatedDecl() == Tmpl && - "Deduction from the wrong function template?"); - (void) FunTmpl; - atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); - ActiveInst.Kind = ActiveInstType::TemplateInstantiation; - ActiveInst.Entity = New; - atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst); - } - } - - const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>(); - assert(Proto && "Function template without prototype?"); - - if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) { - FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); - - // DR1330: In C++11, defer instantiation of a non-trivial - // exception specification. - // DR1484: Local classes and their members are instantiated along with the - // containing function. - if (SemaRef.getLangOpts().CPlusPlus11 && - EPI.ExceptionSpec.Type != EST_None && - EPI.ExceptionSpec.Type != EST_DynamicNone && - EPI.ExceptionSpec.Type != EST_BasicNoexcept && - !Tmpl->isLexicallyWithinFunctionOrMethod()) { - FunctionDecl *ExceptionSpecTemplate = Tmpl; - if (EPI.ExceptionSpec.Type == EST_Uninstantiated) - ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate; - ExceptionSpecificationType NewEST = EST_Uninstantiated; - if (EPI.ExceptionSpec.Type == EST_Unevaluated) - NewEST = EST_Unevaluated; - - // Mark the function has having an uninstantiated exception specification. - const FunctionProtoType *NewProto - = New->getType()->getAs<FunctionProtoType>(); - assert(NewProto && "Template instantiation without function prototype?"); - EPI = NewProto->getExtProtoInfo(); - EPI.ExceptionSpec.Type = NewEST; - EPI.ExceptionSpec.SourceDecl = New; - EPI.ExceptionSpec.SourceTemplate = ExceptionSpecTemplate; - New->setType(SemaRef.Context.getFunctionType( - NewProto->getReturnType(), NewProto->getParamTypes(), EPI)); - } else { - Sema::ContextRAII SwitchContext(SemaRef, New); - SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs); - } - } - - // Get the definition. Leaves the variable unchanged if undefined. - const FunctionDecl *Definition = Tmpl; - Tmpl->isDefined(Definition); - - SemaRef.InstantiateAttrs(TemplateArgs, Definition, New, - LateAttrs, StartingScope); - - return false; -} - -/// Initializes common fields of an instantiated method -/// declaration (New) from the corresponding fields of its template -/// (Tmpl). -/// -/// \returns true if there was an error -bool -TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, - CXXMethodDecl *Tmpl) { - if (InitFunctionInstantiation(New, Tmpl)) - return true; - - if (isa<CXXDestructorDecl>(New) && SemaRef.getLangOpts().CPlusPlus11) - SemaRef.AdjustDestructorExceptionSpec(cast<CXXDestructorDecl>(New)); - - New->setAccess(Tmpl->getAccess()); - if (Tmpl->isVirtualAsWritten()) - New->setVirtualAsWritten(true); - - // FIXME: New needs a pointer to Tmpl - return false; -} - -/// Instantiate (or find existing instantiation of) a function template with a -/// given set of template arguments. -/// -/// Usually this should not be used, and template argument deduction should be -/// used in its place. -FunctionDecl * -Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, - const TemplateArgumentList *Args, - SourceLocation Loc) { - FunctionDecl *FD = FTD->getTemplatedDecl(); - - sema::TemplateDeductionInfo Info(Loc); - InstantiatingTemplate Inst( - *this, Loc, FTD, Args->asArray(), - CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info); - if (Inst.isInvalid()) - return nullptr; - - ContextRAII SavedContext(*this, FD); - MultiLevelTemplateArgumentList MArgs(*Args); - - return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs)); -} - -/// In the MS ABI, we need to instantiate default arguments of dllexported -/// default constructors along with the constructor definition. This allows IR -/// gen to emit a constructor closure which calls the default constructor with -/// its default arguments. -static void InstantiateDefaultCtorDefaultArgs(Sema &S, - CXXConstructorDecl *Ctor) { - assert(S.Context.getTargetInfo().getCXXABI().isMicrosoft() && - Ctor->isDefaultConstructor()); - unsigned NumParams = Ctor->getNumParams(); - if (NumParams == 0) - return; - DLLExportAttr *Attr = Ctor->getAttr<DLLExportAttr>(); - if (!Attr) - return; - for (unsigned I = 0; I != NumParams; ++I) { - (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor, - Ctor->getParamDecl(I)); - S.DiscardCleanupsInEvaluationContext(); - } -} - -/// Instantiate the definition of the given function from its -/// template. -/// -/// \param PointOfInstantiation the point at which the instantiation was -/// required. Note that this is not precisely a "point of instantiation" -/// for the function, but it's close. -/// -/// \param Function the already-instantiated declaration of a -/// function template specialization or member function of a class template -/// specialization. -/// -/// \param Recursive if true, recursively instantiates any functions that -/// are required by this instantiation. -/// -/// \param DefinitionRequired if true, then we are performing an explicit -/// instantiation where the body of the function is required. Complain if -/// there is no such body. -void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, - FunctionDecl *Function, - bool Recursive, - bool DefinitionRequired, - bool AtEndOfTU) { - if (Function->isInvalidDecl() || Function->isDefined() || - isa<CXXDeductionGuideDecl>(Function)) - return; - - // Never instantiate an explicit specialization except if it is a class scope - // explicit specialization. - TemplateSpecializationKind TSK = - Function->getTemplateSpecializationKindForInstantiation(); - if (TSK == TSK_ExplicitSpecialization) - return; - - // Find the function body that we'll be substituting. - const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); - assert(PatternDecl && "instantiating a non-template"); - - const FunctionDecl *PatternDef = PatternDecl->getDefinition(); - Stmt *Pattern = nullptr; - if (PatternDef) { - Pattern = PatternDef->getBody(PatternDef); - PatternDecl = PatternDef; - if (PatternDef->willHaveBody()) - PatternDef = nullptr; - } - - // FIXME: We need to track the instantiation stack in order to know which - // definitions should be visible within this instantiation. - if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Function, - Function->getInstantiatedFromMemberFunction(), - PatternDecl, PatternDef, TSK, - /*Complain*/DefinitionRequired)) { - if (DefinitionRequired) - Function->setInvalidDecl(); - else if (TSK == TSK_ExplicitInstantiationDefinition) { - // Try again at the end of the translation unit (at which point a - // definition will be required). - assert(!Recursive); - Function->setInstantiationIsPending(true); - PendingInstantiations.push_back( - std::make_pair(Function, PointOfInstantiation)); - } else if (TSK == TSK_ImplicitInstantiation) { - if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && - !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) { - Diag(PointOfInstantiation, diag::warn_func_template_missing) - << Function; - Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); - if (getLangOpts().CPlusPlus11) - Diag(PointOfInstantiation, diag::note_inst_declaration_hint) - << Function; - } - } - - return; - } - - // Postpone late parsed template instantiations. - if (PatternDecl->isLateTemplateParsed() && - !LateTemplateParser) { - Function->setInstantiationIsPending(true); - LateParsedInstantiations.push_back( - std::make_pair(Function, PointOfInstantiation)); - return; - } - - llvm::TimeTraceScope TimeScope("InstantiateFunction", [&]() { - std::string Name; - llvm::raw_string_ostream OS(Name); - Function->getNameForDiagnostic(OS, getPrintingPolicy(), - /*Qualified=*/true); - return Name; - }); - - // If we're performing recursive template instantiation, create our own - // queue of pending implicit instantiations that we will instantiate later, - // while we're still within our own instantiation context. - // This has to happen before LateTemplateParser below is called, so that - // it marks vtables used in late parsed templates as used. - GlobalEagerInstantiationScope GlobalInstantiations(*this, - /*Enabled=*/Recursive); - LocalEagerInstantiationScope LocalInstantiations(*this); - - // Call the LateTemplateParser callback if there is a need to late parse - // a templated function definition. - if (!Pattern && PatternDecl->isLateTemplateParsed() && - LateTemplateParser) { - // FIXME: Optimize to allow individual templates to be deserialized. - if (PatternDecl->isFromASTFile()) - ExternalSource->ReadLateParsedTemplates(LateParsedTemplateMap); - - auto LPTIter = LateParsedTemplateMap.find(PatternDecl); - assert(LPTIter != LateParsedTemplateMap.end() && - "missing LateParsedTemplate"); - LateTemplateParser(OpaqueParser, *LPTIter->second); - Pattern = PatternDecl->getBody(PatternDecl); - } - - // Note, we should never try to instantiate a deleted function template. - assert((Pattern || PatternDecl->isDefaulted() || - PatternDecl->hasSkippedBody()) && - "unexpected kind of function template definition"); - - // C++1y [temp.explicit]p10: - // Except for inline functions, declarations with types deduced from their - // initializer or return value, and class template specializations, other - // explicit instantiation declarations have the effect of suppressing the - // implicit instantiation of the entity to which they refer. - if (TSK == TSK_ExplicitInstantiationDeclaration && - !PatternDecl->isInlined() && - !PatternDecl->getReturnType()->getContainedAutoType()) - return; - - if (PatternDecl->isInlined()) { - // Function, and all later redeclarations of it (from imported modules, - // for instance), are now implicitly inline. - for (auto *D = Function->getMostRecentDecl(); /**/; - D = D->getPreviousDecl()) { - D->setImplicitlyInline(); - if (D == Function) - break; - } - } - - InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); - if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) - return; - PrettyDeclStackTraceEntry CrashInfo(Context, Function, SourceLocation(), - "instantiating function definition"); - - // The instantiation is visible here, even if it was first declared in an - // unimported module. - Function->setVisibleDespiteOwningModule(); - - // Copy the inner loc start from the pattern. - Function->setInnerLocStart(PatternDecl->getInnerLocStart()); - - EnterExpressionEvaluationContext EvalContext( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); - - // Introduce a new scope where local variable instantiations will be - // recorded, unless we're actually a member function within a local - // class, in which case we need to merge our results with the parent - // scope (of the enclosing function). - bool MergeWithParentScope = false; - if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext())) - MergeWithParentScope = Rec->isLocalClass(); - - LocalInstantiationScope Scope(*this, MergeWithParentScope); - - if (PatternDecl->isDefaulted()) - SetDeclDefaulted(Function, PatternDecl->getLocation()); - else { - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl); - - // Substitute into the qualifier; we can get a substitution failure here - // through evil use of alias templates. - // FIXME: Is CurContext correct for this? Should we go to the (instantiation - // of the) lexical context of the pattern? - SubstQualifier(*this, PatternDecl, Function, TemplateArgs); - - ActOnStartOfFunctionDef(nullptr, Function); - - // Enter the scope of this instantiation. We don't use - // PushDeclContext because we don't have a scope. - Sema::ContextRAII savedContext(*this, Function); - - if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, - TemplateArgs)) - return; - - StmtResult Body; - if (PatternDecl->hasSkippedBody()) { - ActOnSkippedFunctionBody(Function); - Body = nullptr; - } else { - if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) { - // If this is a constructor, instantiate the member initializers. - InstantiateMemInitializers(Ctor, cast<CXXConstructorDecl>(PatternDecl), - TemplateArgs); - - // If this is an MS ABI dllexport default constructor, instantiate any - // default arguments. - if (Context.getTargetInfo().getCXXABI().isMicrosoft() && - Ctor->isDefaultConstructor()) { - InstantiateDefaultCtorDefaultArgs(*this, Ctor); - } - } - - // Instantiate the function body. - Body = SubstStmt(Pattern, TemplateArgs); - - if (Body.isInvalid()) - Function->setInvalidDecl(); - } - // FIXME: finishing the function body while in an expression evaluation - // context seems wrong. Investigate more. - ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true); - - PerformDependentDiagnostics(PatternDecl, TemplateArgs); - - if (auto *Listener = getASTMutationListener()) - Listener->FunctionDefinitionInstantiated(Function); - - savedContext.pop(); - } - - DeclGroupRef DG(Function); - Consumer.HandleTopLevelDecl(DG); - - // This class may have local implicit instantiations that need to be - // instantiation within this scope. - LocalInstantiations.perform(); - Scope.Exit(); - GlobalInstantiations.perform(); -} - -VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( - VarTemplateDecl *VarTemplate, VarDecl *FromVar, - const TemplateArgumentList &TemplateArgList, - const TemplateArgumentListInfo &TemplateArgsInfo, - SmallVectorImpl<TemplateArgument> &Converted, - SourceLocation PointOfInstantiation, void *InsertPos, - LateInstantiatedAttrVec *LateAttrs, - LocalInstantiationScope *StartingScope) { - if (FromVar->isInvalidDecl()) - return nullptr; - - InstantiatingTemplate Inst(*this, PointOfInstantiation, FromVar); - if (Inst.isInvalid()) - return nullptr; - - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgList); - - // Instantiate the first declaration of the variable template: for a partial - // specialization of a static data member template, the first declaration may - // or may not be the declaration in the class; if it's in the class, we want - // to instantiate a member in the class (a declaration), and if it's outside, - // we want to instantiate a definition. - // - // If we're instantiating an explicitly-specialized member template or member - // partial specialization, don't do this. The member specialization completely - // replaces the original declaration in this case. - bool IsMemberSpec = false; - if (VarTemplatePartialSpecializationDecl *PartialSpec = - dyn_cast<VarTemplatePartialSpecializationDecl>(FromVar)) - IsMemberSpec = PartialSpec->isMemberSpecialization(); - else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate()) - IsMemberSpec = FromTemplate->isMemberSpecialization(); - if (!IsMemberSpec) - FromVar = FromVar->getFirstDecl(); - - MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList); - TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(), - MultiLevelList); - - // TODO: Set LateAttrs and StartingScope ... - - return cast_or_null<VarTemplateSpecializationDecl>( - Instantiator.VisitVarTemplateSpecializationDecl( - VarTemplate, FromVar, InsertPos, TemplateArgsInfo, Converted)); -} - -/// Instantiates a variable template specialization by completing it -/// with appropriate type information and initializer. -VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( - VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, - const MultiLevelTemplateArgumentList &TemplateArgs) { - assert(PatternDecl->isThisDeclarationADefinition() && - "don't have a definition to instantiate from"); - - // Do substitution on the type of the declaration - TypeSourceInfo *DI = - SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs, - PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName()); - if (!DI) - return nullptr; - - // Update the type of this variable template specialization. - VarSpec->setType(DI->getType()); - - // Convert the declaration into a definition now. - VarSpec->setCompleteDefinition(); - - // Instantiate the initializer. - InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs); - - return VarSpec; -} - -/// BuildVariableInstantiation - Used after a new variable has been created. -/// Sets basic variable data and decides whether to postpone the -/// variable instantiation. -void Sema::BuildVariableInstantiation( - VarDecl *NewVar, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs, - LateInstantiatedAttrVec *LateAttrs, DeclContext *Owner, - LocalInstantiationScope *StartingScope, - bool InstantiatingVarTemplate, - VarTemplateSpecializationDecl *PrevDeclForVarTemplateSpecialization) { - // Instantiating a partial specialization to produce a partial - // specialization. - bool InstantiatingVarTemplatePartialSpec = - isa<VarTemplatePartialSpecializationDecl>(OldVar) && - isa<VarTemplatePartialSpecializationDecl>(NewVar); - // Instantiating from a variable template (or partial specialization) to - // produce a variable template specialization. - bool InstantiatingSpecFromTemplate = - isa<VarTemplateSpecializationDecl>(NewVar) && - (OldVar->getDescribedVarTemplate() || - isa<VarTemplatePartialSpecializationDecl>(OldVar)); - - // If we are instantiating a local extern declaration, the - // instantiation belongs lexically to the containing function. - // If we are instantiating a static data member defined - // out-of-line, the instantiation will have the same lexical - // context (which will be a namespace scope) as the template. - if (OldVar->isLocalExternDecl()) { - NewVar->setLocalExternDecl(); - NewVar->setLexicalDeclContext(Owner); - } else if (OldVar->isOutOfLine()) - NewVar->setLexicalDeclContext(OldVar->getLexicalDeclContext()); - NewVar->setTSCSpec(OldVar->getTSCSpec()); - NewVar->setInitStyle(OldVar->getInitStyle()); - NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); - NewVar->setObjCForDecl(OldVar->isObjCForDecl()); - NewVar->setConstexpr(OldVar->isConstexpr()); - NewVar->setInitCapture(OldVar->isInitCapture()); - NewVar->setPreviousDeclInSameBlockScope( - OldVar->isPreviousDeclInSameBlockScope()); - NewVar->setAccess(OldVar->getAccess()); - - if (!OldVar->isStaticDataMember()) { - if (OldVar->isUsed(false)) - NewVar->setIsUsed(); - NewVar->setReferenced(OldVar->isReferenced()); - } - - InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope); - - LookupResult Previous( - *this, NewVar->getDeclName(), NewVar->getLocation(), - NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage - : Sema::LookupOrdinaryName, - NewVar->isLocalExternDecl() ? Sema::ForExternalRedeclaration - : forRedeclarationInCurContext()); - - if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() && - (!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() || - OldVar->getPreviousDecl()->getDeclContext()==OldVar->getDeclContext())) { - // We have a previous declaration. Use that one, so we merge with the - // right type. - if (NamedDecl *NewPrev = FindInstantiatedDecl( - NewVar->getLocation(), OldVar->getPreviousDecl(), TemplateArgs)) - Previous.addDecl(NewPrev); - } else if (!isa<VarTemplateSpecializationDecl>(NewVar) && - OldVar->hasLinkage()) { - LookupQualifiedName(Previous, NewVar->getDeclContext(), false); - } else if (PrevDeclForVarTemplateSpecialization) { - Previous.addDecl(PrevDeclForVarTemplateSpecialization); - } - CheckVariableDeclaration(NewVar, Previous); - - if (!InstantiatingVarTemplate) { - NewVar->getLexicalDeclContext()->addHiddenDecl(NewVar); - if (!NewVar->isLocalExternDecl() || !NewVar->getPreviousDecl()) - NewVar->getDeclContext()->makeDeclVisibleInContext(NewVar); - } - - if (!OldVar->isOutOfLine()) { - if (NewVar->getDeclContext()->isFunctionOrMethod()) - CurrentInstantiationScope->InstantiatedLocal(OldVar, NewVar); - } - - // Link instantiations of static data members back to the template from - // which they were instantiated. - // - // Don't do this when instantiating a template (we link the template itself - // back in that case) nor when instantiating a static data member template - // (that's not a member specialization). - if (NewVar->isStaticDataMember() && !InstantiatingVarTemplate && - !InstantiatingSpecFromTemplate) - NewVar->setInstantiationOfStaticDataMember(OldVar, - TSK_ImplicitInstantiation); - - // If the pattern is an (in-class) explicit specialization, then the result - // is also an explicit specialization. - if (VarTemplateSpecializationDecl *OldVTSD = - dyn_cast<VarTemplateSpecializationDecl>(OldVar)) { - if (OldVTSD->getSpecializationKind() == TSK_ExplicitSpecialization && - !isa<VarTemplatePartialSpecializationDecl>(OldVTSD)) - cast<VarTemplateSpecializationDecl>(NewVar)->setSpecializationKind( - TSK_ExplicitSpecialization); - } - - // Forward the mangling number from the template to the instantiated decl. - Context.setManglingNumber(NewVar, Context.getManglingNumber(OldVar)); - Context.setStaticLocalNumber(NewVar, Context.getStaticLocalNumber(OldVar)); - - // Figure out whether to eagerly instantiate the initializer. - if (InstantiatingVarTemplate || InstantiatingVarTemplatePartialSpec) { - // We're producing a template. Don't instantiate the initializer yet. - } else if (NewVar->getType()->isUndeducedType()) { - // We need the type to complete the declaration of the variable. - InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); - } else if (InstantiatingSpecFromTemplate || - (OldVar->isInline() && OldVar->isThisDeclarationADefinition() && - !NewVar->isThisDeclarationADefinition())) { - // Delay instantiation of the initializer for variable template - // specializations or inline static data members until a definition of the - // variable is needed. - } else { - InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); - } - - // Diagnose unused local variables with dependent types, where the diagnostic - // will have been deferred. - if (!NewVar->isInvalidDecl() && - NewVar->getDeclContext()->isFunctionOrMethod() && - OldVar->getType()->isDependentType()) - DiagnoseUnusedDecl(NewVar); -} - -/// Instantiate the initializer of a variable. -void Sema::InstantiateVariableInitializer( - VarDecl *Var, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs) { - if (ASTMutationListener *L = getASTContext().getASTMutationListener()) - L->VariableDefinitionInstantiated(Var); - - // We propagate the 'inline' flag with the initializer, because it - // would otherwise imply that the variable is a definition for a - // non-static data member. - if (OldVar->isInlineSpecified()) - Var->setInlineSpecified(); - else if (OldVar->isInline()) - Var->setImplicitlyInline(); - - if (OldVar->getInit()) { - EnterExpressionEvaluationContext Evaluated( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); - - // Instantiate the initializer. - ExprResult Init; - - { - ContextRAII SwitchContext(*this, Var->getDeclContext()); - Init = SubstInitializer(OldVar->getInit(), TemplateArgs, - OldVar->getInitStyle() == VarDecl::CallInit); - } - - if (!Init.isInvalid()) { - Expr *InitExpr = Init.get(); - - if (Var->hasAttr<DLLImportAttr>() && - (!InitExpr || - !InitExpr->isConstantInitializer(getASTContext(), false))) { - // Do not dynamically initialize dllimport variables. - } else if (InitExpr) { - bool DirectInit = OldVar->isDirectInit(); - AddInitializerToDecl(Var, InitExpr, DirectInit); - } else - ActOnUninitializedDecl(Var); - } else { - // FIXME: Not too happy about invalidating the declaration - // because of a bogus initializer. - Var->setInvalidDecl(); - } - } else { - // `inline` variables are a definition and declaration all in one; we won't - // pick up an initializer from anywhere else. - if (Var->isStaticDataMember() && !Var->isInline()) { - if (!Var->isOutOfLine()) - return; - - // If the declaration inside the class had an initializer, don't add - // another one to the out-of-line definition. - if (OldVar->getFirstDecl()->hasInit()) - return; - } - - // We'll add an initializer to a for-range declaration later. - if (Var->isCXXForRangeDecl() || Var->isObjCForDecl()) - return; - - ActOnUninitializedDecl(Var); - } - - if (getLangOpts().CUDA) - checkAllowedCUDAInitializer(Var); -} - -/// Instantiate the definition of the given variable from its -/// template. -/// -/// \param PointOfInstantiation the point at which the instantiation was -/// required. Note that this is not precisely a "point of instantiation" -/// for the variable, but it's close. -/// -/// \param Var the already-instantiated declaration of a templated variable. -/// -/// \param Recursive if true, recursively instantiates any functions that -/// are required by this instantiation. -/// -/// \param DefinitionRequired if true, then we are performing an explicit -/// instantiation where a definition of the variable is required. Complain -/// if there is no such definition. -void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, - VarDecl *Var, bool Recursive, - bool DefinitionRequired, bool AtEndOfTU) { - if (Var->isInvalidDecl()) - return; - - // Never instantiate an explicitly-specialized entity. - TemplateSpecializationKind TSK = - Var->getTemplateSpecializationKindForInstantiation(); - if (TSK == TSK_ExplicitSpecialization) - return; - - // Find the pattern and the arguments to substitute into it. - VarDecl *PatternDecl = Var->getTemplateInstantiationPattern(); - assert(PatternDecl && "no pattern for templated variable"); - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(Var); - - VarTemplateSpecializationDecl *VarSpec = - dyn_cast<VarTemplateSpecializationDecl>(Var); - if (VarSpec) { - // If this is a variable template specialization, make sure that it is - // non-dependent. - bool InstantiationDependent = false; - assert(!TemplateSpecializationType::anyDependentTemplateArguments( - VarSpec->getTemplateArgsInfo(), InstantiationDependent) && - "Only instantiate variable template specializations that are " - "not type-dependent"); - (void)InstantiationDependent; - - // If this is a static data member template, there might be an - // uninstantiated initializer on the declaration. If so, instantiate - // it now. - // - // FIXME: This largely duplicates what we would do below. The difference - // is that along this path we may instantiate an initializer from an - // in-class declaration of the template and instantiate the definition - // from a separate out-of-class definition. - if (PatternDecl->isStaticDataMember() && - (PatternDecl = PatternDecl->getFirstDecl())->hasInit() && - !Var->hasInit()) { - // FIXME: Factor out the duplicated instantiation context setup/tear down - // code here. - InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); - if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) - return; - PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(), - "instantiating variable initializer"); - - // The instantiation is visible here, even if it was first declared in an - // unimported module. - Var->setVisibleDespiteOwningModule(); - - // If we're performing recursive template instantiation, create our own - // queue of pending implicit instantiations that we will instantiate - // later, while we're still within our own instantiation context. - GlobalEagerInstantiationScope GlobalInstantiations(*this, - /*Enabled=*/Recursive); - LocalInstantiationScope Local(*this); - LocalEagerInstantiationScope LocalInstantiations(*this); - - // Enter the scope of this instantiation. We don't use - // PushDeclContext because we don't have a scope. - ContextRAII PreviousContext(*this, Var->getDeclContext()); - InstantiateVariableInitializer(Var, PatternDecl, TemplateArgs); - PreviousContext.pop(); - - // This variable may have local implicit instantiations that need to be - // instantiated within this scope. - LocalInstantiations.perform(); - Local.Exit(); - GlobalInstantiations.perform(); - } - } else { - assert(Var->isStaticDataMember() && PatternDecl->isStaticDataMember() && - "not a static data member?"); - } - - VarDecl *Def = PatternDecl->getDefinition(getASTContext()); - - // If we don't have a definition of the variable template, we won't perform - // any instantiation. Rather, we rely on the user to instantiate this - // definition (or provide a specialization for it) in another translation - // unit. - if (!Def && !DefinitionRequired) { - if (TSK == TSK_ExplicitInstantiationDefinition) { - PendingInstantiations.push_back( - std::make_pair(Var, PointOfInstantiation)); - } else if (TSK == TSK_ImplicitInstantiation) { - // Warn about missing definition at the end of translation unit. - if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() && - !getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) { - Diag(PointOfInstantiation, diag::warn_var_template_missing) - << Var; - Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); - if (getLangOpts().CPlusPlus11) - Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var; - } - return; - } - } - - // FIXME: We need to track the instantiation stack in order to know which - // definitions should be visible within this instantiation. - // FIXME: Produce diagnostics when Var->getInstantiatedFromStaticDataMember(). - if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Var, - /*InstantiatedFromMember*/false, - PatternDecl, Def, TSK, - /*Complain*/DefinitionRequired)) - return; - - // C++11 [temp.explicit]p10: - // Except for inline functions, const variables of literal types, variables - // of reference types, [...] explicit instantiation declarations - // have the effect of suppressing the implicit instantiation of the entity - // to which they refer. - // - // FIXME: That's not exactly the same as "might be usable in constant - // expressions", which only allows constexpr variables and const integral - // types, not arbitrary const literal types. - if (TSK == TSK_ExplicitInstantiationDeclaration && - !Var->mightBeUsableInConstantExpressions(getASTContext())) - return; - - // Make sure to pass the instantiated variable to the consumer at the end. - struct PassToConsumerRAII { - ASTConsumer &Consumer; - VarDecl *Var; - - PassToConsumerRAII(ASTConsumer &Consumer, VarDecl *Var) - : Consumer(Consumer), Var(Var) { } - - ~PassToConsumerRAII() { - Consumer.HandleCXXStaticMemberVarInstantiation(Var); - } - } PassToConsumerRAII(Consumer, Var); - - // If we already have a definition, we're done. - if (VarDecl *Def = Var->getDefinition()) { - // We may be explicitly instantiating something we've already implicitly - // instantiated. - Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(), - PointOfInstantiation); - return; - } - - InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); - if (Inst.isInvalid() || Inst.isAlreadyInstantiating()) - return; - PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(), - "instantiating variable definition"); - - // If we're performing recursive template instantiation, create our own - // queue of pending implicit instantiations that we will instantiate later, - // while we're still within our own instantiation context. - GlobalEagerInstantiationScope GlobalInstantiations(*this, - /*Enabled=*/Recursive); - - // Enter the scope of this instantiation. We don't use - // PushDeclContext because we don't have a scope. - ContextRAII PreviousContext(*this, Var->getDeclContext()); - LocalInstantiationScope Local(*this); - - LocalEagerInstantiationScope LocalInstantiations(*this); - - VarDecl *OldVar = Var; - if (Def->isStaticDataMember() && !Def->isOutOfLine()) { - // We're instantiating an inline static data member whose definition was - // provided inside the class. - InstantiateVariableInitializer(Var, Def, TemplateArgs); - } else if (!VarSpec) { - Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), - TemplateArgs)); - } else if (Var->isStaticDataMember() && - Var->getLexicalDeclContext()->isRecord()) { - // We need to instantiate the definition of a static data member template, - // and all we have is the in-class declaration of it. Instantiate a separate - // declaration of the definition. - TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), - TemplateArgs); - Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl( - VarSpec->getSpecializedTemplate(), Def, nullptr, - VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray())); - if (Var) { - llvm::PointerUnion<VarTemplateDecl *, - VarTemplatePartialSpecializationDecl *> PatternPtr = - VarSpec->getSpecializedTemplateOrPartial(); - if (VarTemplatePartialSpecializationDecl *Partial = - PatternPtr.dyn_cast<VarTemplatePartialSpecializationDecl *>()) - cast<VarTemplateSpecializationDecl>(Var)->setInstantiationOf( - Partial, &VarSpec->getTemplateInstantiationArgs()); - - // Merge the definition with the declaration. - LookupResult R(*this, Var->getDeclName(), Var->getLocation(), - LookupOrdinaryName, forRedeclarationInCurContext()); - R.addDecl(OldVar); - MergeVarDecl(Var, R); - - // Attach the initializer. - InstantiateVariableInitializer(Var, Def, TemplateArgs); - } - } else - // Complete the existing variable's definition with an appropriately - // substituted type and initializer. - Var = CompleteVarTemplateSpecializationDecl(VarSpec, Def, TemplateArgs); - - PreviousContext.pop(); - - if (Var) { - PassToConsumerRAII.Var = Var; - Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind(), - OldVar->getPointOfInstantiation()); - } - - // This variable may have local implicit instantiations that need to be - // instantiated within this scope. - LocalInstantiations.perform(); - Local.Exit(); - GlobalInstantiations.perform(); -} - -void -Sema::InstantiateMemInitializers(CXXConstructorDecl *New, - const CXXConstructorDecl *Tmpl, - const MultiLevelTemplateArgumentList &TemplateArgs) { - - SmallVector<CXXCtorInitializer*, 4> NewInits; - bool AnyErrors = Tmpl->isInvalidDecl(); - - // Instantiate all the initializers. - for (const auto *Init : Tmpl->inits()) { - // Only instantiate written initializers, let Sema re-construct implicit - // ones. - if (!Init->isWritten()) - continue; - - SourceLocation EllipsisLoc; - - if (Init->isPackExpansion()) { - // This is a pack expansion. We should expand it now. - TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc(); - SmallVector<UnexpandedParameterPack, 4> Unexpanded; - collectUnexpandedParameterPacks(BaseTL, Unexpanded); - collectUnexpandedParameterPacks(Init->getInit(), Unexpanded); - bool ShouldExpand = false; - bool RetainExpansion = false; - Optional<unsigned> NumExpansions; - if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), - BaseTL.getSourceRange(), - Unexpanded, - TemplateArgs, ShouldExpand, - RetainExpansion, - NumExpansions)) { - AnyErrors = true; - New->setInvalidDecl(); - continue; - } - assert(ShouldExpand && "Partial instantiation of base initializer?"); - - // Loop over all of the arguments in the argument pack(s), - for (unsigned I = 0; I != *NumExpansions; ++I) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); - - // Instantiate the initializer. - ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, - /*CXXDirectInit=*/true); - if (TempInit.isInvalid()) { - AnyErrors = true; - break; - } - - // Instantiate the base type. - TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(), - TemplateArgs, - Init->getSourceLocation(), - New->getDeclName()); - if (!BaseTInfo) { - AnyErrors = true; - break; - } - - // Build the initializer. - MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), - BaseTInfo, TempInit.get(), - New->getParent(), - SourceLocation()); - if (NewInit.isInvalid()) { - AnyErrors = true; - break; - } - - NewInits.push_back(NewInit.get()); - } - - continue; - } - - // Instantiate the initializer. - ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, - /*CXXDirectInit=*/true); - if (TempInit.isInvalid()) { - AnyErrors = true; - continue; - } - - MemInitResult NewInit; - if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) { - TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(), - TemplateArgs, - Init->getSourceLocation(), - New->getDeclName()); - if (!TInfo) { - AnyErrors = true; - New->setInvalidDecl(); - continue; - } - - if (Init->isBaseInitializer()) - NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.get(), - New->getParent(), EllipsisLoc); - else - NewInit = BuildDelegatingInitializer(TInfo, TempInit.get(), - cast<CXXRecordDecl>(CurContext->getParent())); - } else if (Init->isMemberInitializer()) { - FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl( - Init->getMemberLocation(), - Init->getMember(), - TemplateArgs)); - if (!Member) { - AnyErrors = true; - New->setInvalidDecl(); - continue; - } - - NewInit = BuildMemberInitializer(Member, TempInit.get(), - Init->getSourceLocation()); - } else if (Init->isIndirectMemberInitializer()) { - IndirectFieldDecl *IndirectMember = - cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl( - Init->getMemberLocation(), - Init->getIndirectMember(), TemplateArgs)); - - if (!IndirectMember) { - AnyErrors = true; - New->setInvalidDecl(); - continue; - } - - NewInit = BuildMemberInitializer(IndirectMember, TempInit.get(), - Init->getSourceLocation()); - } - - if (NewInit.isInvalid()) { - AnyErrors = true; - New->setInvalidDecl(); - } else { - NewInits.push_back(NewInit.get()); - } - } - - // Assign all the initializers to the new constructor. - ActOnMemInitializers(New, - /*FIXME: ColonLoc */ - SourceLocation(), - NewInits, - AnyErrors); -} - -// TODO: this could be templated if the various decl types used the -// same method name. -static bool isInstantiationOf(ClassTemplateDecl *Pattern, - ClassTemplateDecl *Instance) { - Pattern = Pattern->getCanonicalDecl(); - - do { - Instance = Instance->getCanonicalDecl(); - if (Pattern == Instance) return true; - Instance = Instance->getInstantiatedFromMemberTemplate(); - } while (Instance); - - return false; -} - -static bool isInstantiationOf(FunctionTemplateDecl *Pattern, - FunctionTemplateDecl *Instance) { - Pattern = Pattern->getCanonicalDecl(); - - do { - Instance = Instance->getCanonicalDecl(); - if (Pattern == Instance) return true; - Instance = Instance->getInstantiatedFromMemberTemplate(); - } while (Instance); - - return false; -} - -static bool -isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern, - ClassTemplatePartialSpecializationDecl *Instance) { - Pattern - = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl()); - do { - Instance = cast<ClassTemplatePartialSpecializationDecl>( - Instance->getCanonicalDecl()); - if (Pattern == Instance) - return true; - Instance = Instance->getInstantiatedFromMember(); - } while (Instance); - - return false; -} - -static bool isInstantiationOf(CXXRecordDecl *Pattern, - CXXRecordDecl *Instance) { - Pattern = Pattern->getCanonicalDecl(); - - do { - Instance = Instance->getCanonicalDecl(); - if (Pattern == Instance) return true; - Instance = Instance->getInstantiatedFromMemberClass(); - } while (Instance); - - return false; -} - -static bool isInstantiationOf(FunctionDecl *Pattern, - FunctionDecl *Instance) { - Pattern = Pattern->getCanonicalDecl(); - - do { - Instance = Instance->getCanonicalDecl(); - if (Pattern == Instance) return true; - Instance = Instance->getInstantiatedFromMemberFunction(); - } while (Instance); - - return false; -} - -static bool isInstantiationOf(EnumDecl *Pattern, - EnumDecl *Instance) { - Pattern = Pattern->getCanonicalDecl(); - - do { - Instance = Instance->getCanonicalDecl(); - if (Pattern == Instance) return true; - Instance = Instance->getInstantiatedFromMemberEnum(); - } while (Instance); - - return false; -} - -static bool isInstantiationOf(UsingShadowDecl *Pattern, - UsingShadowDecl *Instance, - ASTContext &C) { - return declaresSameEntity(C.getInstantiatedFromUsingShadowDecl(Instance), - Pattern); -} - -static bool isInstantiationOf(UsingDecl *Pattern, UsingDecl *Instance, - ASTContext &C) { - return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern); -} - -template<typename T> -static bool isInstantiationOfUnresolvedUsingDecl(T *Pattern, Decl *Other, - ASTContext &Ctx) { - // An unresolved using declaration can instantiate to an unresolved using - // declaration, or to a using declaration or a using declaration pack. - // - // Multiple declarations can claim to be instantiated from an unresolved - // using declaration if it's a pack expansion. We want the UsingPackDecl - // in that case, not the individual UsingDecls within the pack. - bool OtherIsPackExpansion; - NamedDecl *OtherFrom; - if (auto *OtherUUD = dyn_cast<T>(Other)) { - OtherIsPackExpansion = OtherUUD->isPackExpansion(); - OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUUD); - } else if (auto *OtherUPD = dyn_cast<UsingPackDecl>(Other)) { - OtherIsPackExpansion = true; - OtherFrom = OtherUPD->getInstantiatedFromUsingDecl(); - } else if (auto *OtherUD = dyn_cast<UsingDecl>(Other)) { - OtherIsPackExpansion = false; - OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUD); - } else { - return false; - } - return Pattern->isPackExpansion() == OtherIsPackExpansion && - declaresSameEntity(OtherFrom, Pattern); -} - -static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, - VarDecl *Instance) { - assert(Instance->isStaticDataMember()); - - Pattern = Pattern->getCanonicalDecl(); - - do { - Instance = Instance->getCanonicalDecl(); - if (Pattern == Instance) return true; - Instance = Instance->getInstantiatedFromStaticDataMember(); - } while (Instance); - - return false; -} - -// Other is the prospective instantiation -// D is the prospective pattern -static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { - if (auto *UUD = dyn_cast<UnresolvedUsingTypenameDecl>(D)) - return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx); - - if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(D)) - return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx); - - if (D->getKind() != Other->getKind()) - return false; - - if (auto *Record = dyn_cast<CXXRecordDecl>(Other)) - return isInstantiationOf(cast<CXXRecordDecl>(D), Record); - - if (auto *Function = dyn_cast<FunctionDecl>(Other)) - return isInstantiationOf(cast<FunctionDecl>(D), Function); - - if (auto *Enum = dyn_cast<EnumDecl>(Other)) - return isInstantiationOf(cast<EnumDecl>(D), Enum); - - if (auto *Var = dyn_cast<VarDecl>(Other)) - if (Var->isStaticDataMember()) - return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var); - - if (auto *Temp = dyn_cast<ClassTemplateDecl>(Other)) - return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp); - - if (auto *Temp = dyn_cast<FunctionTemplateDecl>(Other)) - return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp); - - if (auto *PartialSpec = - dyn_cast<ClassTemplatePartialSpecializationDecl>(Other)) - return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D), - PartialSpec); - - if (auto *Field = dyn_cast<FieldDecl>(Other)) { - if (!Field->getDeclName()) { - // This is an unnamed field. - return declaresSameEntity(Ctx.getInstantiatedFromUnnamedFieldDecl(Field), - cast<FieldDecl>(D)); - } - } - - if (auto *Using = dyn_cast<UsingDecl>(Other)) - return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx); - - if (auto *Shadow = dyn_cast<UsingShadowDecl>(Other)) - return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx); - - return D->getDeclName() && - D->getDeclName() == cast<NamedDecl>(Other)->getDeclName(); -} - -template<typename ForwardIterator> -static NamedDecl *findInstantiationOf(ASTContext &Ctx, - NamedDecl *D, - ForwardIterator first, - ForwardIterator last) { - for (; first != last; ++first) - if (isInstantiationOf(Ctx, D, *first)) - return cast<NamedDecl>(*first); - - return nullptr; -} - -/// Finds the instantiation of the given declaration context -/// within the current instantiation. -/// -/// \returns NULL if there was an error -DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, - const MultiLevelTemplateArgumentList &TemplateArgs) { - if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) { - Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs, true); - return cast_or_null<DeclContext>(ID); - } else return DC; -} - -/// Find the instantiation of the given declaration within the -/// current instantiation. -/// -/// This routine is intended to be used when \p D is a declaration -/// referenced from within a template, that needs to mapped into the -/// corresponding declaration within an instantiation. For example, -/// given: -/// -/// \code -/// template<typename T> -/// struct X { -/// enum Kind { -/// KnownValue = sizeof(T) -/// }; -/// -/// bool getKind() const { return KnownValue; } -/// }; -/// -/// template struct X<int>; -/// \endcode -/// -/// In the instantiation of <tt>X<int>::getKind()</tt>, we need to map the -/// \p EnumConstantDecl for \p KnownValue (which refers to -/// <tt>X<T>::<Kind>::KnownValue</tt>) to its instantiation -/// (<tt>X<int>::<Kind>::KnownValue</tt>). \p FindInstantiatedDecl performs -/// this mapping from within the instantiation of <tt>X<int></tt>. -NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool FindingInstantiatedContext) { - DeclContext *ParentDC = D->getDeclContext(); - // FIXME: Parmeters of pointer to functions (y below) that are themselves - // parameters (p below) can have their ParentDC set to the translation-unit - // - thus we can not consistently check if the ParentDC of such a parameter - // is Dependent or/and a FunctionOrMethod. - // For e.g. this code, during Template argument deduction tries to - // find an instantiated decl for (T y) when the ParentDC for y is - // the translation unit. - // e.g. template <class T> void Foo(auto (*p)(T y) -> decltype(y())) {} - // float baz(float(*)()) { return 0.0; } - // Foo(baz); - // The better fix here is perhaps to ensure that a ParmVarDecl, by the time - // it gets here, always has a FunctionOrMethod as its ParentDC?? - // For now: - // - as long as we have a ParmVarDecl whose parent is non-dependent and - // whose type is not instantiation dependent, do nothing to the decl - // - otherwise find its instantiated decl. - if (isa<ParmVarDecl>(D) && !ParentDC->isDependentContext() && - !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType()) - return D; - if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || - isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || - ((ParentDC->isFunctionOrMethod() || - isa<OMPDeclareReductionDecl>(ParentDC) || - isa<OMPDeclareMapperDecl>(ParentDC)) && - ParentDC->isDependentContext()) || - (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) { - // D is a local of some kind. Look into the map of local - // declarations to their instantiations. - if (CurrentInstantiationScope) { - if (auto Found = CurrentInstantiationScope->findInstantiationOf(D)) { - if (Decl *FD = Found->dyn_cast<Decl *>()) - return cast<NamedDecl>(FD); - - int PackIdx = ArgumentPackSubstitutionIndex; - assert(PackIdx != -1 && - "found declaration pack but not pack expanding"); - typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; - return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]); - } - } - - // If we're performing a partial substitution during template argument - // deduction, we may not have values for template parameters yet. They - // just map to themselves. - if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || - isa<TemplateTemplateParmDecl>(D)) - return D; - - if (D->isInvalidDecl()) - return nullptr; - - // Normally this function only searches for already instantiated declaration - // however we have to make an exclusion for local types used before - // definition as in the code: - // - // template<typename T> void f1() { - // void g1(struct x1); - // struct x1 {}; - // } - // - // In this case instantiation of the type of 'g1' requires definition of - // 'x1', which is defined later. Error recovery may produce an enum used - // before definition. In these cases we need to instantiate relevant - // declarations here. - bool NeedInstantiate = false; - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) - NeedInstantiate = RD->isLocalClass(); - else - NeedInstantiate = isa<EnumDecl>(D); - if (NeedInstantiate) { - Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); - CurrentInstantiationScope->InstantiatedLocal(D, Inst); - return cast<TypeDecl>(Inst); - } - - // If we didn't find the decl, then we must have a label decl that hasn't - // been found yet. Lazily instantiate it and return it now. - assert(isa<LabelDecl>(D)); - - Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); - assert(Inst && "Failed to instantiate label??"); - - CurrentInstantiationScope->InstantiatedLocal(D, Inst); - return cast<LabelDecl>(Inst); - } - - // For variable template specializations, update those that are still - // type-dependent. - if (VarTemplateSpecializationDecl *VarSpec = - dyn_cast<VarTemplateSpecializationDecl>(D)) { - bool InstantiationDependent = false; - const TemplateArgumentListInfo &VarTemplateArgs = - VarSpec->getTemplateArgsInfo(); - if (TemplateSpecializationType::anyDependentTemplateArguments( - VarTemplateArgs, InstantiationDependent)) - D = cast<NamedDecl>( - SubstDecl(D, VarSpec->getDeclContext(), TemplateArgs)); - return D; - } - - if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { - if (!Record->isDependentContext()) - return D; - - // Determine whether this record is the "templated" declaration describing - // a class template or class template partial specialization. - ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); - if (ClassTemplate) - ClassTemplate = ClassTemplate->getCanonicalDecl(); - else if (ClassTemplatePartialSpecializationDecl *PartialSpec - = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) - ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl(); - - // Walk the current context to find either the record or an instantiation of - // it. - DeclContext *DC = CurContext; - while (!DC->isFileContext()) { - // If we're performing substitution while we're inside the template - // definition, we'll find our own context. We're done. - if (DC->Equals(Record)) - return Record; - - if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) { - // Check whether we're in the process of instantiating a class template - // specialization of the template we're mapping. - if (ClassTemplateSpecializationDecl *InstSpec - = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){ - ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate(); - if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate)) - return InstRecord; - } - - // Check whether we're in the process of instantiating a member class. - if (isInstantiationOf(Record, InstRecord)) - return InstRecord; - } - - // Move to the outer template scope. - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) { - if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ - DC = FD->getLexicalDeclContext(); - continue; - } - // An implicit deduction guide acts as if it's within the class template - // specialization described by its name and first N template params. - auto *Guide = dyn_cast<CXXDeductionGuideDecl>(FD); - if (Guide && Guide->isImplicit()) { - TemplateDecl *TD = Guide->getDeducedTemplate(); - // Convert the arguments to an "as-written" list. - TemplateArgumentListInfo Args(Loc, Loc); - for (TemplateArgument Arg : TemplateArgs.getInnermost().take_front( - TD->getTemplateParameters()->size())) { - ArrayRef<TemplateArgument> Unpacked(Arg); - if (Arg.getKind() == TemplateArgument::Pack) - Unpacked = Arg.pack_elements(); - for (TemplateArgument UnpackedArg : Unpacked) - Args.addArgument( - getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc)); - } - QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args); - if (T.isNull()) - return nullptr; - auto *SubstRecord = T->getAsCXXRecordDecl(); - assert(SubstRecord && "class template id not a class type?"); - // Check that this template-id names the primary template and not a - // partial or explicit specialization. (In the latter cases, it's - // meaningless to attempt to find an instantiation of D within the - // specialization.) - // FIXME: The standard doesn't say what should happen here. - if (FindingInstantiatedContext && - usesPartialOrExplicitSpecialization( - Loc, cast<ClassTemplateSpecializationDecl>(SubstRecord))) { - Diag(Loc, diag::err_specialization_not_primary_template) - << T << (SubstRecord->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization); - return nullptr; - } - DC = SubstRecord; - continue; - } - } - - DC = DC->getParent(); - } - - // Fall through to deal with other dependent record types (e.g., - // anonymous unions in class templates). - } - - if (!ParentDC->isDependentContext()) - return D; - - ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs); - if (!ParentDC) - return nullptr; - - if (ParentDC != D->getDeclContext()) { - // We performed some kind of instantiation in the parent context, - // so now we need to look into the instantiated parent context to - // find the instantiation of the declaration D. - - // If our context used to be dependent, we may need to instantiate - // it before performing lookup into that context. - bool IsBeingInstantiated = false; - if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) { - if (!Spec->isDependentContext()) { - QualType T = Context.getTypeDeclType(Spec); - const RecordType *Tag = T->getAs<RecordType>(); - assert(Tag && "type of non-dependent record is not a RecordType"); - if (Tag->isBeingDefined()) - IsBeingInstantiated = true; - if (!Tag->isBeingDefined() && - RequireCompleteType(Loc, T, diag::err_incomplete_type)) - return nullptr; - - ParentDC = Tag->getDecl(); - } - } - - NamedDecl *Result = nullptr; - // FIXME: If the name is a dependent name, this lookup won't necessarily - // find it. Does that ever matter? - if (auto Name = D->getDeclName()) { - DeclarationNameInfo NameInfo(Name, D->getLocation()); - Name = SubstDeclarationNameInfo(NameInfo, TemplateArgs).getName(); - if (!Name) - return nullptr; - DeclContext::lookup_result Found = ParentDC->lookup(Name); - Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); - } else { - // Since we don't have a name for the entity we're looking for, - // our only option is to walk through all of the declarations to - // find that name. This will occur in a few cases: - // - // - anonymous struct/union within a template - // - unnamed class/struct/union/enum within a template - // - // FIXME: Find a better way to find these instantiations! - Result = findInstantiationOf(Context, D, - ParentDC->decls_begin(), - ParentDC->decls_end()); - } - - if (!Result) { - if (isa<UsingShadowDecl>(D)) { - // UsingShadowDecls can instantiate to nothing because of using hiding. - } else if (Diags.hasErrorOccurred()) { - // We've already complained about something, so most likely this - // declaration failed to instantiate. There's no point in complaining - // further, since this is normal in invalid code. - } else if (IsBeingInstantiated) { - // The class in which this member exists is currently being - // instantiated, and we haven't gotten around to instantiating this - // member yet. This can happen when the code uses forward declarations - // of member classes, and introduces ordering dependencies via - // template instantiation. - Diag(Loc, diag::err_member_not_yet_instantiated) - << D->getDeclName() - << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC)); - Diag(D->getLocation(), diag::note_non_instantiated_member_here); - } else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) { - // This enumeration constant was found when the template was defined, - // but can't be found in the instantiation. This can happen if an - // unscoped enumeration member is explicitly specialized. - EnumDecl *Enum = cast<EnumDecl>(ED->getLexicalDeclContext()); - EnumDecl *Spec = cast<EnumDecl>(FindInstantiatedDecl(Loc, Enum, - TemplateArgs)); - assert(Spec->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization); - Diag(Loc, diag::err_enumerator_does_not_exist) - << D->getDeclName() - << Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext())); - Diag(Spec->getLocation(), diag::note_enum_specialized_here) - << Context.getTypeDeclType(Spec); - } else { - // We should have found something, but didn't. - llvm_unreachable("Unable to find instantiation of declaration!"); - } - } - - D = Result; - } - - return D; -} - -/// Performs template instantiation for all implicit template -/// instantiations we have seen until this point. -void Sema::PerformPendingInstantiations(bool LocalOnly) { - while (!PendingLocalImplicitInstantiations.empty() || - (!LocalOnly && !PendingInstantiations.empty())) { - PendingImplicitInstantiation Inst; - - if (PendingLocalImplicitInstantiations.empty()) { - Inst = PendingInstantiations.front(); - PendingInstantiations.pop_front(); - } else { - Inst = PendingLocalImplicitInstantiations.front(); - PendingLocalImplicitInstantiations.pop_front(); - } - - // Instantiate function definitions - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) { - bool DefinitionRequired = Function->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition; - if (Function->isMultiVersion()) { - getASTContext().forEachMultiversionedFunctionVersion( - Function, [this, Inst, DefinitionRequired](FunctionDecl *CurFD) { - InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, CurFD, true, - DefinitionRequired, true); - if (CurFD->isDefined()) - CurFD->setInstantiationIsPending(false); - }); - } else { - InstantiateFunctionDefinition(/*FIXME:*/ Inst.second, Function, true, - DefinitionRequired, true); - if (Function->isDefined()) - Function->setInstantiationIsPending(false); - } - continue; - } - - // Instantiate variable definitions - VarDecl *Var = cast<VarDecl>(Inst.first); - - assert((Var->isStaticDataMember() || - isa<VarTemplateSpecializationDecl>(Var)) && - "Not a static data member, nor a variable template" - " specialization?"); - - // Don't try to instantiate declarations if the most recent redeclaration - // is invalid. - if (Var->getMostRecentDecl()->isInvalidDecl()) - continue; - - // Check if the most recent declaration has changed the specialization kind - // and removed the need for implicit instantiation. - switch (Var->getMostRecentDecl() - ->getTemplateSpecializationKindForInstantiation()) { - case TSK_Undeclared: - llvm_unreachable("Cannot instantitiate an undeclared specialization."); - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitSpecialization: - continue; // No longer need to instantiate this type. - case TSK_ExplicitInstantiationDefinition: - // We only need an instantiation if the pending instantiation *is* the - // explicit instantiation. - if (Var != Var->getMostRecentDecl()) - continue; - break; - case TSK_ImplicitInstantiation: - break; - } - - PrettyDeclStackTraceEntry CrashInfo(Context, Var, SourceLocation(), - "instantiating variable definition"); - bool DefinitionRequired = Var->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition; - - // Instantiate static data member definitions or variable template - // specializations. - InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true, - DefinitionRequired, true); - } -} - -void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs) { - for (auto DD : Pattern->ddiags()) { - switch (DD->getKind()) { - case DependentDiagnostic::Access: - HandleDependentAccessCheck(*DD, TemplateArgs); - break; - } - } -} |
