[cfe-commits] r55561 - in /cfe/trunk/lib: AST/StmtDumper.cpp CodeGen/CGExpr.cpp CodeGen/CGExprAgg.cpp CodeGen/CGExprComplex.cpp CodeGen/CGObjC.cpp CodeGen/CGObjCGNU.cpp CodeGen/CGObjCMac.cpp CodeGen/CGObjCRuntime.h CodeGen/CodeGenFunction.h Sema/SemaExpr.cpp

Daniel Dunbar daniel at zuster.org
Fri Aug 29 22:35:16 PDT 2008


Author: ddunbar
Date: Sat Aug 30 00:35:15 2008
New Revision: 55561

URL: http://llvm.org/viewvc/llvm-project?rev=55561&view=rev
Log:
Add Objective-C property setter support.
 - Change Obj-C runtime message API, drop the ObjCMessageExpr arg in
   favor of just result type and selector. Necessary so it can be
   reused in situations where we don't want to cons up an
   ObjCMessageExpr.
 - Update aggregate binary assignment to know about special property
   ref lvalues.
 - Add CodeGenFunction::EmitCallArg overload which takes an already
   emitted rvalue.

Add CodeGenFunction::StoreComplexIntoAddr.

Disabled logic in Sema for parsing Objective-C dot-syntax that
accesses methods. This code does not search in the correct order and
the AST node has no way of properly representing its results.

Updated StmtDumper to print a bit more information about
ObjCPropertyRefExprs.

Modified:
    cfe/trunk/lib/AST/StmtDumper.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprComplex.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CGObjCMac.cpp
    cfe/trunk/lib/CodeGen/CGObjCRuntime.h
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/lib/AST/StmtDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtDumper.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtDumper.cpp (original)
+++ cfe/trunk/lib/AST/StmtDumper.cpp Sat Aug 30 00:35:15 2008
@@ -136,6 +136,7 @@
     void VisitObjCMessageExpr(ObjCMessageExpr* Node);
     void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
     void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
     void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
   };
 }
@@ -449,6 +450,18 @@
   fprintf(F, " ");
   fprintf(F, "%s", Node->getProtocol()->getName());
 }
+
+void StmtDumper::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+  DumpExpr(Node);
+  
+  if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Node->getDecl())) {
+    fprintf(F, " MethodDecl=\"%s\"", MD->getSelector().getName().c_str());
+  } else {
+    ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(Node->getDecl());
+    fprintf(F, " PropertyDecl=\"%s\"", PD->getName());
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Stmt method implementations
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sat Aug 30 00:35:15 2008
@@ -830,6 +830,24 @@
   return EmitCall(Callee, ResultType, Args);
 }
 
+// FIXME: Merge the following two functions.
+void CodeGenFunction::EmitCallArg(RValue RV, QualType Ty,
+                                  CallArgList &Args) {
+  llvm::Value *ArgValue;
+
+  if (RV.isScalar()) {
+    ArgValue = RV.getScalarVal();
+  } else if (RV.isComplex()) {
+    // Make a temporary alloca to pass the argument.
+    ArgValue = CreateTempAlloca(ConvertType(Ty));
+    StoreComplexToAddr(RV.getComplexVal(), ArgValue, false); 
+  } else {
+    ArgValue = RV.getAggregateAddr();
+  }
+
+  Args.push_back(std::make_pair(ArgValue, Ty));
+}
+
 void CodeGenFunction::EmitCallArg(const Expr *E, CallArgList &Args) {
   QualType ArgTy = E->getType();
   llvm::Value *ArgValue;

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sat Aug 30 00:35:15 2008
@@ -264,14 +264,26 @@
          && "Invalid assignment");
   LValue LHS = CGF.EmitLValue(E->getLHS());
 
