| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 
 | // RUN: %check_clang_tidy %s android-comparison-in-temp-failure-retry %t
#define TEMP_FAILURE_RETRY(x)                                                  \
  ({                                                                           \
    typeof(x) __z;                                                             \
    do                                                                         \
      __z = (x);                                                               \
    while (__z == -1);                                                         \
    __z;                                                                       \
  })
int foo();
int bar(int a);
void test() {
  int i;
  TEMP_FAILURE_RETRY((i = foo()));
  TEMP_FAILURE_RETRY(foo());
  TEMP_FAILURE_RETRY((foo()));
  TEMP_FAILURE_RETRY(foo() == 1);
  // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: top-level comparison in TEMP_FAILURE_RETRY [android-comparison-in-temp-failure-retry]
  TEMP_FAILURE_RETRY((foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: top-level comparison in TEMP_FAILURE_RETRY
  TEMP_FAILURE_RETRY((int)(foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
  TEMP_FAILURE_RETRY(bar(foo() == 1));
  TEMP_FAILURE_RETRY((bar(foo() == 1)));
  TEMP_FAILURE_RETRY((bar(foo() == 1)) == 1);
  // CHECK-MESSAGES: :[[@LINE-1]]:40: warning: top-level comparison in TEMP_FAILURE_RETRY
  TEMP_FAILURE_RETRY(((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: top-level comparison in TEMP_FAILURE_RETRY
  TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
#define INDIRECT TEMP_FAILURE_RETRY
  INDIRECT(foo());
  INDIRECT((foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY
  INDIRECT(bar(foo() == 1));
  INDIRECT((int)((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY
#define TFR(x) TEMP_FAILURE_RETRY(x)
  TFR(foo());
  TFR((foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: top-level comparison in TEMP_FAILURE_RETRY
  TFR(bar(foo() == 1));
  TFR((int)((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY
#define ADD_TFR(x) (1 + TEMP_FAILURE_RETRY(x) + 1)
  ADD_TFR(foo());
  ADD_TFR(foo() == 1);
  // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: top-level comparison in TEMP_FAILURE_RETRY
  ADD_TFR(bar(foo() == 1));
  ADD_TFR((int)((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: top-level comparison in TEMP_FAILURE_RETRY
#define ADDP_TFR(x) (1 + TEMP_FAILURE_RETRY((x)) + 1)
  ADDP_TFR(foo());
  ADDP_TFR((foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: top-level comparison in TEMP_FAILURE_RETRY
  ADDP_TFR(bar(foo() == 1));
  ADDP_TFR((int)((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: top-level comparison in TEMP_FAILURE_RETRY
#define MACRO TEMP_FAILURE_RETRY(foo() == 1)
  MACRO;
  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: top-level comparison in TEMP_FAILURE_RETRY
  // Be sure that being a macro arg doesn't mess with this.
#define ID(x) (x)
  ID(ADDP_TFR(bar(foo() == 1)));
  ID(ADDP_TFR(bar(foo() == 1) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: top-level comparison in TEMP_FAILURE_RETRY
  ID(MACRO);
  // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: top-level comparison in TEMP_FAILURE_RETRY
#define CMP(x) x == 1
  TEMP_FAILURE_RETRY(CMP(foo()));
  // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: top-level comparison in TEMP_FAILURE_RETRY
}
// Be sure that it works inside of things like loops, if statements, etc.
void control_flow() {
  do {
    if (TEMP_FAILURE_RETRY(foo())) {
    }
    if (TEMP_FAILURE_RETRY(foo() == 1)) {
      // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
    }
    if (TEMP_FAILURE_RETRY(bar(foo() == 1))) {
    }
    if (TEMP_FAILURE_RETRY(bar(foo() == 1) == 1)) {
      // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: top-level comparison in TEMP_FAILURE_RETRY
    }
  } while (TEMP_FAILURE_RETRY(foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: top-level comparison in TEMP_FAILURE_RETRY
}
void with_nondependent_variable_type() {
#undef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(x)                                                  \
  ({                                                                           \
    long int __z;                                                              \
    do                                                                         \
      __z = (x);                                                               \
    while (__z == -1);                                                         \
    __z;                                                                       \
  })
  TEMP_FAILURE_RETRY((foo()));
  TEMP_FAILURE_RETRY((int)(foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
  TEMP_FAILURE_RETRY((bar(foo() == 1)));
  TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
}
// I can't find a case where TEMP_FAILURE_RETRY is implemented like this, but if
// we can cheaply support it, I don't see why not.
void obscured_temp_failure_retry() {
#undef TEMP_FAILURE_RETRY
#define IMPL(x)                                                                \
  ({                                                                           \
    typeof(x) __z;                                                             \
    do                                                                         \
      __z = (x);                                                               \
    while (__z == -1);                                                         \
    __z;                                                                       \
  })
#define IMPL2(x) IMPL(x)
#define TEMP_FAILURE_RETRY(x) IMPL2(x)
  TEMP_FAILURE_RETRY((foo()));
  TEMP_FAILURE_RETRY((int)(foo() == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: top-level comparison in TEMP_FAILURE_RETRY
  TEMP_FAILURE_RETRY((bar(foo() == 1)));
  TEMP_FAILURE_RETRY((int)((bar(foo() == 1)) == 1));
  // CHECK-MESSAGES: :[[@LINE-1]]:46: warning: top-level comparison in TEMP_FAILURE_RETRY
}
 |