]> granicus.if.org Git - clang/commitdiff
Support a new InheritableAttr subclass, InheritableParamAttr, which is
authorJohn McCall <rjmccall@apple.com>
Wed, 2 Mar 2011 04:00:57 +0000 (04:00 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 2 Mar 2011 04:00:57 +0000 (04:00 +0000)
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

include/clang/AST/Attr.h
include/clang/Basic/Attr.td
include/clang/Basic/AttrKinds.h
include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclObjC.cpp

index 67968fde2d6bdc7d94134907eb5a10de4f977654..502b9f775fc94a23010dde457aea2f7e5b3c07f5 100644 (file)
@@ -120,6 +120,19 @@ public:
   static bool classof(const InheritableAttr *) { return true; }
 };
 
+class InheritableParamAttr : public InheritableAttr {
+protected:
+  InheritableParamAttr(attr::Kind AK, SourceLocation L)
+    : InheritableAttr(AK, L) {}
+
+public:
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Attr *A) {
+    return A->getKind() <= attr::LAST_INHERITABLE_PARAM;
+  }
+  static bool classof(const InheritableParamAttr *) { return true; }
+};
+
 #include "clang/AST/Attrs.inc"
 
 /// AttrVec - A vector of Attr, which is how they are stored on the AST.
index 3e62d411d51a348797b97c7ab8dddad5aaca8a8f..57e5be4ae8ead07ec7c2fc609f9b087252b0ad1b 100644 (file)
@@ -89,8 +89,13 @@ class Attr {
   code AdditionalMembers = [{}];
 }
 
+/// An inheritable attribute is inherited by later redeclarations.
 class InheritableAttr : Attr;
 
+/// An inheritable parameter attribute is inherited by later
+/// redeclarations, even when it's written on a parameter.
+class InheritableParamAttr : InheritableAttr;
+
 //
 // Attributes begin here
 //
@@ -134,7 +139,7 @@ def Blocks : InheritableAttr {
   let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
 }
 
-def CarriesDependency : InheritableAttr {
+def CarriesDependency : InheritableParamAttr {
   let Spellings = ["carries_dependency"];
   let Subjects = [ParmVar, Function];
   let Namespaces = ["", "std"];
@@ -154,7 +159,7 @@ def CFReturnsNotRetained : InheritableAttr {
   let Subjects = [ObjCMethod, Function];
 }
 
-def CFConsumed : InheritableAttr {
+def CFConsumed : InheritableParamAttr {
   let Spellings = ["cf_consumed"];
   let Subjects = [ParmVar];
 }
@@ -355,7 +360,7 @@ def NSConsumesSelf : InheritableAttr {
   let Subjects = [ObjCMethod];
 }
 
-def NSConsumed : InheritableAttr {
+def NSConsumed : InheritableParamAttr {
   let Spellings = ["ns_consumed"];
   let Subjects = [ParmVar];
 }
index 65c4f98c952c50b523014793110e6400fe0890a6..9d5ae588c50f151705b8547e5d0055cac5a519eb 100644 (file)
@@ -22,6 +22,7 @@ namespace attr {
 enum Kind {
 #define ATTR(X) X,
 #define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X,
+#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X,
 #include "clang/Basic/AttrList.inc"
   NUM_ATTRS
 };
index 5ad041f67eb857b0f2df807d5b7528af6a07f566..fcc29442a5ce2b8be54508b0210cd5e514e225b0 100644 (file)
@@ -1068,6 +1068,7 @@ public:
   void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
   bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
   bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
+  void mergeObjCMethodDecls(ObjCMethodDecl *New, const ObjCMethodDecl *Old);
   void MergeVarDeclTypes(VarDecl *New, VarDecl *Old);
   void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
   bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
index 9d90499759973e5975b7c45b0ad12453b7c678ff..70c405c1323730df53fdb451456ea8bff2c5ccfd 100644 (file)
@@ -1054,23 +1054,58 @@ DeclHasAttr(const Decl *D, const Attr *A) {
   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 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
 /// \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 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) {
   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 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
     New->setInvalidDecl();
   }
   
-  MergeDeclAttributes(New, Old, Context);
+  mergeDeclAttributes(New, Old, Context);
 
   // Merge the types.
   MergeVarDeclTypes(New, Old);
index 652318f7204ee621f5bb98ad669a0b1b00392921..24ca4e6164d9dba674bb7132bcbca78228b90174 100644 (file)
@@ -1888,16 +1888,9 @@ Decl *Sema::ActOnMethodDeclaration(
     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;
 }