diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 346 |
1 files changed, 254 insertions, 92 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index dc1e0ef60cac..be4c51930789 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -9,6 +9,7 @@ // //===----------------------------------------------------------------------===/ +#include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" @@ -23,6 +24,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" @@ -474,7 +476,7 @@ static void instantiateOMPDeclareVariantAttr( SourceLocation(), SubstFD, /* RefersToEnclosingVariableOrCapture */ false, /* NameLoc */ SubstFD->getLocation(), - SubstFD->getType(), ExprValueKind::VK_RValue); + SubstFD->getType(), ExprValueKind::VK_PRValue); } } } @@ -548,6 +550,35 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr); } +// This doesn't take any template parameters, but we have a custom action that +// needs to happen when the kernel itself is instantiated. We need to run the +// ItaniumMangler to mark the names required to name this kernel. +static void instantiateDependentSYCLKernelAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const SYCLKernelAttr &Attr, Decl *New) { + // Functions cannot be partially specialized, so if we are being instantiated, + // we are obviously a complete specialization. Since this attribute is only + // valid on function template declarations, we know that this is a full + // instantiation of a kernel. + S.AddSYCLKernelLambda(cast<FunctionDecl>(New)); + + // Evaluate whether this would change any of the already evaluated + // __builtin_sycl_unique_stable_name values. + for (auto &Itr : S.Context.SYCLUniqueStableNameEvaluatedValues) { + const std::string &CurName = Itr.first->ComputeName(S.Context); + if (Itr.second != CurName) { + S.Diag(New->getLocation(), + diag::err_kernel_invalidates_sycl_unique_stable_name); + S.Diag(Itr.first->getLocation(), + diag::note_sycl_unique_stable_name_evaluated_here); + // Update this so future diagnostics work correctly. + Itr.second = CurName; + } + } + + New->addAttr(Attr.clone(S.getASTContext())); +} + /// Determine whether the attribute A might be relevent to the declaration D. /// If not, we can skip instantiating it. The attribute may or may not have /// been instantiated yet. @@ -723,6 +754,11 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } + if (auto *A = dyn_cast<SYCLKernelAttr>(TmplAttr)) { + instantiateDependentSYCLKernelAttr(*this, TemplateArgs, *A, New); + continue; + } + assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the @@ -856,10 +892,11 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, 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. + // HACK: 2012-10-23 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. The bugs + // are fixed in g++ and libstdc++ 4.9.0 (2014-04-22). const DecltypeType *DT = DI->getType()->getAs<DecltypeType>(); CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()); if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) && @@ -1050,11 +1087,30 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, 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); + QualType RT; + if (auto *F = dyn_cast<FunctionDecl>(DC)) + RT = F->getReturnType(); + else if (isa<BlockDecl>(DC)) + RT = cast<FunctionType>(SemaRef.getCurBlock()->FunctionType) + ->getReturnType(); + else + llvm_unreachable("Unknown context type"); + + // This is the last chance we have of checking copy elision eligibility + // for functions in dependent contexts. The sema actions for building + // the return statement during template instantiation will have no effect + // regarding copy elision, since NRVO propagation runs on the scope exit + // actions, and these are not run on instantiation. + // This might run through some VarDecls which were returned from non-taken + // 'if constexpr' branches, and these will end up being constructed on the + // return slot even if they will never be returned, as a sort of accidental + // 'optimization'. Notably, functions with 'auto' return types won't have it + // deduced by this point. Coupled with the limitation described + // previously, this makes it very hard to support copy elision for these. + Sema::NamedReturnInfo Info = SemaRef.getNamedReturnInfo(Var); + bool NRVO = SemaRef.getCopyElisionCandidate(Info, RT) != nullptr; + Var->setNRVOVariable(NRVO); } Var->setImplicit(D->isImplicit()); @@ -1517,48 +1573,18 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { 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; - } + if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, true, + Sema::TPL_TemplateMatch)) + return nullptr; // Do some additional validation, then merge default arguments // from the existing declarations. - if (!AdoptedPreviousTemplateParams && - SemaRef.CheckTemplateParameterList(InstParams, PrevParams, + if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams, Sema::TPC_ClassTemplate)) return nullptr; } @@ -1800,9 +1826,16 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { PrevDecl = cast<CXXRecordDecl>(Prev); } - CXXRecordDecl *Record = CXXRecordDecl::Create( - SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), - D->getLocation(), D->getIdentifier(), PrevDecl); + CXXRecordDecl *Record = nullptr; + if (D->isLambda()) + Record = CXXRecordDecl::CreateLambda( + SemaRef.Context, Owner, D->getLambdaTypeInfo(), D->getLocation(), + D->isDependentLambda(), D->isGenericLambda(), + D->getLambdaCaptureDefault()); + else + 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)) @@ -2281,6 +2314,20 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( if (InstantiatedExplicitSpecifier.isInvalid()) return nullptr; + // Implicit destructors/constructors created for local classes in + // DeclareImplicit* (see SemaDeclCXX.cpp) might not have an associated TSI. + // Unfortunately there isn't enough context in those functions to + // conditionally populate the TSI without breaking non-template related use + // cases. Populate TSIs prior to calling SubstFunctionType to make sure we get + // a proper transformation. + if (cast<CXXRecordDecl>(D->getParent())->isLambda() && + !D->getTypeSourceInfo() && + isa<CXXConstructorDecl, CXXDestructorDecl>(D)) { + TypeSourceInfo *TSI = + SemaRef.Context.getTrivialTypeSourceInfo(D->getType()); + D->setTypeSourceInfo(TSI); + } + SmallVector<ParmVarDecl *, 4> Params; TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) @@ -2370,6 +2417,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( Destructor->isInlineSpecified(), false, Destructor->getConstexprKind(), TrailingRequiresClause); Method->setRangeEnd(Destructor->getEndLoc()); + Method->setDeclName(SemaRef.Context.DeclarationNames.getCXXDestructorName( + SemaRef.Context.getCanonicalType( + SemaRef.Context.getTypeDeclType(Record)))); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, @@ -2610,7 +2660,6 @@ Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *D) { - // TODO: don't always clone when decls are refcounted. assert(D->getTypeForDecl()->isTemplateTypeParmType()); Optional<unsigned> NumExpanded; @@ -3009,6 +3058,53 @@ Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { return Inst; } +Decl *TemplateDeclInstantiator::VisitBaseUsingDecls(BaseUsingDecl *D, + BaseUsingDecl *Inst, + LookupResult *Lookup) { + + bool isFunctionScope = Owner->isFunctionOrMethod(); + + for (auto *Shadow : D->shadows()) { + // FIXME: UsingShadowDecl doesn't preserve its immediate target, so + // reconstruct it in the case where it matters. Hm, can we extract it from + // the DeclSpec when parsing and save it in the UsingDecl itself? + NamedDecl *OldTarget = Shadow->getTargetDecl(); + if (auto *CUSD = dyn_cast<ConstructorUsingShadowDecl>(Shadow)) + if (auto *BaseShadow = CUSD->getNominatedBaseClassShadowDecl()) + OldTarget = BaseShadow; + + NamedDecl *InstTarget = nullptr; + if (auto *EmptyD = + dyn_cast<UnresolvedUsingIfExistsDecl>(Shadow->getTargetDecl())) { + InstTarget = UnresolvedUsingIfExistsDecl::Create( + SemaRef.Context, Owner, EmptyD->getLocation(), EmptyD->getDeclName()); + } else { + InstTarget = cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), OldTarget, TemplateArgs)); + } + if (!InstTarget) + return nullptr; + + UsingShadowDecl *PrevDecl = nullptr; + if (Lookup && + SemaRef.CheckUsingShadowDecl(Inst, InstTarget, *Lookup, PrevDecl)) + continue; + + if (UsingShadowDecl *OldPrev = getPreviousDeclForInstantiation(Shadow)) + PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), OldPrev, TemplateArgs)); + + UsingShadowDecl *InstShadow = SemaRef.BuildUsingShadowDecl( + /*Scope*/ nullptr, Inst, InstTarget, PrevDecl); + SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); + + if (isFunctionScope) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); + } + + return Inst; +} + Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { // The nested name specifier may be dependent, for example @@ -3034,11 +3130,9 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { 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). + // 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); @@ -3059,12 +3153,11 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { D->hasTypename(), SS, D->getLocation(), Prev)) NewUD->setInvalidDecl(); - } if (!NewUD->isInvalidDecl() && - SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), - SS, NameInfo, D->getLocation())) + SemaRef.CheckUsingDeclQualifier(D->getUsingLoc(), D->hasTypename(), SS, + NameInfo, D->getLocation(), nullptr, D)) NewUD->setInvalidDecl(); SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D); @@ -3075,46 +3168,39 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { if (NewUD->isInvalidDecl()) return NewUD; + // If the using scope was dependent, or we had dependent bases, we need to + // recheck the inheritance if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) SemaRef.CheckInheritingConstructorUsingDecl(NewUD); - bool isFunctionScope = Owner->isFunctionOrMethod(); + return VisitBaseUsingDecls(D, NewUD, CheckRedeclaration ? &Prev : nullptr); +} - // 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; +Decl *TemplateDeclInstantiator::VisitUsingEnumDecl(UsingEnumDecl *D) { + // Cannot be a dependent type, but still could be an instantiation + EnumDecl *EnumD = cast_or_null<EnumDecl>(SemaRef.FindInstantiatedDecl( + D->getLocation(), D->getEnumDecl(), TemplateArgs)); - NamedDecl *InstTarget = - cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), OldTarget, TemplateArgs)); - if (!InstTarget) - return nullptr; + if (SemaRef.RequireCompleteEnumDecl(EnumD, EnumD->getLocation())) + 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)); - } + UsingEnumDecl *NewUD = + UsingEnumDecl::Create(SemaRef.Context, Owner, D->getUsingLoc(), + D->getEnumLoc(), D->getLocation(), EnumD); - UsingShadowDecl *InstShadow = - SemaRef.BuildUsingShadowDecl(/*Scope*/nullptr, NewUD, InstTarget, - PrevDecl); - SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); + SemaRef.Context.setInstantiatedFromUsingEnumDecl(NewUD, D); + NewUD->setAccess(D->getAccess()); + Owner->addDecl(NewUD); - if (isFunctionScope) - SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); - } + // Don't process the shadow decls for an invalid decl. + if (NewUD->isInvalidDecl()) + return NewUD; - return NewUD; + // We don't have to recheck for duplication of the UsingEnumDecl itself, as it + // cannot be dependent, and will therefore have been checked during template + // definition. + + return VisitBaseUsingDecls(D, NewUD, nullptr); } Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { @@ -3214,13 +3300,16 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( SourceLocation EllipsisLoc = InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc(); + bool IsUsingIfExists = D->template hasAttr<UsingIfExistsAttr>(); NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, ParsedAttributesView(), - /*IsInstantiation*/ true); - if (UD) + /*IsInstantiation*/ true, IsUsingIfExists); + if (UD) { + SemaRef.InstantiateAttrs(TemplateArgs, D, UD); SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); + } return UD; } @@ -3235,6 +3324,11 @@ Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl( return instantiateUnresolvedUsingDecl(D); } +Decl *TemplateDeclInstantiator::VisitUnresolvedUsingIfExistsDecl( + UnresolvedUsingIfExistsDecl *D) { + llvm_unreachable("referring to unresolved decl out of UsingShadowDecl"); +} + Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { SmallVector<NamedDecl*, 8> Expansions; for (auto *UD : D->expansions()) { @@ -4841,16 +4935,85 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // 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). + // scope (of the enclosing function). The exception is instantiating + // a function template specialization, since the template to be + // instantiated already has references to locals properly substituted. bool MergeWithParentScope = false; if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext())) - MergeWithParentScope = Rec->isLocalClass(); + MergeWithParentScope = + Rec->isLocalClass() && !Function->isFunctionTemplateSpecialization(); LocalInstantiationScope Scope(*this, MergeWithParentScope); + auto RebuildTypeSourceInfoForDefaultSpecialMembers = [&]() { + // Special members might get their TypeSourceInfo set up w.r.t the + // PatternDecl context, in which case parameters could still be pointing + // back to the original class, make sure arguments are bound to the + // instantiated record instead. + assert(PatternDecl->isDefaulted() && + "Special member needs to be defaulted"); + auto PatternSM = getDefaultedFunctionKind(PatternDecl).asSpecialMember(); + if (!(PatternSM == Sema::CXXCopyConstructor || + PatternSM == Sema::CXXCopyAssignment || + PatternSM == Sema::CXXMoveConstructor || + PatternSM == Sema::CXXMoveAssignment)) + return; + + auto *NewRec = dyn_cast<CXXRecordDecl>(Function->getDeclContext()); + const auto *PatternRec = + dyn_cast<CXXRecordDecl>(PatternDecl->getDeclContext()); + if (!NewRec || !PatternRec) + return; + if (!PatternRec->isLambda()) + return; + + struct SpecialMemberTypeInfoRebuilder + : TreeTransform<SpecialMemberTypeInfoRebuilder> { + using Base = TreeTransform<SpecialMemberTypeInfoRebuilder>; + const CXXRecordDecl *OldDecl; + CXXRecordDecl *NewDecl; - if (PatternDecl->isDefaulted()) + SpecialMemberTypeInfoRebuilder(Sema &SemaRef, const CXXRecordDecl *O, + CXXRecordDecl *N) + : TreeTransform(SemaRef), OldDecl(O), NewDecl(N) {} + + bool TransformExceptionSpec(SourceLocation Loc, + FunctionProtoType::ExceptionSpecInfo &ESI, + SmallVectorImpl<QualType> &Exceptions, + bool &Changed) { + return false; + } + + QualType TransformRecordType(TypeLocBuilder &TLB, RecordTypeLoc TL) { + const RecordType *T = TL.getTypePtr(); + RecordDecl *Record = cast_or_null<RecordDecl>( + getDerived().TransformDecl(TL.getNameLoc(), T->getDecl())); + if (Record != OldDecl) + return Base::TransformRecordType(TLB, TL); + + QualType Result = getDerived().RebuildRecordType(NewDecl); + if (Result.isNull()) + return QualType(); + + RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } + } IR{*this, PatternRec, NewRec}; + + TypeSourceInfo *NewSI = IR.TransformType(Function->getTypeSourceInfo()); + Function->setType(NewSI->getType()); + Function->setTypeSourceInfo(NewSI); + + ParmVarDecl *Parm = Function->getParamDecl(0); + TypeSourceInfo *NewParmSI = IR.TransformType(Parm->getTypeSourceInfo()); + Parm->setType(NewParmSI->getType()); + Parm->setTypeSourceInfo(NewParmSI); + }; + + if (PatternDecl->isDefaulted()) { + RebuildTypeSourceInfoForDefaultSpecialMembers(); SetDeclDefaulted(Function, PatternDecl->getLocation()); - else { + } else { MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl); @@ -5030,7 +5193,6 @@ void Sema::BuildVariableInstantiation( NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); NewVar->setObjCForDecl(OldVar->isObjCForDecl()); NewVar->setConstexpr(OldVar->isConstexpr()); - MaybeAddCUDAConstantAttr(NewVar); NewVar->setInitCapture(OldVar->isInitCapture()); NewVar->setPreviousDeclInSameBlockScope( OldVar->isPreviousDeclInSameBlockScope()); |