-  // Codegen the RHS so that it stores directly into the LHS.
-  CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
-
-  if (DestPtr == 0)
-    return;
-
-  // If the result of the assignment is used, copy the RHS there also.
-  EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType());
+  // We have to special case property setters, otherwise we must have
+  // a simple lvalue (no aggregates inside vectors, bitfields).
+  if (LHS.isPropertyRef()) {
+    // FIXME: Volatility?
+    llvm::Value *AggLoc = DestPtr;
+    if (!AggLoc)
+      AggLoc = CGF.CreateTempAlloca(CGF.ConvertType(E->getRHS()->getType()));
+    CGF.EmitAggExpr(E->getRHS(), AggLoc, false);
+    CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), 
+                            RValue::getAggregate(AggLoc));
+  } else {
+    // Codegen the RHS so that it stores directly into the LHS.
+    CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), false /*FIXME: VOLATILE LHS*/);
+    
+    if (DestPtr == 0)
+      return;
+    
+    // If the result of the assignment is used, copy the RHS there also.
+    EmitAggregateCopy(DestPtr, LHS.getAddress(), E->getType());
+  }
 }
 
 void AggExprEmitter::VisitConditionalOperator(const ConditionalOperator *E) {

Modified: cfe/trunk/lib/CodeGen/CGExprComplex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprComplex.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprComplex.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprComplex.cpp Sat Aug 30 00:35:15 2008
@@ -546,6 +546,13 @@
   Emitter.EmitStoreOfComplex(Val, DestAddr, DestIsVolatile);
 }
 
+/// StoreComplexToAddr - Store a complex number into the specified address.
+void CodeGenFunction::StoreComplexToAddr(ComplexPairTy V,
+                                         llvm::Value *DestAddr,
+                                         bool DestIsVolatile) {
+  ComplexExprEmitter(*this).EmitStoreOfComplex(V, DestAddr, DestIsVolatile);
+}
+
 /// LoadComplexFromAddr - Load a complex number from the specified address.
 ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr, 
                                                    bool SrcIsVolatile) {

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sat Aug 30 00:35:15 2008
@@ -86,13 +86,15 @@
   if (isSuperMessage) {
     // super is only valid in an Objective-C method
     const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
-    return Runtime.GenerateMessageSendSuper(*this, E,
+    return Runtime.GenerateMessageSendSuper(*this, E->getType(),
+                                            E->getSelector(),
                                             OMD->getClassInterface(),
                                             Receiver,
                                             isClassMessage,
                                             Args);
   }
-  return Runtime.GenerateMessageSend(*this, E, Receiver, isClassMessage, Args);
+  return Runtime.GenerateMessageSend(*this, E->getType(), E->getSelector(), 
+                                     Receiver, isClassMessage, Args);
 }
 
 /// StartObjCMethod - Begin emission of an ObjCMethod. This generates
@@ -234,20 +236,28 @@
     S = cast<ObjCPropertyDecl>(E->getDecl())->getGetterName();
   }
 
-  // FIXME: Improve location information.
-  SourceLocation Loc = E->getLocation();
-  // PropertyRefExprs are always instance messages.
-  // FIXME: Is there any reason to try and pass the method here?
-  ObjCMessageExpr GetExpr(const_cast<Expr*>(E->getBase()), 
-                          S, E->getType(), 0, Loc, Loc,
-                          0, 0);
-
-  return EmitObjCMessageExpr(&GetExpr);
+  return CGM.getObjCRuntime().
+    GenerateMessageSend(*this, E->getType(), S, 
+                        EmitScalarExpr(E->getBase()), 
+                        false, CallArgList());
 }
 
 void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
                                           RValue Src) {
-  ErrorUnsupported(E, "Objective-C property setter call");
+  Selector S;
+  if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(E->getDecl())) {
+    S = PD->getSetterName();
+  } else {
+    // FIXME: How can we have a method decl here?
+    ErrorUnsupported(E, "Objective-C property setter call");
+    return;
+  }
+
+  CallArgList Args;
+  EmitCallArg(Src, E->getType(), Args);
+  CGM.getObjCRuntime().GenerateMessageSend(*this, getContext().VoidTy, S, 
+                                           EmitScalarExpr(E->getBase()), 
+                                           false, Args);
 }
 
 CGObjCRuntime::~CGObjCRuntime() {}

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sat Aug 30 00:35:15 2008
@@ -96,13 +96,15 @@
   virtual llvm::Constant *GenerateConstantString(const std::string &String);
   virtual CodeGen::RValue 
   GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                      const ObjCMessageExpr *E,
+                      QualType ResultType,
+                      Selector Sel,
                       llvm::Value *Receiver,
                       bool IsClassMessage,
                       const CallArgList &CallArgs);
   virtual CodeGen::RValue 
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                           const ObjCMessageExpr *E,
+                           QualType ResultType,
+                           Selector Sel,
                            const ObjCInterfaceDecl *Class,
                            llvm::Value *Receiver,
                            bool IsClassMessage,
