@@ -3227,10 +3227,44 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
32273227 if (!foundAny) New->dropAttrs();
32283228}
32293229
3230+ template <class T>
3231+ static unsigned propagateAttribute(ParmVarDecl *toDecl,
3232+ const ParmVarDecl *fromDecl, Sema &S) {
3233+ unsigned found = 0;
3234+ for (const auto *I : fromDecl->specific_attrs<T>()) {
3235+ if (!DeclHasAttr(toDecl, I)) {
3236+ T *newAttr = cast<T>(I->clone(S.Context));
3237+ newAttr->setInherited(true);
3238+ toDecl->addAttr(newAttr);
3239+ ++found;
3240+ }
3241+ }
3242+ return found;
3243+ }
3244+
3245+ template <class F>
3246+ static void propagateAttributes(ParmVarDecl *toDecl,
3247+ const ParmVarDecl *fromDecl, F &&propagator) {
3248+ if (!fromDecl->hasAttrs()) {
3249+ return;
3250+ }
3251+
3252+ bool foundAny = toDecl->hasAttrs();
3253+
3254+ // Ensure that any moving of objects within the allocated map is
3255+ // done before we process them.
3256+ if (!foundAny)
3257+ toDecl->setAttrs(AttrVec());
3258+
3259+ foundAny |= std::forward<F>(propagator)(toDecl, fromDecl) != 0;
3260+
3261+ if (!foundAny)
3262+ toDecl->dropAttrs();
3263+ }
3264+
32303265/// mergeParamDeclAttributes - Copy attributes from the old parameter
32313266/// to the new one.
3232- static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
3233- const ParmVarDecl *oldDecl,
3267+ static void mergeParamDeclAttributes(ParmVarDecl *newDecl, ParmVarDecl *oldDecl,
32343268 Sema &S) {
32353269 // C++11 [dcl.attr.depend]p2:
32363270 // The first declaration of a function shall specify the
@@ -3250,26 +3284,25 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
32503284 diag::note_carries_dependency_missing_first_decl) << 1/*Param*/;
32513285 }
32523286
3253- if (!oldDecl->hasAttrs())
3254- return;
3255-
3256- bool foundAny = newDecl->hasAttrs();
3257-
3258- // Ensure that any moving of objects within the allocated map is
3259- // done before we process them.
3260- if (!foundAny) newDecl->setAttrs(AttrVec());
3261-
3262- for (const auto *I : oldDecl->specific_attrs<InheritableParamAttr>()) {
3263- if (!DeclHasAttr(newDecl, I)) {
3264- InheritableAttr *newAttr =
3265- cast<InheritableParamAttr>(I->clone(S.Context));
3266- newAttr->setInherited(true);
3267- newDecl->addAttr(newAttr);
3268- foundAny = true;
3269- }
3270- }
3287+ // Forward propagation (from old parameter to new)
3288+ propagateAttributes(
3289+ newDecl, oldDecl, [&S](ParmVarDecl *toDecl, const ParmVarDecl *fromDecl) {
3290+ unsigned found = 0;
3291+ found += propagateAttribute<InheritableParamAttr>(toDecl, fromDecl, S);
3292+ return found;
3293+ });
32713294
3272- if (!foundAny) newDecl->dropAttrs();
3295+ // Backward propagation (from new parameter to old)
3296+ propagateAttributes(
3297+ oldDecl, newDecl, [&S](ParmVarDecl *toDecl, const ParmVarDecl *fromDecl) {
3298+ unsigned found = 0;
3299+ // Propagate the lifetimebound attribute from parameters to the
3300+ // canonical declaration. Note that this doesn't include the implicit
3301+ // 'this' parameter, as the attribute is applied to the function type in
3302+ // that case.
3303+ found += propagateAttribute<LifetimeBoundAttr>(toDecl, fromDecl, S);
3304+ return found;
3305+ });
32733306}
32743307
32753308static bool EquivalentArrayTypes(QualType Old, QualType New,
@@ -4323,8 +4356,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
43234356 mergeDeclAttributes(newMethod, oldMethod, MergeKind);
43244357
43254358 // Merge attributes from the parameters.
4326- ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(),
4327- oe = oldMethod->param_end();
4359+ ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(),
4360+ oe = oldMethod->param_end();
43284361 for (ObjCMethodDecl::param_iterator
43294362 ni = newMethod->param_begin(), ne = newMethod->param_end();
43304363 ni != ne && oi != oe; ++ni, ++oi)
0 commit comments