/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, November 2010.  */
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */

/* Test dot-syntax with more tricky assignments.  */

#include <stdlib.h>
#include <objc/objc.h>
#include <objc/runtime.h>

@interface MyRootClass
{
  Class isa;
  id a;
  id b;
  int p1;
  float p2;
}
+ (id) initialize;
+ (id) alloc;
- (id) init;

@property (assign) id object1;
@property (assign) id object2;
- (id) test;
- (id) myself;
- (id) nilObject;

@property int p1;
@property float p2;
@end

@implementation MyRootClass
+ (id) initialize { return self; }
+ (id) alloc { return class_createInstance (self, 0); }
- (id) init { return self; }
@synthesize object1 = a;
@synthesize object2 = b;
- (id) test
{
  /* Test multiple assignments with 'self'.  */
  self.object1 = self.object2 = self;

  if (self.object1 != self || self.object2 != self)
    abort ();

  /* Test multiple assignments with a conditional and method calls.  */
  self.object1 = self.object2 = (self ? [self myself] : [self nilObject]);

  if (self.object1 != self || self.object2 != self)
    abort ();

  self.object1 = self.object2 = (self ? [self nilObject] : [self myself]);

  if (self.object1 != nil || self.object2 != nil)
    abort ();

  return self.object1;
}
- (id) myself
{
  return self;
}
- (id) nilObject
{
  return nil;
}

@synthesize p1;
@synthesize p2;
@end

int main (void)
{
  MyRootClass *object = [[MyRootClass alloc] init];
  MyRootClass *object1 = [[MyRootClass alloc] init];

  [object test];

  /* Now, test multiple assignments with different types.  Use
     int/float as they seem to happily crash the compiler in gimplify
     if proper conversions are not being generated by the
     frontend. ;-) */
  object.p1 = object.p2 = 12;

  if (object.p1 != 12 || object.p2 != 12)
    abort ();

  object.p1 = object.p2 = 2.7;

  if (object.p1 != 2)
    abort ();

  /* Just try a different loop, mixing in a few different standard C
     constructs to cover a few other cases.  */
  object.p1 = 10;
  object1.p1 = 0;
  while (object.p1)
    {
      object1.p1 += ((object.p2 = 4.56) ? 0 : object.p1);
      object.p1--;
    }

  if (object.p1 != 0 || object1.p1 != 0)
    abort ();

  if ((object.p1 = 0))
    abort ();

  return 0;
}