@@ -239,16 +241,17 @@
 ///should be called.
 CodeGen::RValue
 CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                                    const ObjCMessageExpr *E,
+                                    QualType ResultType,
+                                    Selector Sel,
                                     const ObjCInterfaceDecl *Class,
                                     llvm::Value *Receiver,
                                     bool IsClassMessage,
                                     const CallArgList &CallArgs) {
   const ObjCInterfaceDecl *SuperClass = Class->getSuperClass();
-  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
   // TODO: This should be cached, not looked up every time.
   llvm::Value *ReceiverClass = GetClass(CGF.Builder, SuperClass);
-  llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
+  llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
   std::vector<const llvm::Type*> impArgTypes;
   impArgTypes.push_back(Receiver->getType());
   impArgTypes.push_back(SelectorTy);
@@ -282,18 +285,19 @@
   ActualArgs.push_back(std::make_pair(cmd,
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
-  return CGF.EmitCall(imp, E->getType(), ActualArgs);
+  return CGF.EmitCall(imp, ResultType, ActualArgs);
 }
 
 /// Generate code for a message send expression.  
 CodeGen::RValue
 CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                               const ObjCMessageExpr *E,
+                               QualType ResultType,
+                               Selector Sel,
                                llvm::Value *Receiver,
                                bool IsClassMessage,
                                const CallArgList &CallArgs) {
-  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
-  llvm::Value *cmd = GetSelector(CGF.Builder, E->getSelector());
+  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
+  llvm::Value *cmd = GetSelector(CGF.Builder, Sel);
 
   // Look up the method implementation.
   std::vector<const llvm::Type*> impArgTypes;
@@ -328,7 +332,7 @@
   ActualArgs.push_back(std::make_pair(cmd,
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
-  return CGF.EmitCall(imp, E->getType(), ActualArgs);
+  return CGF.EmitCall(imp, ResultType, ActualArgs);
 }
 
 /// Generates a MethodList.  Used in construction of a objc_class and 

Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Sat Aug 30 00:35:15 2008
@@ -219,7 +219,8 @@
                             const ObjCInterfaceDecl *ID);
 
   CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
-                                  const ObjCMessageExpr *E,
+                                  QualType ResultType,
+                                  Selector Sel,
                                   llvm::Value *Arg0,
                                   QualType Arg0Ty,
                                   bool IsSuper,
@@ -337,14 +338,16 @@
   virtual llvm::Constant *GenerateConstantString(const std::string &String);
 
   virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                                              const ObjCMessageExpr *E,
+                                              QualType ResultType,
+                                              Selector Sel,
                                               llvm::Value *Receiver,
                                               bool IsClassMessage,
                                               const CallArgList &CallArgs);
 
   virtual CodeGen::RValue 
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                           const ObjCMessageExpr *E,
+                           QualType ResultType,
+                           Selector Sel,
                            const ObjCInterfaceDecl *Class,
                            llvm::Value *Receiver,
                            bool IsClassMessage,
@@ -428,7 +431,8 @@
 /// which class's method should be called.
 CodeGen::RValue
 CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                                    const ObjCMessageExpr *E,
+                                    QualType ResultType,
+                                    Selector Sel,
                                     const ObjCInterfaceDecl *Class,
                                     llvm::Value *Receiver,
                                     bool IsClassMessage,
@@ -460,34 +464,35 @@
   CGF.Builder.CreateStore(Target, 
                           CGF.Builder.CreateStructGEP(ObjCSuper, 1));
     
-  return EmitMessageSend(CGF, E, 
+  return EmitMessageSend(CGF, ResultType, Sel, 
                          ObjCSuper, ObjCTypes.SuperPtrCTy,
                          true, CallArgs);
 }
                                            
 /// Generate code for a message send expression.  
 CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                                               const ObjCMessageExpr *E,
+                                               QualType ResultType,
+                                               Selector Sel,
                                                llvm::Value *Receiver,
                                                bool IsClassMessage,
                                                const CallArgList &CallArgs) {
   llvm::Value *Arg0 = 
     CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
-  return EmitMessageSend(CGF, E, 
+  return EmitMessageSend(CGF, ResultType, Sel,
                          Arg0, CGF.getContext().getObjCIdType(),
                          false, CallArgs);
 }
 
 CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
-                                           const ObjCMessageExpr *E,
+                                           QualType ResultType,
+                                           Selector Sel,
                                            llvm::Value *Arg0,
                                            QualType Arg0Ty,
                                            bool IsSuper,
                                            const CallArgList &CallArgs) {
   CallArgList ActualArgs;
   ActualArgs.push_back(std::make_pair(Arg0, Arg0Ty));
-  ActualArgs.push_back(std::make_pair(EmitSelector(CGF.Builder, 
-                                                   E->getSelector()),
+  ActualArgs.push_back(std::make_pair(EmitSelector(CGF.Builder, Sel),
                                       CGF.getContext().getObjCSelType()));
   ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
 
@@ -496,10 +501,9 @@
   // parameter and set the structure return flag. See
   // getMessageSendFn().
                                                    
-  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(E->getType());
+  const llvm::Type *ReturnTy = CGM.getTypes().ConvertType(ResultType);
   return CGF.EmitCall(ObjCTypes.getMessageSendFn(IsSuper, ReturnTy),
-                      E->getType(),
-                      ActualArgs);
+                      ResultType, ActualArgs);
 }
 
 llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder, 

Modified: cfe/trunk/lib/CodeGen/CGObjCRuntime.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCRuntime.h?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCRuntime.h (original)
+++ cfe/trunk/lib/CodeGen/CGObjCRuntime.h Sat Aug 30 00:35:15 2008
@@ -81,7 +81,8 @@
   /// Generate an Objective-C message send operation.
   virtual CodeGen::RValue 
   GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
-                      const ObjCMessageExpr *E,
+                      QualType ResultType,
+                      Selector Sel,
                       llvm::Value *Receiver,
                       bool IsClassMessage,
                       const CallArgList &CallArgs) = 0;
