Support a new InheritableAttr subclass, InheritableParamAttr, which is
used for attributes that are okay to inherit when written on a parameter.
Dependent on LLVM r126827.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126828 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9d90499..70c405c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1054,23 +1054,58 @@
return false;
}
-/// MergeDeclAttributes - append attributes from the Old decl to the New one.
-static void MergeDeclAttributes(Decl *New, Decl *Old, ASTContext &C) {
- if (!Old->hasAttrs())
+/// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
+static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl,
+ ASTContext &C) {
+ if (!oldDecl->hasAttrs())
return;
+
+ bool foundAny = newDecl->hasAttrs();
+
// Ensure that any moving of objects within the allocated map is done before
// we process them.
- if (!New->hasAttrs())
- New->setAttrs(AttrVec());
+ if (!foundAny) newDecl->setAttrs(AttrVec());
+
for (specific_attr_iterator<InheritableAttr>
- i = Old->specific_attr_begin<InheritableAttr>(),
- e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) {
- if (!DeclHasAttr(New, *i)) {
- InheritableAttr *NewAttr = cast<InheritableAttr>((*i)->clone(C));
- NewAttr->setInherited(true);
- New->addAttr(NewAttr);
+ i = oldDecl->specific_attr_begin<InheritableAttr>(),
+ e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) {
+ if (!DeclHasAttr(newDecl, *i)) {
+ InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C));
+ newAttr->setInherited(true);
+ newDecl->addAttr(newAttr);
+ foundAny = true;
}
}
+
+ if (!foundAny) newDecl->dropAttrs();
+}
+
+/// mergeParamDeclAttributes - Copy attributes from the old parameter
+/// to the new one.
+static void mergeParamDeclAttributes(ParmVarDecl *newDecl,
+ const ParmVarDecl *oldDecl,
+ ASTContext &C) {
+ if (!oldDecl->hasAttrs())
+ return;
+
+ bool foundAny = newDecl->hasAttrs();
+
+ // Ensure that any moving of objects within the allocated map is
+ // done before we process them.
+ if (!foundAny) newDecl->setAttrs(AttrVec());
+
+ for (specific_attr_iterator<InheritableParamAttr>
+ i = oldDecl->specific_attr_begin<InheritableParamAttr>(),
+ e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) {
+ if (!DeclHasAttr(newDecl, *i)) {
+ InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C));
+ newAttr->setInherited(true);
+ newDecl->addAttr(newAttr);
+ foundAny = true;
+ }
+ }
+
+ if (!foundAny) newDecl->dropAttrs();
}
namespace {
@@ -1471,7 +1506,7 @@
/// \returns false
bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
// Merge the attributes
- MergeDeclAttributes(New, Old, Context);
+ mergeDeclAttributes(New, Old, Context);
// Merge the storage class.
if (Old->getStorageClass() != SC_Extern &&
@@ -1486,12 +1521,31 @@
if (Old->isDeleted())
New->setDeleted();
+ // Merge attributes from the parameters. These can mismatch with K&R
+ // declarations.
+ if (New->getNumParams() == Old->getNumParams())
+ for (unsigned i = 0, e = New->getNumParams(); i != e; ++i)
+ mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i),
+ Context);
+
if (getLangOptions().CPlusPlus)
return MergeCXXFunctionDecl(New, Old);
return false;
}
+void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod,
+ const ObjCMethodDecl *oldMethod) {
+ // Merge the attributes.
+ mergeDeclAttributes(newMethod, oldMethod, Context);
+
+ // Merge attributes from the parameters.
+ for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(),
+ ni = newMethod->param_begin(), ne = newMethod->param_end();
+ ni != ne; ++ni, ++oi)
+ mergeParamDeclAttributes(*ni, *oi, Context);
+}
+
/// MergeVarDecl - We parsed a variable 'New' which has the same name and scope
/// as a previous declaration 'Old'. Figure out how to merge their types,
/// emitting diagnostics as appropriate.
@@ -1585,7 +1639,7 @@
New->setInvalidDecl();
}
- MergeDeclAttributes(New, Old, Context);
+ mergeDeclAttributes(New, Old, Context);
// Merge the types.
MergeVarDeclTypes(New, Old);
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 652318f..24ca4e6 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1888,16 +1888,9 @@
Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
}
- // If the interface declared this method, and it was deprecated there,
- // mark it deprecated here.
+ // Merge information down from the interface declaration if we have one.
if (InterfaceMD)
- if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>()) {
- StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1);
- ObjCMethod->addAttr(::new (Context)
- DeprecatedAttr(DA->getLocation(),
- Context,
- SE->getString()));
- }
+ mergeObjCMethodDecls(ObjCMethod, InterfaceMD);
return ObjCMethod;
}