@@ -91,7 +92,8 @@
   /// object.
   virtual CodeGen::RValue
   GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
-                           const ObjCMessageExpr *E,
+                           QualType ResultType,
+                           Selector Sel,
                            const ObjCInterfaceDecl *Class,
                            llvm::Value *Self,
                            bool IsClassMessage,

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sat Aug 30 00:35:15 2008
@@ -299,8 +299,22 @@
   //                         Scalar Expression Emission
   //===--------------------------------------------------------------------===//
 
+  /// CallArgList - Type for representing both the value and type of
+  /// arguments in a call.
   typedef llvm::SmallVector<std::pair<llvm::Value*, QualType>, 16> CallArgList;
+
+  /// EmitCallArg - Emit the given expression and append the result
+  /// onto the given Args list.
   void EmitCallArg(const Expr *E, CallArgList &Args);
+
+  /// EmitCallArg - Append the appropriate call argument for the given
+  /// rvalue and type onto the Args list.
+  void EmitCallArg(RValue RV, QualType Ty, CallArgList &Args);
+
+  /// EmitCall - Generate a call of the given function, expecting the
+  /// given result type, and using the given argument list which
+  /// specifies both the LLVM arguments and the types they were
+  /// derived from.
   RValue EmitCall(llvm::Value *Callee,
                   QualType ResultType,
                   const CallArgList &Args);
@@ -366,6 +380,10 @@
   /// of complex type, storing into the specified Value*.
   void EmitComplexExprIntoAddr(const Expr *E, llvm::Value *DestAddr,
                                bool DestIsVolatile);
+
+  /// StoreComplexToAddr - Store a complex number into the specified address.
+  void StoreComplexToAddr(ComplexPairTy V, llvm::Value *DestAddr,
+                          bool DestIsVolatile);
   /// LoadComplexFromAddr - Load a complex number from the specified address.
   ComplexPairTy LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile);
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=55561&r1=55560&r2=55561&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Aug 30 00:35:15 2008
@@ -869,7 +869,11 @@
     
     // FIXME: The logic for looking up nullary and unary selectors should be
     // shared with the code in ActOnInstanceMessage.
-    
+
+    // FIXME: This logic is not correct, we should search for
+    // properties first. Additionally, the AST node doesn't currently
+    // have enough information to store the setter argument.
+#if 0
     // Before we look for explicit property declarations, we check for
     // nullary methods (which allow '.' notation).
     Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
@@ -886,6 +890,7 @@
             return new ObjCPropertyRefExpr(MD, MD->getResultType(), 
                                            MemberLoc, BaseExpr);
     }      
+#endif
     
     // FIXME: Need to deal with setter methods that take 1 argument. E.g.:
     // @interface NSBundle : NSObject {}





More information about the cfe-commits mailing list