// Clear and create directories
// RUN: rm -rf %t
// RUN: mkdir %t
// RUN: mkdir %t/cache
// RUN: mkdir %t/Inputs

// Build first header file
// RUN: echo "#define FIRST" >> %t/Inputs/first.h
// RUN: cat %s               >> %t/Inputs/first.h

// Build second header file
// RUN: echo "#define SECOND" >> %t/Inputs/second.h
// RUN: cat %s                >> %t/Inputs/second.h

// Test that each header can compile
// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/first.h
// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/second.h

// Build module map file
// RUN: echo "module FirstModule {"     >> %t/Inputs/module.map
// RUN: echo "    header \"first.h\""   >> %t/Inputs/module.map
// RUN: echo "}"                        >> %t/Inputs/module.map
// RUN: echo "module SecondModule {"    >> %t/Inputs/module.map
// RUN: echo "    header \"second.h\""  >> %t/Inputs/module.map
// RUN: echo "}"                        >> %t/Inputs/module.map

// Run test
// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++1z

#if !defined(FIRST) && !defined(SECOND)
#include "first.h"
#include "second.h"
#endif

// Used for testing
#if defined(FIRST)
#define ACCESS public:
#elif defined(SECOND)
#define ACCESS private:
#endif

namespace AccessSpecifiers {
#if defined(FIRST)
struct S1 {
};
#elif defined(SECOND)
struct S1 {
  private:
};
#else
S1 s1;
// expected-error@second.h:* {{'AccessSpecifiers::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found end of class}}
#endif

#if defined(FIRST)
struct S2 {
  public:
};
#elif defined(SECOND)
struct S2 {
  protected:
};
#else
S2 s2;
// expected-error@second.h:* {{'AccessSpecifiers::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found protected access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif

#define DECLS \
public:       \
private:      \
protected:

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'AccessSpecifiers::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif

#undef DECLS
} // namespace AccessSpecifiers

namespace StaticAssert {
#if defined(FIRST)
struct S1 {
  static_assert(1 == 1, "First");
};
#elif defined(SECOND)
struct S1 {
  static_assert(1 == 1, "Second");
};
#else
S1 s1;
// expected-error@second.h:* {{'StaticAssert::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found static assert with message}}
// expected-note@first.h:* {{but in 'FirstModule' found static assert with different message}}
#endif

#if defined(FIRST)
struct S2 {
  static_assert(2 == 2, "Message");
};
#elif defined(SECOND)
struct S2 {
  static_assert(2 == 2);
};
#else
S2 s2;
// expected-error@second.h:* {{'StaticAssert::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found static assert with no message}}
// expected-note@first.h:* {{but in 'FirstModule' found static assert with message}}
#endif

#if defined(FIRST)
struct S3 {
  static_assert(3 == 3, "Message");
};
#elif defined(SECOND)
struct S3 {
  static_assert(3 != 4, "Message");
};
#else
S3 s3;
// expected-error@second.h:* {{'StaticAssert::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found static assert with condition}}
// expected-note@first.h:* {{but in 'FirstModule' found static assert with different condition}}
#endif

#if defined(FIRST)
struct S4 {
  static_assert(4 == 4, "Message");
};
#elif defined(SECOND)
struct S4 {
  public:
};
#else
S4 s4;
// expected-error@second.h:* {{'StaticAssert::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found static assert}}
#endif

#define DECLS                       \
  static_assert(4 == 4, "Message"); \
  static_assert(5 == 5);

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'StaticAssert::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace StaticAssert

namespace Field {
#if defined(FIRST)
struct S1 {
  int x;
  private:
  int y;
};
#elif defined(SECOND)
struct S1 {
  int x;
  int y;
};
#else
S1 s1;
// expected-error@second.h:* {{'Field::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
// expected-note@first.h:* {{but in 'FirstModule' found private access specifier}}
#endif

#if defined(FIRST)
struct S2 {
  int x;
  int y;
};
#elif defined(SECOND)
struct S2 {
  int y;
  int x;
};
#else
S2 s2;
// expected-error@second.h:* {{'Field::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'y'}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x'}}
#endif

#if defined(FIRST)
struct S3 {
  double x;
};
#elif defined(SECOND)
struct S3 {
  int x;
};
#else
S3 s3;
// expected-error@first.h:* {{'Field::S3::x' from module 'FirstModule' is not present in definition of 'Field::S3' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
typedef int A;
struct S4 {
  A x;
};

struct S5 {
  A x;
};
#elif defined(SECOND)
typedef int B;
struct S4 {
  B x;
};

struct S5 {
  int x;
};
#else
S4 s4;
// expected-error@second.h:* {{'Field::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'Field::B' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'Field::A' (aka 'int')}}

S5 s5;
// expected-error@second.h:* {{'Field::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'int'}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'Field::A' (aka 'int')}}
#endif

#if defined(FIRST)
struct S6 {
  unsigned x;
};
#elif defined(SECOND)
struct S6 {
  unsigned x : 1;
};
#else
S6 s6;
// expected-error@second.h:* {{'Field::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x'}}
// expected-note@first.h:* {{but in 'FirstModule' found non-bitfield 'x'}}
#endif

#if defined(FIRST)
struct S7 {
  unsigned x : 2;
};
#elif defined(SECOND)
struct S7 {
  unsigned x : 1;
};
#else
S7 s7;
// expected-error@second.h:* {{'Field::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x' with one width expression}}
// expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}}
#endif

#if defined(FIRST)
struct S8 {
  unsigned x : 2;
};
#elif defined(SECOND)
struct S8 {
  unsigned x : 1 + 1;
};
#else
S8 s8;
// expected-error@second.h:* {{'Field::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x' with one width expression}}
// expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}}
#endif

#if defined(FIRST)
struct S9 {
  mutable int x;
};
#elif defined(SECOND)
struct S9 {
  int x;
};
#else
S9 s9;
// expected-error@second.h:* {{'Field::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found non-mutable field 'x'}}
// expected-note@first.h:* {{but in 'FirstModule' found mutable field 'x'}}
#endif

#if defined(FIRST)
struct S10 {
  unsigned x = 5;
};
#elif defined(SECOND)
struct S10 {
  unsigned x;
};
#else
S10 s10;
// expected-error@second.h:* {{'Field::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with no initalizer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with an initializer}}
#endif

#if defined(FIRST)
struct S11 {
  unsigned x = 5;
};
#elif defined(SECOND)
struct S11 {
  unsigned x = 7;
};
#else
S11 s11;
// expected-error@second.h:* {{'Field::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with a different initializer}}
#endif

#if defined(FIRST)
struct S12 {
  unsigned x[5];
};
#elif defined(SECOND)
struct S12 {
  unsigned x[7];
};
#else
S12 s12;
// expected-error@first.h:* {{'Field::S12::x' from module 'FirstModule' is not present in definition of 'Field::S12' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
struct S13 {
  unsigned x[7];
};
#elif defined(SECOND)
struct S13 {
  double x[7];
};
#else
S13 s13;
// expected-error@first.h:* {{'Field::S13::x' from module 'FirstModule' is not present in definition of 'Field::S13' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#define DECLS         \
  int a;              \
  int b : 3;          \
  unsigned c : 1 + 2; \
  s d;                \
  double e = 1.0;     \
  long f[5];

#if defined(FIRST) || defined(SECOND)
typedef short s;
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'Field::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace Field

namespace Method {
#if defined(FIRST)
struct S1 {
  void A() {}
};
#elif defined(SECOND)
struct S1 {
  private:
  void A() {}
};
#else
S1 s1;
// expected-error@second.h:* {{'Method::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found method}}
#endif

#if defined(FIRST)
struct S2 {
  void A() {}
  void B() {}
};
#elif defined(SECOND)
struct S2 {
  void B() {}
  void A() {}
};
#else
S2 s2;
// expected-error@second.h:* {{'Method::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'B'}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A'}}
#endif

#if defined(FIRST)
struct S3 {
  static void A() {}
  void A(int) {}
};
#elif defined(SECOND)
struct S3 {
  void A(int) {}
  static void A() {}
};
#else
S3 s3;
// expected-error@second.h:* {{'Method::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' is not static}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' is static}}
#endif

#if defined(FIRST)
struct S4 {
  virtual void A() {}
  void B() {}
};
#elif defined(SECOND)
struct S4 {
  void A() {}
  virtual void B() {}
};
#else
S4 s4;
// expected-error@second.h:* {{'Method::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' is not virtual}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' is virtual}}
#endif

#if defined(FIRST)
struct S5 {
  virtual void A() = 0;
  virtual void B() {};
};
#elif defined(SECOND)
struct S5 {
  virtual void A() {}
  virtual void B() = 0;
};
#else
S5 *s5;
// expected-error@second.h:* {{'Method::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' is virtual}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' is pure virtual}}
#endif

#if defined(FIRST)
struct S6 {
  inline void A() {}
};
#elif defined(SECOND)
struct S6 {
  void A() {}
};
#else
S6 s6;
// expected-error@second.h:* {{'Method::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' is not inline}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' is inline}}
#endif

#if defined(FIRST)
struct S7 {
  void A() volatile {}
  void A() {}
};
#elif defined(SECOND)
struct S7 {
  void A() {}
  void A() volatile {}
};
#else
S7 s7;
// expected-error@second.h:* {{'Method::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' is not volatile}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' is volatile}}
#endif

#if defined(FIRST)
struct S8 {
  void A() const {}
  void A() {}
};
#elif defined(SECOND)
struct S8 {
  void A() {}
  void A() const {}
};
#else
S8 s8;
// expected-error@second.h:* {{'Method::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' is not const}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' is const}}
#endif

#if defined(FIRST)
struct S9 {
  void A(int x) {}
  void A(int x, int y) {}
};
#elif defined(SECOND)
struct S9 {
  void A(int x, int y) {}
  void A(int x) {}
};
#else
S9 s9;
// expected-error@second.h:* {{'Method::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' that has 2 parameters}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' that has 1 parameter}}
#endif

#if defined(FIRST)
struct S10 {
  void A(int x) {}
  void A(float x) {}
};
#elif defined(SECOND)
struct S10 {
  void A(float x) {}
  void A(int x) {}
};
#else
S10 s10;
// expected-error@second.h:* {{'Method::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter of type 'float'}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter of type 'int'}}
#endif

#if defined(FIRST)
struct S11 {
  void A(int x);
};
#elif defined(SECOND)
struct S11 {
  void A(int y);
};
#else
S11 s11;
// expected-error@second.h:* {{'Method::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter named 'y'}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter named 'x'}}
#endif

#if defined(FIRST)
struct S12 {
  void A(int x);
};
#elif defined(SECOND)
struct S12 {
  void A(int x = 1);
};
#else
S12 s12;
// expected-error@second.h:* {{'Method::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter without a default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter with a default argument}}
#endif

#if defined(FIRST)
struct S13 {
  void A(int x = 1 + 0);
};
#elif defined(SECOND)
struct S13 {
  void A(int x = 1);
};
#else
S13 s13;
// expected-error@second.h:* {{'Method::S13' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter with a default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter with a different default argument}}
#endif

#if defined(FIRST)
struct S14 {
  void A(int x[2]);
};
#elif defined(SECOND)
struct S14 {
  void A(int x[3]);
};
#else
S14 s14;
// expected-error@second.h:* {{'Method::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter of type 'int *' decayed from 'int [3]'}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter of type 'int *' decayed from 'int [2]'}}
#endif

#if defined(FIRST)
struct S15 {
  int A() { return 0; }
};
#elif defined(SECOND)
struct S15 {
  long A() { return 0; }
};
#else
S15 s15;
// expected-error@first.h:* {{'Method::S15::A' from module 'FirstModule' is not present in definition of 'Method::S15' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'A' does not match}}
#endif

#define DECLS            \
  void A();              \
  static void B();       \
  virtual void C();      \
  virtual void D() = 0;  \
  inline void E();       \
  void F() const;        \
  void G() volatile;     \
  void H(int x);         \
  void I(int x = 5 + 5); \
  void J(int);           \
  void K(int x[2]);      \
  int L();

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1* v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1* i1;
// expected-error@second.h:* {{'Method::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace Method

namespace MethodBody {
#if defined(FIRST)
struct S1 {
  int A() { return 0; }
};
#elif defined(SECOND)
struct S1 {
  int A() { return 0; }
};
#else
S1 s1;
#endif

#if defined(FIRST)
struct S2 {
  int BothBodies() { return 0; }
};
#elif defined(SECOND)
struct S2 {
  int BothBodies() { return 1; }
};
#else
S2 s2;
// expected-error@first.h:* {{'MethodBody::S2' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'BothBodies' with body}}
// expected-note@second.h:* {{but in 'SecondModule' found method 'BothBodies' with different body}}
#endif

#if defined(FIRST)
struct S3 {
  int FirstBody() { return 0; }
};
#elif defined(SECOND)
struct S3 {
  int FirstBody();
};
#else
S3 s3;
// expected-error@first.h:* {{'MethodBody::S3' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstBody' with body}}
// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstBody' with no body}}
#endif

#if defined(FIRST)
struct S4 {
  int SecondBody();
};
#elif defined(SECOND)
struct S4 {
  int SecondBody() { return 0; }
};
#else
S4 s4;
// expected-error@first.h:* {{'MethodBody::S4' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'SecondBody' with no body}}
// expected-note@second.h:* {{but in 'SecondModule' found method 'SecondBody' with body}}
#endif

#if defined(FIRST)
struct S5 {
  int FirstBodySecondOutOfLine() { return 0; }
};
#elif defined(SECOND)
struct S5 {
  int FirstBodySecondOutOfLine();
};
int S5::FirstBodySecondOutOfLine() { return 0; }
#else
S5 s5;
// expected-error@second.h:* {{'MethodBody::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'FirstBodySecondOutOfLine' with no body}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'FirstBodySecondOutOfLine' with body}}
#endif

#if defined(FIRST)
struct S6 {
  int FirstOutOfLineSecondBody();
};
int S6::FirstOutOfLineSecondBody() { return 0; }
#elif defined(SECOND)
struct S6 {
  int FirstOutOfLineSecondBody() { return 0; }
};
#else
S6 s6;
// expected-error@first.h:* {{'MethodBody::S6' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstOutOfLineSecondBody' with no body}}
// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstOutOfLineSecondBody' with body}}
#endif

#if defined(FIRST)
struct S7 {
  int BothOutOfLine();
};
int S7::BothOutOfLine() { return 1; }
#elif defined(SECOND)
struct S7 {
  int BothOutOfLine();
};
int S7::BothOutOfLine() { return 0; }
#else
S7 s7;
// expected-error@second.h:* {{'MethodBody::S7::BothOutOfLine' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
#endif

#if defined(FIRST)
struct S8 {
  int FirstBodySecondOutOfLine() { return 0; }
};
#elif defined(SECOND)
struct S8 {
  int FirstBodySecondOutOfLine();
};
int S8::FirstBodySecondOutOfLine() { return 1; }
#else
S8 s8;
// expected-error@second.h:* {{'MethodBody::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'FirstBodySecondOutOfLine' with no body}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'FirstBodySecondOutOfLine' with body}}
#endif

#if defined(FIRST)
struct S9 {
  int FirstOutOfLineSecondBody();
};
int S9::FirstOutOfLineSecondBody() { return 1; }
#elif defined(SECOND)
struct S9 {
  int FirstOutOfLineSecondBody() { return 0; }
};
#else
S9 s9;
// expected-error@first.h:* {{'MethodBody::S9' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'FirstOutOfLineSecondBody' with no body}}
// expected-note@second.h:* {{but in 'SecondModule' found method 'FirstOutOfLineSecondBody' with body}}
#endif

#if defined(FIRST)
struct S10 {
  S10(int);
  S10() = delete;
};
#elif defined(SECOND)
struct S10 {
  S10(int);
  S10();
};
#else
S10 s10(10);
// expected-error@first.h:* {{'MethodBody::S10' has different definitions in different modules; first difference is definition in module 'FirstModule' found constructor is deleted}}
// expected-note@second.h:* {{but in 'SecondModule' found constructor is not deleted}}
#endif

#if defined(FIRST)
struct S11 {
  S11() = default;
};
#elif defined(SECOND)
struct S11 {
  S11();
};
#else
S11 s11;
// expected-error@first.h:* {{'MethodBody::S11' has different definitions in different modules; first difference is definition in module 'FirstModule' found constructor is defaulted}}
// expected-note@second.h:* {{but in 'SecondModule' found constructor is not defaulted}}
#endif

#define DECLS(CLASSNAME) \
  CLASSNAME() = default; \
  ~CLASSNAME() = delete; \
  void A();              \
  void B() { return; };  \
  void C();              \
  void D();

#define OUTOFLINEDEFS(CLASSNAME) \
  void CLASSNAME::C() {}         \
  void CLASSNAME::D() { return; }

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS(Valid1)
};
OUTOFLINEDEFS(Valid1)
#else
Valid1* v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS(Invalid1)
  ACCESS
};
OUTOFLINEDEFS(Invalid1)
#else
Invalid1* i1;
// expected-error@first.h:* {{'MethodBody::Invalid1' has different definitions in different modules; first difference is definition in module 'FirstModule' found public access specifier}}
// expected-note@second.h:* {{but in 'SecondModule' found private access specifier}}
#endif
#undef DECLS
}  // namespace MethodBody

namespace Constructor {
#if defined(FIRST)
struct S1 {
  S1() {}
  void foo() {}
};
#elif defined(SECOND)
struct S1 {
  void foo() {}
  S1() {}
};
#else
S1 s1;
// expected-error@second.h:* {{'Constructor::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'foo'}}
// expected-note@first.h:* {{but in 'FirstModule' found constructor}}
#endif

#if defined(FIRST)
struct S2 {
  S2(int) {}
  S2(int, int) {}
};
#elif defined(SECOND)
struct S2 {
  S2(int, int) {}
  S2(int) {}
};
#else
S2* s2;
// expected-error@second.h:* {{'Constructor::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found constructor that has 2 parameters}}
// expected-note@first.h:* {{but in 'FirstModule' found constructor that has 1 parameter}}
#endif

#define DECLS(CLASS) \
  CLASS(int);        \
  CLASS(double);     \
  CLASS(int, int);

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS(Valid1)
};
#else
Valid1* v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS(Invalid1)
  ACCESS
};
#else
Invalid1* i1;
// expected-error@second.h:* {{'Constructor::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace Constructor

namespace Destructor {
#if defined(FIRST)
struct S1 {
  ~S1() {}
  S1() {}
};
#elif defined(SECOND)
struct S1 {
  S1() {}
  ~S1() {}
};
#else
S1 s1;
// expected-error@second.h:* {{'Destructor::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found constructor}}
// expected-note@first.h:* {{but in 'FirstModule' found destructor}}
#endif

#if defined(FIRST)
struct S2 {
  virtual ~S2() {}
  void foo() {}
};
#elif defined(SECOND)
struct S2 {
  ~S2() {}
  virtual void foo() {}
};
#else
S2 s2;
// expected-error@second.h:* {{'Destructor::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found destructor is not virtual}}
// expected-note@first.h:* {{but in 'FirstModule' found destructor is virtual}}
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  ~Valid1();
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  ~Invalid1();
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'Destructor::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid2 {
  virtual ~Valid2();
};
#else
Valid2 v2;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid2 {
  virtual ~Invalid2();
  ACCESS
};
#else
Invalid2 i2;
// expected-error@second.h:* {{'Destructor::Invalid2' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
}  // namespace Destructor

namespace TypeDef {
#if defined(FIRST)
struct S1 {
  typedef int a;
};
#elif defined(SECOND)
struct S1 {
  typedef double a;
};
#else
S1 s1;
// expected-error@first.h:* {{'TypeDef::S1::a' from module 'FirstModule' is not present in definition of 'TypeDef::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'a' does not match}}
#endif

#if defined(FIRST)
struct S2 {
  typedef int a;
};
#elif defined(SECOND)
struct S2 {
  typedef int b;
};
#else
S2 s2;
// expected-error@first.h:* {{'TypeDef::S2::a' from module 'FirstModule' is not present in definition of 'TypeDef::S2' in module 'SecondModule'}}
// expected-note@second.h:* {{definition has no member 'a'}}
#endif

#if defined(FIRST)
typedef int T;
struct S3 {
  typedef T a;
};
#elif defined(SECOND)
typedef double T;
struct S3 {
  typedef T a;
};
#else
S3 s3;
// expected-error@first.h:* {{'TypeDef::S3::a' from module 'FirstModule' is not present in definition of 'TypeDef::S3' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'a' does not match}}
#endif

#if defined(FIRST)
struct S4 {
  typedef int a;
  typedef int b;
};
#elif defined(SECOND)
struct S4 {
  typedef int b;
  typedef int a;
};
#else
S4 s4;
// expected-error@second.h:* {{'TypeDef::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef name 'b'}}
// expected-note@first.h:* {{but in 'FirstModule' found typedef name 'a'}}
#endif

#if defined(FIRST)
struct S5 {
  typedef int a;
  typedef int b;
  int x;
};
#elif defined(SECOND)
struct S5 {
  int x;
  typedef int b;
  typedef int a;
};
#else
S5 s5;
// expected-error@second.h:* {{'TypeDef::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
// expected-note@first.h:* {{but in 'FirstModule' found typedef}}
#endif

#if defined(FIRST)
typedef float F;
struct S6 {
  typedef int a;
  typedef F b;
};
#elif defined(SECOND)
struct S6 {
  typedef int a;
  typedef float b;
};
#else
S6 s6;
// expected-error@second.h:* {{'TypeDef::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef 'b' with underlying type 'float'}}
// expected-note@first.h:* {{but in 'FirstModule' found typedef 'b' with different underlying type 'TypeDef::F' (aka 'float')}}
#endif

#define DECLS       \
  typedef int A;    \
  typedef double B; \
  typedef I C;

#if defined(FIRST) || defined(SECOND)
typedef int I;
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'TypeDef::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace TypeDef

namespace Using {
#if defined(FIRST)
struct S1 {
  using a = int;
};
#elif defined(SECOND)
struct S1 {
  using a = double;
};
#else
S1 s1;
// expected-error@first.h:* {{'Using::S1::a' from module 'FirstModule' is not present in definition of 'Using::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'a' does not match}}
#endif

#if defined(FIRST)
struct S2 {
  using a = int;
};
#elif defined(SECOND)
struct S2 {
  using b = int;
};
#else
S2 s2;
// expected-error@first.h:* {{'Using::S2::a' from module 'FirstModule' is not present in definition of 'Using::S2' in module 'SecondModule'}}
// expected-note@second.h:* {{definition has no member 'a'}}
#endif

#if defined(FIRST)
typedef int T;
struct S3 {
  using a = T;
};
#elif defined(SECOND)
typedef double T;
struct S3 {
  using a = T;
};
#else
S3 s3;
// expected-error@first.h:* {{'Using::S3::a' from module 'FirstModule' is not present in definition of 'Using::S3' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'a' does not match}}
#endif

#if defined(FIRST)
struct S4 {
  using a = int;
  using b = int;
};
#elif defined(SECOND)
struct S4 {
  using b = int;
  using a = int;
};
#else
S4 s4;
// expected-error@second.h:* {{'Using::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias name 'b'}}
// expected-note@first.h:* {{but in 'FirstModule' found type alias name 'a'}}
#endif

#if defined(FIRST)
struct S5 {
  using a = int;
  using b = int;
  int x;
};
#elif defined(SECOND)
struct S5 {
  int x;
  using b = int;
  using a = int;
};
#else
S5 s5;
// expected-error@second.h:* {{'Using::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
// expected-note@first.h:* {{but in 'FirstModule' found type alias}}
#endif

#if defined(FIRST)
typedef float F;
struct S6 {
  using a = int;
  using b = F;
};
#elif defined(SECOND)
struct S6 {
  using a = int;
  using b = float;
};
#else
S6 s6;
// expected-error@second.h:* {{'Using::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'b' with underlying type 'float'}}
// expected-note@first.h:* {{but in 'FirstModule' found type alias 'b' with different underlying type 'Using::F' (aka 'float')}}
#endif

#if defined(FIRST) || defined(SECOND)
using I = int;
#endif

#define DECLS       \
  using A = int;    \
  using B = double; \
  using C = I;

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'Using::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace Using

namespace RecordType {
#if defined(FIRST)
struct B1 {};
struct S1 {
  B1 x;
};
#elif defined(SECOND)
struct A1 {};
struct S1 {
  A1 x;
};
#else
S1 s1;
// expected-error@first.h:* {{'RecordType::S1::x' from module 'FirstModule' is not present in definition of 'RecordType::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#define DECLS \
  Foo F;

#if defined(FIRST) || defined(SECOND)
struct Foo {};
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'RecordType::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace RecordType

namespace DependentType {
#if defined(FIRST)
template <class T>
class S1 {
  typename T::typeA x;
};
#elif defined(SECOND)
template <class T>
class S1 {
  typename T::typeB x;
};
#else
template<class T>
using U1 = S1<T>;
// expected-error@first.h:* {{'DependentType::S1::x' from module 'FirstModule' is not present in definition of 'S1<T>' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#define DECLS \
  typename T::typeA x;

#if defined(FIRST) || defined(SECOND)
template <class T>
struct Valid1 {
  DECLS
};
#else
template <class T>
using V1 = Valid1<T>;
#endif

#if defined(FIRST) || defined(SECOND)
template <class T>
struct Invalid1 {
  DECLS
  ACCESS
};
#else
template <class T>
using I1 = Invalid1<T>;
// expected-error@second.h:* {{'DependentType::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace DependentType

namespace ElaboratedType {
#if defined(FIRST)
namespace N1 { using type = double; }
struct S1 {
  N1::type x;
};
#elif defined(SECOND)
namespace N1 { using type = int; }
struct S1 {
  N1::type x;
};
#else
S1 s1;
// expected-error@first.h:* {{'ElaboratedType::S1::x' from module 'FirstModule' is not present in definition of 'ElaboratedType::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#define DECLS \
  NS::type x;

#if defined(FIRST) || defined(SECOND)
namespace NS { using type = float; }
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'ElaboratedType::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace ElaboratedType

namespace Enum {
#if defined(FIRST)
enum A1 {};
struct S1 {
  A1 x;
};
#elif defined(SECOND)
enum A2 {};
struct S1 {
  A2 x;
};
#else
S1 s1;
// expected-error@first.h:* {{'Enum::S1::x' from module 'FirstModule' is not present in definition of 'Enum::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#define DECLS \
  E e = E1;

#if defined(FIRST) || defined(SECOND)
enum E { E1, E2 };
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'Enum::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}

namespace NestedNamespaceSpecifier {
#if defined(FIRST)
namespace LevelA1 {
using Type = int;
}

struct S1 {
  LevelA1::Type x;
};
# elif defined(SECOND)
namespace LevelB1 {
namespace LevelC1 {
using Type = int;
}
}

struct S1 {
  LevelB1::LevelC1::Type x;
};
#else
S1 s1;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'LevelB1::LevelC1::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA1::Type' (aka 'int')}}
#endif

#if defined(FIRST)
namespace LevelA2 { using Type = int; }
struct S2 {
  LevelA2::Type x;
};
# elif defined(SECOND)
struct S2 {
  int x;
};
#else
S2 s2;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'int'}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA2::Type' (aka 'int')}}
#endif

namespace LevelA3 { using Type = int; }
namespace LevelB3 { using Type = int; }
#if defined(FIRST)
struct S3 {
  LevelA3::Type x;
};
# elif defined(SECOND)
struct S3 {
  LevelB3::Type x;
};
#else
S3 s3;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'LevelB3::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'LevelA3::Type' (aka 'int')}}
#endif

#if defined(FIRST)
struct TA4 { using Type = int; };
struct S4 {
  TA4::Type x;
};
# elif defined(SECOND)
struct TB4 { using Type = int; };
struct S4 {
  TB4::Type x;
};
#else
S4 s4;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'TB4::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'TA4::Type' (aka 'int')}}
#endif

#if defined(FIRST)
struct T5 { using Type = int; };
struct S5 {
  T5::Type x;
};
# elif defined(SECOND)
namespace T5 { using Type = int; };
struct S5 {
  T5::Type x;
};
#else
S5 s5;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'T5::Type' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'T5::Type' (aka 'int')}}
#endif

#if defined(FIRST)
namespace N6 {using I = int;}
struct S6 {
  NestedNamespaceSpecifier::N6::I x;
};
# elif defined(SECOND)
using I = int;
struct S6 {
  ::NestedNamespaceSpecifier::I x;
};
#else
S6 s6;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '::NestedNamespaceSpecifier::I' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'NestedNamespaceSpecifier::N6::I' (aka 'int')}}
#endif

#if defined(FIRST)
template <class T, class U>
class S7 {
  typename T::type *x = {};
  int z = x->T::foo();
};
#elif defined(SECOND)
template <class T, class U>
class S7 {
  typename T::type *x = {};
  int z = x->U::foo();
};
#else
template <class T, class U>
using U7 = S7<T, U>;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'z' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'z' with a different initializer}}
#endif

#if defined(FIRST)
template <class T>
class S8 {
  int x = T::template X<int>::value;
};
#elif defined(SECOND)
template <class T>
class S8 {
  int x = T::template Y<int>::value;
};
#else
template <class T>
using U8 = S8<T>;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with a different initializer}}
#endif

#if defined(FIRST)
namespace N9 { using I = int; }
namespace O9 = N9;
struct S9 {
  O9::I x;
};
#elif defined(SECOND)
namespace N9 { using I = int; }
namespace P9 = N9;
struct S9 {
  P9::I x;
};
#else
S9 s9;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type 'P9::I' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'O9::I' (aka 'int')}}
#endif

namespace N10 {
#if defined(FIRST)
inline namespace A { struct X {}; }
struct S10 {
  A::X x;
};
#elif defined(SECOND)
inline namespace B { struct X {}; }
struct S10 {
  B::X x;
};
#else
S10 s10;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::N10::S10::x' from module 'SecondModule' is not present in definition of 'NestedNamespaceSpecifier::N10::S10' in module 'FirstModule'}}
// expected-note@first.h:* {{declaration of 'x' does not match}}
#endif
}

#define DECLS       \
  NS1::Type a;      \
  NS1::NS2::Type b; \
  NS1::S c;         \
  NS3::Type d;

#if defined(FIRST) || defined(SECOND)
namespace NS1 {
  using Type = int;
  namespace NS2 {
    using Type = double;
  }
  struct S {};
}
namespace NS3 = NS1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS

#define DECLS               \
  typename T::type *x = {}; \
  int y = x->T::foo();      \
  int z = U::template X<int>::value;

#if defined(FIRST) || defined(SECOND)
template <class T, class U>
struct Valid2 {
  DECLS
};
#else
template <class T, class U>
using V2 = Valid2<T, U>;
#endif

#if defined(FIRST) || defined(SECOND)
template <class T, class U>
struct Invalid2 {
  DECLS
  ACCESS
};
#else
template <class T, class U>
using I2 = Invalid2<T, U>;
// expected-error@second.h:* {{'NestedNamespaceSpecifier::Invalid2' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace NestedNamespaceSpecifier

namespace TemplateSpecializationType {
#if defined(FIRST)
template <class T1> struct U1 {};
struct S1 {
  U1<int> u;
};
#elif defined(SECOND)
template <class T1, class T2> struct U1 {};
struct S1 {
  U1<int, int> u;
};
#else
S1 s1;
// expected-error@first.h:* {{'TemplateSpecializationType::S1::u' from module 'FirstModule' is not present in definition of 'TemplateSpecializationType::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'u' does not match}}
#endif

#if defined(FIRST)
template <class T1> struct U2 {};
struct S2 {
  U2<int> u;
};
#elif defined(SECOND)
template <class T1> struct V1 {};
struct S2 {
  V1<int> u;
};
#else
S2 s2;
// expected-error@first.h:* {{'TemplateSpecializationType::S2::u' from module 'FirstModule' is not present in definition of 'TemplateSpecializationType::S2' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'u' does not match}}
#endif

#define DECLS                       \
  OneTemplateArg<int> x;            \
  OneTemplateArg<double> y;         \
  OneTemplateArg<char *> z;         \
  TwoTemplateArgs<int, int> a;      \
  TwoTemplateArgs<double, float> b; \
  TwoTemplateArgs<short *, char> c;

#if defined(FIRST) || defined(SECOND)
template <class T> struct OneTemplateArg {};
template <class T, class U> struct TwoTemplateArgs {};
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
DECLS
ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'TemplateSpecializationType::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace TemplateSpecializationType

namespace TemplateArgument {
#if defined(FIRST)
template <class> struct U1{};
struct S1 {
  U1<int> x;
};
#elif defined(SECOND)
template <int> struct U1{};
struct S1 {
  U1<1> x;
};
#else
S1 s1;
// expected-error@first.h:* {{'TemplateArgument::S1::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
template <int> struct U2{};
struct S2 {
  using T = U2<2>;
};
#elif defined(SECOND)
template <int> struct U2{};
struct S2 {
  using T = U2<(2)>;
};
#else
S2 s2;
// expected-error@second.h:* {{'TemplateArgument::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'U2<(2)>'}}
// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'U2<2>'}}
#endif

#if defined(FIRST)
template <int> struct U3{};
struct S3 {
  using T = U3<2>;
};
#elif defined(SECOND)
template <int> struct U3{};
struct S3 {
  using T = U3<1 + 1>;
};
#else
S3 s3;
// expected-error@second.h:* {{'TemplateArgument::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'U3<1 + 1>'}}
// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'U3<2>'}}
#endif

#if defined(FIRST)
template<class> struct T4a {};
template <template <class> class T> struct U4 {};
struct S4 {
  U4<T4a> x;
};
#elif defined(SECOND)
template<class> struct T4b {};
template <template <class> class T> struct U4 {};
struct S4 {
  U4<T4b> x;
};
#else
S4 s4;
// expected-error@first.h:* {{'TemplateArgument::S4::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S4' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
template <class T> struct U5 {};
struct S5 {
  U5<int> x;
};
#elif defined(SECOND)
template <class T> struct U5 {};
struct S5 {
  U5<short> x;
};
#else
S5 s5;
// expected-error@first.h:* {{'TemplateArgument::S5::x' from module 'FirstModule' is not present in definition of 'TemplateArgument::S5' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
template <class T> struct U6 {};
struct S6 {
  U6<int> x;
  U6<short> y;
};
#elif defined(SECOND)
template <class T> struct U6 {};
struct S6 {
  U6<short> y;
  U6<int> x;
};
#else
S6 s6;
// expected-error@second.h:* {{'TemplateArgument::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'y'}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x'}}
#endif

#if defined(FIRST)
struct S7 {
  template<int> void run() {}
  template<> void run<1>() {}
};
#elif defined(SECOND)
struct S7 {
  template<int> void run() {}
  void run() {}
};
#else
S7 s7;
// expected-error@second.h:* {{'TemplateArgument::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with no template arguments}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with template arguments}}
#endif

#if defined(FIRST)
struct S8 {
  static int a, b;
  template<int&> void run() {}
  template<int&, int&> void run() {}
  template<> void run<a>() {}
};
#elif defined(SECOND)
struct S8 {
  static int a, b;
  template<int&> void run() {}
  template<int&, int&> void run() {}
  template<> void run<a, b>() {}
};
#else
S8 s8;
// expected-error@second.h:* {{'TemplateArgument::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 2 template arguments}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 1 template argument}}
#endif

#if defined(FIRST)
struct S9 {
  static int a, b;
  template<int&> void run() {}
  template<> void run<a>() {}
};
#elif defined(SECOND)
struct S9 {
  static int a, b;
  template<int&> void run() {}
  template<> void run<b>() {}
};
#else
S9 s9;
// expected-error@second.h:* {{'TemplateArgument::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 'b' for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 'a' for 1st template argument}}
#endif

#if defined(FIRST)
struct S10 {
  static int a, b;
  template<int, int&...> void run() {}
  template<> void run<1, a>() {}
};
#elif defined(SECOND)
struct S10 {
  static int a, b;
  template<int, int&...> void run() {}
  template<> void run<1, b>() {}
};
#else
S10 s10;
// expected-error@second.h:* {{'TemplateArgument::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 'b' for 2nd template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 'a' for 2nd template argument}}
#endif

#if defined(FIRST)
struct S11 {
  static int a, b;
  template<int, int&...> void run() {}
  template<> void run<1, a>() {}
};
#elif defined(SECOND)
struct S11 {
  static int a, b;
  template<int, int&...> void run() {}
  template<> void run<1, a, a>() {}
};
#else
S11 s11;
// expected-error@second.h:* {{'TemplateArgument::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'run' with 3 template arguments}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'run' with 2 template arguments}}
#endif

#define DECLS                   \
  OneClass<int> a;              \
  OneInt<1> b;                  \
  using c = OneClass<float>;    \
  using d = OneInt<2>;          \
  using e = OneInt<2 + 2>;      \
  OneTemplateClass<OneClass> f; \
  OneTemplateInt<OneInt> g;     \
  static int i1, i2;            \
  template <int &>              \
  void Function() {}            \
  template <int &, int &>       \
  void Function() {}            \
  template <>                   \
  void Function<i1>() {}        \
  template <>                   \
  void Function<i2>() {}        \
  template <>                   \
  void Function<i1, i2>() {}    \
  template <>                   \
  void Function<i2, i1>() {}

#if defined(FIRST) || defined(SECOND)
template <class> struct OneClass{};
template <int> struct OneInt{};
template <template <class> class> struct OneTemplateClass{};
template <template <int> class> struct OneTemplateInt{};
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
DECLS
ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'TemplateArgument::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace TemplateArgument

namespace TemplateTypeParmType {
#if defined(FIRST)
template <class T1, class T2>
struct S1 {
  T1 x;
};
#elif defined(SECOND)
template <class T1, class T2>
struct S1 {
  T2 x;
};
#else
using TemplateTypeParmType::S1;
// expected-error@first.h:* {{'TemplateTypeParmType::S1::x' from module 'FirstModule' is not present in definition of 'S1<T1, T2>' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
template <int ...Ts>
struct U2 {};
template <int T, int U>
class S2 {
  typedef U2<U, T> type;
  type x;
};
#elif defined(SECOND)
template <int ...Ts>
struct U2 {};
template <int T, int U>
class S2 {
  typedef U2<T, U> type;
  type x;
};
#else
using TemplateTypeParmType::S2;
// expected-error@first.h:* {{'TemplateTypeParmType::S2::x' from module 'FirstModule' is not present in definition of 'S2<T, U>' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
// expected-error@first.h:* {{'TemplateTypeParmType::S2::type' from module 'FirstModule' is not present in definition of 'S2<T, U>' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'type' does not match}}
#endif

#define DECLS            \
  T t;                   \
  U u;                   \
  ParameterPack<T> a;    \
  ParameterPack<T, U> b; \
  ParameterPack<U> c;    \
  ParameterPack<U, T> d;

#if defined(FIRST) || defined(SECOND)
template <class ...Ts> struct ParameterPack {};
#endif

#if defined(FIRST) || defined(SECOND)
template <class T, class U>
struct Valid1 {
  DECLS
};
#else
using TemplateTypeParmType::Valid1;
#endif

#if defined(FIRST) || defined(SECOND)
template <class T, class U>
struct Invalid1 {
  DECLS
  ACCESS
};
#else
using TemplateTypeParmType::Invalid1;
// expected-error@second.h:* {{'TemplateTypeParmType::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace TemplateTypeParmType

namespace VarDecl {
#if defined(FIRST)
struct S1 {
  static int x;
  static int y;
};
#elif defined(SECOND)
struct S1 {
  static int y;
  static int x;
};
#else
S1 s1;
// expected-error@second.h:* {{'VarDecl::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found data member with name 'y'}}
// expected-note@first.h:* {{but in 'FirstModule' found data member with name 'x'}}
#endif

#if defined(FIRST)
struct S2 {
  static int x;
};
#elif defined(SECOND)
using I = int;
struct S2 {
  static I x;
};
#else
S2 s2;
// expected-error@second.h:* {{'VarDecl::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found data member 'x' with type 'VarDecl::I' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found data member 'x' with different type 'int'}}
#endif

#if defined(FIRST)
struct S3 {
  static const int x = 1;
};
#elif defined(SECOND)
struct S3 {
  static const int x;
};
#else
S3 s3;
// expected-error@second.h:* {{'VarDecl::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found data member 'x' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found data member 'x' without an initializer}}
#endif

#if defined(FIRST)
struct S4 {
  static const int x = 1;
};
#elif defined(SECOND)
struct S4 {
  static const int x = 2;
};
#else
S4 s4;
// expected-error@second.h:* {{'VarDecl::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found data member 'x' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found data member 'x' with a different initializer}}
#endif

#if defined(FIRST)
struct S5 {
  static const int x = 1;
};
#elif defined(SECOND)
struct S5 {
  static constexpr int x = 1;
};
#else
S5 s5;
// expected-error@second.h:* {{'VarDecl::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found data member 'x' is not constexpr}}
// expected-note@first.h:* {{but in 'FirstModule' found data member 'x' is constexpr}}
#endif

#if defined(FIRST)
struct S6 {
  static const int x = 1;
};
#elif defined(SECOND)
struct S6 {
  static const int y = 1;
};
#else
S6 s6;
// expected-error@first.h:* {{'VarDecl::S6::x' from module 'FirstModule' is not present in definition of 'VarDecl::S6' in module 'SecondModule'}}
// expected-note@second.h:* {{definition has no member 'x'}}
#endif

#if defined(FIRST)
struct S7 {
  static const int x = 1;
};
#elif defined(SECOND)
struct S7 {
  static const unsigned x = 1;
};
#else
S7 s7;
// expected-error@first.h:* {{'VarDecl::S7::x' from module 'FirstModule' is not present in definition of 'VarDecl::S7' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
struct S8 {
public:
  static const int x = 1;
};
#elif defined(SECOND)
struct S8 {
  static const int x = 1;
public:
};
#else
S8 s8;
// expected-error@second.h:* {{'VarDecl::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found data member}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif

#if defined(FIRST)
struct S9 {
  static const int x = 1;
};
#elif defined(SECOND)
struct S9 {
  static int x;
};
#else
S9 s9;
// expected-error@first.h:* {{'VarDecl::S9::x' from module 'FirstModule' is not present in definition of 'VarDecl::S9' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#define DECLS             \
  static int a;           \
  static I b;             \
  static const int c = 1; \
  static constexpr int d = 5;

#if defined(FIRST) || defined(SECOND)
using I = int;
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'VarDecl::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace VarDecl

namespace Friend {
#if defined(FIRST)
struct T1 {};
struct S1 {
  friend class T1;
};
#elif defined(SECOND)
struct T1 {};
struct S1 {
  friend T1;
};
#else
S1 s1;
// expected-error@second.h:* {{'Friend::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T1'}}
// expected-note@first.h:* {{but in 'FirstModule' found friend 'class T1'}}
#endif

#if defined(FIRST)
struct T2 {};
struct S2 {
  friend class T2;
};
#elif defined(SECOND)
struct T2 {};
struct S2 {
  friend struct T2;
};
#else
S2 s2;
// expected-error@second.h:* {{'Friend::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'struct T2'}}
// expected-note@first.h:* {{but in 'FirstModule' found friend 'class T2'}}
#endif

#if defined(FIRST)
struct T3 {};
struct S3 {
  friend const T3;
};
#elif defined(SECOND)
struct T3 {};
struct S3 {
  friend T3;
};
#else
S3 s3;
// expected-error@second.h:* {{'Friend::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T3'}}
// expected-note@first.h:* {{but in 'FirstModule' found friend 'const Friend::T3'}}
#endif

#if defined(FIRST)
struct T4 {};
struct S4 {
  friend T4;
};
#elif defined(SECOND)
struct S4 {
  friend void T4();
};
#else
S4 s4;
// expected-error@second.h:* {{'Friend::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend function}}
// expected-note@first.h:* {{but in 'FirstModule' found friend class}}
#endif

#if defined(FIRST)
struct S5 {
  friend void T5a();
};
#elif defined(SECOND)
struct S5 {
  friend void T5b();
};
#else
S5 s5;
// expected-error@second.h:* {{'Friend::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend function 'T5b'}}
// expected-note@first.h:* {{but in 'FirstModule' found friend function 'T5a'}}
#endif

#define DECLS            \
  friend class FriendA;  \
  friend struct FriendB; \
  friend FriendC;        \
  friend const FriendD;  \
  friend void Function();

#if defined(FIRST) || defined(SECOND)
class FriendA {};
class FriendB {};
class FriendC {};
class FriendD {};
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'Friend::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace Friend

namespace TemplateParameters {
#if defined(FIRST)
template <class A>
struct S1 {};
#elif defined(SECOND)
template <class B>
struct S1 {};
#else
using TemplateParameters::S1;
// expected-error@second.h:* {{'TemplateParameters::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found template parameter 'B'}}
// expected-note@first.h:* {{but in 'FirstModule' found template parameter 'A'}}
#endif

#if defined(FIRST)
template <class A = double>
struct S2 {};
#elif defined(SECOND)
template <class A = int>
struct S2 {};
#else
using TemplateParameters::S2;
// expected-error@second.h:* {{'TemplateParameters::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found template parameter with default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found template parameter with different default argument}}
#endif

#if defined(FIRST)
template <class A = int>
struct S3 {};
#elif defined(SECOND)
template <class A>
struct S3 {};
#else
using TemplateParameters::S3;
// expected-error@second.h:* {{'TemplateParameters::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found template parameter with no default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found template parameter with default argument}}
#endif

#if defined(FIRST)
template <int A>
struct S4 {};
#elif defined(SECOND)
template <int A = 2>
struct S4 {};
#else
using TemplateParameters::S4;
// expected-error@second.h:* {{'TemplateParameters::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found template parameter with default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found template parameter with no default argument}}
#endif

#if defined(FIRST)
template <int> class S5_first {};
template <template<int> class A = S5_first>
struct S5 {};
#elif defined(SECOND)
template <int> class S5_second {};
template <template<int> class A = S5_second>
struct S5 {};
#else
using TemplateParameters::S5;
// expected-error@second.h:* {{'TemplateParameters::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found template parameter with default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found template parameter with different default argument}}
#endif

#if defined(FIRST)
template <class A>
struct S6 {};
#elif defined(SECOND)
template <class>
struct S6 {};
#else
using TemplateParameters::S6;
// expected-error@second.h:* {{'TemplateParameters::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found unnamed template parameter}}
// expected-note@first.h:* {{but in 'FirstModule' found template parameter 'A'}}
#endif

#define DECLS

#if defined(FIRST) || defined(SECOND)
template <class> class DefaultArg;
#endif

#if defined(FIRST) || defined(SECOND)
template <int, class, template <class> class,
          int A, class B, template <int> class C,
          int D = 1, class E = int, template <class F> class = DefaultArg>
struct Valid1 {
  DECLS
};
#else
using TemplateParameters::Valid1;
#endif

#if defined(FIRST) || defined(SECOND)
template <int, class, template <class> class,
          int A, class B, template <int> class C,
          int D = 1, class E = int, template <class F> class = DefaultArg>
struct Invalid1 {
  DECLS
  ACCESS
};
#else
using TemplateParameters::Invalid1;
// expected-error@second.h:* {{'TemplateParameters::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace TemplateParameters

namespace BaseClass {
#if defined(FIRST)
struct B1 {};
struct S1 : B1 {};
#elif defined(SECOND)
struct S1 {};
#else
S1 s1;
// expected-error@second.h:* {{'BaseClass::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found 0 base classes}}
// expected-note@first.h:* {{but in 'FirstModule' found 1 base class}}
#endif

#if defined(FIRST)
struct S2 {};
#elif defined(SECOND)
struct B2 {};
struct S2 : virtual B2 {};
#else
S2 s2;
// expected-error@second.h:* {{'BaseClass::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1 base class}}
// expected-note@first.h:* {{but in 'FirstModule' found 0 base classes}}
#endif

#if defined(FIRST)
struct B3a {};
struct S3 : B3a {};
#elif defined(SECOND)
struct B3b {};
struct S3 : virtual B3b {};
#else
S3 s3;
// expected-error@second.h:* {{'BaseClass::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1 virtual base class}}
// expected-note@first.h:* {{but in 'FirstModule' found 0 virtual base classes}}
#endif

#if defined(FIRST)
struct B4a {};
struct S4 : B4a {};
#elif defined(SECOND)
struct B4b {};
struct S4 : B4b {};
#else
S4 s4;
// expected-error@second.h:* {{'BaseClass::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1st base class with type 'BaseClass::B4b'}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class with different type 'BaseClass::B4a'}}
#endif

#if defined(FIRST)
struct B5a {};
struct S5 : virtual B5a {};
#elif defined(SECOND)
struct B5a {};
struct S5 : B5a {};
#else
S5 s5;
// expected-error@second.h:* {{'BaseClass::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found 0 virtual base classes}}
// expected-note@first.h:* {{but in 'FirstModule' found 1 virtual base class}}
#endif

#if defined(FIRST)
struct B6a {};
struct S6 : B6a {};
#elif defined(SECOND)
struct B6a {};
struct S6 : virtual B6a {};
#else
S6 s6;
// expected-error@second.h:* {{'BaseClass::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1 virtual base class}}
// expected-note@first.h:* {{but in 'FirstModule' found 0 virtual base classes}}
#endif

#if defined(FIRST)
struct B7a {};
struct S7 : protected B7a {};
#elif defined(SECOND)
struct B7a {};
struct S7 : B7a {};
#else
S7 s7;
// expected-error@second.h:* {{'BaseClass::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1st base class 'BaseClass::B7a' with no access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class 'BaseClass::B7a' with protected access specifier}}
#endif

#if defined(FIRST)
struct B8a {};
struct S8 : public B8a {};
#elif defined(SECOND)
struct B8a {};
struct S8 : private B8a {};
#else
S8 s8;
// expected-error@second.h:* {{'BaseClass::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1st base class 'BaseClass::B8a' with private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class 'BaseClass::B8a' with public access specifier}}
#endif

#if defined(FIRST)
struct B9a {};
struct S9 : private B9a {};
#elif defined(SECOND)
struct B9a {};
struct S9 : public B9a {};
#else
S9 s9;
// expected-error@second.h:* {{'BaseClass::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1st base class 'BaseClass::B9a' with public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class 'BaseClass::B9a' with private access specifier}}
#endif

#if defined(FIRST)
struct B10a {};
struct S10 : B10a {};
#elif defined(SECOND)
struct B10a {};
struct S10 : protected B10a {};
#else
S10 s10;
// expected-error@second.h:* {{'BaseClass::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found 1st base class 'BaseClass::B10a' with protected access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class 'BaseClass::B10a' with no access specifier}}
#endif

#define DECLS

#if defined(FIRST) || defined(SECOND)
struct Base1 {};
struct Base2 {};
struct Base3 {};
struct Base4 {};
struct Base5 {};
#endif

#if defined(FIRST) || defined(SECOND)
struct Valid1 :
  Base1, virtual Base2, protected Base3, public Base4, private Base5 {

  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 :
  Base1, virtual Base2, protected Base3, public Base4, private Base5 {

  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'BaseClass::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace BaseClass

namespace PointersAndReferences {
#if defined(FIRST) || defined(SECOND)
template<typename> struct Wrapper{};
#endif

#if defined(FIRST)
struct S1 {
  Wrapper<int*> x;
};
#elif defined(SECOND)
struct S1 {
  Wrapper<float*> x;
};
#else
S1 s1;
// expected-error@first.h:* {{PointersAndReferences::S1::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
struct S2 {
  Wrapper<int &&> x;
};
#elif defined(SECOND)
struct S2 {
  Wrapper<float &&> x;
};
#else
S2 s2;
// expected-error@first.h:* {{PointersAndReferences::S2::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S2' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
struct S3 {
  Wrapper<int *> x;
};
#elif defined(SECOND)
struct S3 {
  Wrapper<float *> x;
};
#else
S3 s3;
// expected-error@first.h:* {{PointersAndReferences::S3::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S3' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
struct S4 {
  Wrapper<int &> x;
};
#elif defined(SECOND)
struct S4 {
  Wrapper<float &> x;
};
#else
S4 s4;
// expected-error@first.h:* {{PointersAndReferences::S4::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S4' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
struct S5 {
  Wrapper<S5 *> x;
};
#elif defined(SECOND)
struct S5 {
  Wrapper<const S5 *> x;
};
#else
S5 s5;
// expected-error@second.h:* {{'PointersAndReferences::S5::x' from module 'SecondModule' is not present in definition of 'PointersAndReferences::S5' in module 'FirstModule'}}
// expected-note@first.h:* {{declaration of 'x' does not match}}
#endif

#if defined(FIRST)
struct S6 {
  Wrapper<int &> x;
};
#elif defined(SECOND)
struct S6 {
  Wrapper<const int &> x;
};
#else
S6 s6;
// expected-error@first.h:* {{PointersAndReferences::S6::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S6' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'x' does not match}}
#endif

#define DECLS                \
  Wrapper<int *> x1;         \
  Wrapper<float *> x2;       \
  Wrapper<const float *> x3; \
  Wrapper<int &> x4;         \
  Wrapper<int &&> x5;        \
  Wrapper<const int &> x6;   \
  Wrapper<S1 *> x7;          \
  Wrapper<S1 &> x8;          \
  Wrapper<S1 &&> x9;

#if defined(FIRST) || defined(SECOND)
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'PointersAndReferences::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}  // namespace PointersAndReferences

namespace FunctionTemplate {
#if defined(FIRST)
struct S1 {
  template <int, int> void foo();
};
#elif defined(SECOND)
struct S1 {
  template <int> void foo();
};
#else
S1 s1;
// expected-error@first.h:* {{'FunctionTemplate::S1::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'foo' does not match}}
#endif

#if defined(FIRST)
struct S2 {
  template <char> void foo();
};
#elif defined(SECOND)
struct S2 {
  template <int> void foo();
};
#else
S2 s2;
// expected-error@first.h:* {{'FunctionTemplate::S2::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S2' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'foo' does not match}}
#endif

#if defined(FIRST)
struct S3 {
  template <int x> void foo();
};
#elif defined(SECOND)
struct S3 {
  template <int y> void foo();
};
#else
S3 s3;
// expected-error@second.h:* {{'FunctionTemplate::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter named 'y'}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}}
#endif

#if defined(FIRST)
struct S4 {
  template <int x> void foo();
};
#elif defined(SECOND)
struct S4 {
  template <int x> void bar();
};
#else
S4 s4;
// expected-error@first.h:* {{'FunctionTemplate::S4::foo' from module 'FirstModule' is not present in definition of 'FunctionTemplate::S4' in module 'SecondModule'}}
// expected-note@second.h:* {{definition has no member 'foo'}}
#endif

#if defined(FIRST)
struct S5 {
  template <int x> void foo();
};
#elif defined(SECOND)
struct S5 {
 public:
  template <int x> void foo();
};
#else
S5 s5;
// expected-error@second.h:* {{'FunctionTemplate::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found function template}}
#endif

#if defined(FIRST)
struct S6 {
  template <typename x = int> void foo();
};
#elif defined(SECOND)
struct S6 {
  template <typename x> void foo();
};
#else
S6 s6;
// expected-error@second.h:* {{'FunctionTemplate::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
#endif

#if defined(FIRST)
struct S7 {
  template <typename x = void> void foo();
};
#elif defined(SECOND)
struct S7 {
  template <typename x = int> void foo();
};
#else
S7 s7;
// expected-error@second.h:* {{'FunctionTemplate::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'int'}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'void'}}
#endif

#if defined(FIRST)
template <int>
struct U8 {};
struct S8 {
  template <template<int> class x = U8> void foo();
};
#elif defined(SECOND)
template <int>
struct T8 {};
struct S8{
  template <template<int> class x = T8> void foo();
};
#else
S8 s8;
// expected-error@second.h:* {{'FunctionTemplate::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'T8'}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'U8'}}
#endif

#if defined(FIRST)
template <int>
struct U9 {};
struct S9 { S9();
  template <template<int> class x = U9> void foo();
};
#elif defined(SECOND)
struct S9 { S9();
  template <template<int> class x> void foo();
};
#else
S9 s9;
// expected-error@second.h:* {{'FunctionTemplate::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
#endif

#if defined(FIRST)
struct S10 {
  template <template<int> class x> void foo();
  template <template<typename> class x> void foo();
};
#elif defined(SECOND)
struct S10 {
  template <template<typename> class x> void foo();
  template <template<int> class x> void foo();
};
#else
S10 s10;
// expected-error@second.h:* {{'FunctionTemplate::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}}
#endif

#if defined(FIRST)
struct S11 {
  template <template<int> class x> void foo();
};
#elif defined(SECOND)
struct S11 {
  template <template<int> class> void foo();
};
#else
S11 s11;
// expected-error@second.h:* {{'FunctionTemplate::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no name}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter named 'x'}}
#endif

#if defined(FIRST)
struct S12 {
  template <class> void foo();
  template <class, class> void foo();
};
#elif defined(SECOND)
struct S12 {
  template <class, class> void foo();
  template <class> void foo();
};
#else
S12 s12;
// expected-error@second.h:* {{'FunctionTemplate::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 2 template parameters}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1 template parameter}}
#endif

#if defined(FIRST)
struct S13 {
  template <class = int> void foo();
};
#elif defined(SECOND)
struct S13 {
  template <class = void> void foo();
};
#else
S13 s13;
// expected-error@second.h:* {{'FunctionTemplate::S13' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 'void'}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 'int'}}
#endif

#if defined(FIRST)
struct S14 {
  template <class = void> void foo();
};
#elif defined(SECOND)
struct S14 {
  template <class> void foo();
};
#else
S14 s14;
// expected-error@second.h:* {{'FunctionTemplate::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with no default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument}}
#endif

#if defined(FIRST)
struct S15 {
  template <class> void foo();
};
#elif defined(SECOND)
struct S15 {
  template <class = void> void foo();
};
#else
S15 s15;
// expected-error@second.h:* {{'FunctionTemplate::S15' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}}
#endif

#if defined(FIRST)
struct S16 {
  template <short> void foo();
};
#elif defined(SECOND)
struct S16 {
  template <short = 1> void foo();
};
#else
S16 s16;
// expected-error@second.h:* {{'FunctionTemplate::S16' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with no default argument}}
#endif

#if defined(FIRST)
struct S17 {
  template <short = 2> void foo();
};
#elif defined(SECOND)
struct S17 {
  template <short = 1 + 1> void foo();
};
#else
S17 s17;
// expected-error@second.h:* {{'FunctionTemplate::S17' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with default argument 1 + 1}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with default argument 2}}
#endif

#if defined(FIRST)
struct S18 {
  template <short> void foo();
  template <int> void foo();
};
#elif defined(SECOND)
struct S18 {
  template <int> void foo();
  template <short> void foo();
};
#else
S18 s18;
// expected-error@second.h:* {{'FunctionTemplate::S18' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter with one type}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter with different type}}
#endif

#if defined(FIRST)
struct S19 {
  template <short> void foo();
  template <short...> void foo();
};
#elif defined(SECOND)
struct S19 {
  template <short...> void foo();
  template <short> void foo();
};
#else
S19 s19;
// expected-error@second.h:* {{'FunctionTemplate::S19' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
#endif

#if defined(FIRST)
struct S20 {
  template <class> void foo();
  template <class...> void foo();
};
#elif defined(SECOND)
struct S20 {
  template <class...> void foo();
  template <class> void foo();
};
#else
S20 s20;
// expected-error@second.h:* {{'FunctionTemplate::S20' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
#endif

#if defined(FIRST)
struct S21 {
  template <template<class> class...> void foo();
  template <template<class> class> void foo();
};
#elif defined(SECOND)
struct S21 {
  template <template<class> class> void foo();
  template <template<class> class...> void foo();
};
#else
S21 s21;
// expected-error@second.h:* {{'FunctionTemplate::S21' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter not being a template parameter pack}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template parameter being a template parameter pack}}
#endif

#if defined(FIRST)
struct S22 {
  template <template<class> class> void foo();
  template <class> void foo();
  template <int> void foo();
};
#elif defined(SECOND)
struct S22 {
  template <class> void foo();
  template <int> void foo();
  template <template<class> class> void foo();
};
#else
S22 s22;
// expected-error@second.h:* {{'FunctionTemplate::S22' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a type template parameter}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a template template parameter}}
#endif

#if defined(FIRST)
struct S23 {
  template <class> void foo();
  template <int> void foo();
  template <template<class> class> void foo();
};
#elif defined(SECOND)
struct S23 {
  template <int> void foo();
  template <template<class> class> void foo();
  template <class> void foo();
};
#else
S23 s23;
// expected-error@second.h:* {{'FunctionTemplate::S23' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a non-type template parameter}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a type template parameter}}
#endif

#if defined(FIRST)
struct S24 {
  template <int> void foo();
  template <template<class> class> void foo();
  template <class> void foo();
};
#elif defined(SECOND)
struct S24 {
  template <template<class> class> void foo();
  template <class> void foo();
  template <int> void foo();
};
#else
S24 s24;
// expected-error@second.h:* {{'FunctionTemplate::S24' has different definitions in different modules; first difference is definition in module 'SecondModule' found function template 'foo' with 1st template parameter being a template template parameter}}
// expected-note@first.h:* {{but in 'FirstModule' found function template 'foo' with 1st template paramter being a non-type template parameter}}
#endif

#if defined(FIRST)
struct S25 {
  template <int> void foo();
};
#elif defined(SECOND)
struct S25 {
 public:
  template <int> void foo();
};
#else
S25 s25;
// expected-error@second.h:* {{'FunctionTemplate::S25' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found function template}}
#endif

#define DECLS                                           \
  template <int>                                        \
  void nontype1();                                      \
  template <int x>                                      \
  void nontype2();                                      \
  template <int, int>                                   \
  void nontype3();                                      \
  template <int x = 5>                                  \
  void nontype4();                                      \
  template <int... x>                                   \
  void nontype5();                                      \
                                                        \
  template <class>                                      \
  void type1();                                         \
  template <class x>                                    \
  void type2();                                         \
  template <class, class>                               \
  void type3();                                         \
  template <class x = int>                              \
  void type4();                                         \
  template <class... x>                                 \
  void type5();                                         \
                                                        \
  template <template <int> class>                       \
  void template1();                                     \
  template <template <int> class x>                     \
  void template2();                                     \
  template <template <int> class, template <int> class> \
  void template3();                                     \
  template <template <int> class x = U>                 \
  void template4();                                     \
  template <template <int> class... x>                  \
  void template5();

#if defined(FIRST) || defined(SECOND)
template<int>
struct U {};
struct Valid1 {
  DECLS
};
#else
Valid1 v1;
#endif

#if defined(FIRST) || defined(SECOND)
struct Invalid1 {
  DECLS
  ACCESS
};
#else
Invalid1 i1;
// expected-error@second.h:* {{'FunctionTemplate::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
#undef DECLS
}

namespace Enums {
#if defined(FIRST)
enum E1 { x11 };
#elif defined(SECOND)
enum E1 {};
#else
E1 e1;
// expected-error@first.h:* {{'Enums::x11' from module 'FirstModule' is not present in definition of 'Enums::E1' in module 'SecondModule'}}
// expected-note@second.h:* {{definition has no member 'x11'}}
#endif

#if defined(FIRST)
enum E2 {};
#elif defined(SECOND)
enum E2 { x21 };
#else
E2 e2;
// expected-error@second.h:* {{'Enums::E2' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with 1 element}}
// expected-note@first.h:* {{but in 'FirstModule' found enum with 0 elements}}
#endif

#if defined(FIRST)
enum E3 { x31 };
#elif defined(SECOND)
enum E3 { x32 };
#else
E3 e3;
// expected-error@first.h:* {{'Enums::x31' from module 'FirstModule' is not present in definition of 'Enums::E3' in module 'SecondModule'}}
// expected-note@second.h:* {{definition has no member 'x31'}}
#endif

#if defined(FIRST)
enum E4 { x41 };
#elif defined(SECOND)
enum E4 { x41, x42 };
#else
E4 e4;
// expected-error@second.h:* {{'Enums::E4' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with 2 elements}}
// expected-note@first.h:* {{but in 'FirstModule' found enum with 1 element}}
#endif

#if defined(FIRST)
enum E5 { x51, x52 };
#elif defined(SECOND)
enum E5 { x51 };
#else
E5 e5;
// expected-error@first.h:* {{'Enums::x52' from module 'FirstModule' is not present in definition of 'Enums::E5' in module 'SecondModule'}}
// expected-note@second.h:* {{definition has no member 'x52'}}
#endif

#if defined(FIRST)
enum E6 { x61, x62 };
#elif defined(SECOND)
enum E6 { x62, x61 };
#else
E6 e6;
// expected-error@second.h:* {{'Enums::E6' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element has name 'x62'}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st element has name 'x61'}}
#endif

#if defined(FIRST)
enum E7 { x71 = 0 };
#elif defined(SECOND)
enum E7 { x71 };
#else
E7 e7;
// expected-error@second.h:* {{'Enums::E7' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element 'x71' has an initilizer}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x71' does not have an initializer}}
#endif

#if defined(FIRST)
enum E8 { x81 };
#elif defined(SECOND)
enum E8 { x81 = 0 };
#else
E8 e8;
// expected-error@second.h:* {{'Enums::E8' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st element 'x81' does not have an initilizer}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st element 'x81' has an initializer}}
#endif

#if defined(FIRST)
enum E9 { x91 = 0, x92 = 1 };
#elif defined(SECOND)
enum E9 { x91 = 0, x92 = 2 - 1 };
#else
E9 e9;
// expected-error@second.h:* {{'Enums::E9' has different definitions in different modules; definition in module 'SecondModule' first difference is 2nd element 'x92' has an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found 2nd element 'x92' has different initializer}}
#endif

#if defined(FIRST)
enum class E10 : int {};
#elif defined(SECOND)
enum class E10 {};
#else
E10 e10;
// expected-error@second.h:* {{'Enums::E10' has different definitions in different modules; definition in module 'SecondModule' first difference is enum without specified type}}
// expected-note@first.h:* {{but in 'FirstModule' found enum with specified type}}
#endif

#if defined(FIRST)
enum E11 {};
#elif defined(SECOND)
enum E11 : int {};
#else
E11 e11;
// expected-error@second.h:* {{'Enums::E11' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with specified type}}
// expected-note@first.h:* {{but in 'FirstModule' found enum without specified type}}
#endif

#if defined(FIRST)
enum struct E12 : long {};
#elif defined(SECOND)
enum struct E12 : int {};
#else
E12 e12;
// expected-error@second.h:* {{'Enums::E12' has different definitions in different modules; definition in module 'SecondModule' first difference is enum with specified type 'int'}}
// expected-note@first.h:* {{but in 'FirstModule' found enum with specified type 'long'}}
#endif

#if defined(FIRST)
enum struct E13 {};
#elif defined(SECOND)
enum E13 {};
#else
E13 e13;
// expected-error@second.h:* {{'Enums::E13' has different definitions in different modules; definition in module 'SecondModule' first difference is enum that is not scoped}}
// expected-note@first.h:* {{but in 'FirstModule' found enum that is scoped}}
#endif

#if defined(FIRST)
enum E14 {};
#elif defined(SECOND)
enum struct E14 {};
#else
E14 e14;
// expected-error@second.h:* {{'Enums::E14' has different definitions in different modules; definition in module 'SecondModule' first difference is enum that is scoped}}
// expected-note@first.h:* {{but in 'FirstModule' found enum that is not scoped}}
#endif

#if defined(FIRST)
enum class E15 {};
#elif defined(SECOND)
enum struct E15 {};
#else
E15 e15;
// expected-error@second.h:* {{'Enums::E15' has different definitions in different modules; definition in module 'SecondModule' first difference is enum scoped with keyword struct}}
// expected-note@first.h:* {{but in 'FirstModule' found enum scoped with keyword class}}
#endif

#if defined(FIRST)
enum struct E16 {};
#elif defined(SECOND)
enum class E16 {};
#else
E16 e16;
// expected-error@second.h:* {{'Enums::E16' has different definitions in different modules; definition in module 'SecondModule' first difference is enum scoped with keyword class}}
// expected-note@first.h:* {{but in 'FirstModule' found enum scoped with keyword struct}}
#endif

#if defined(FIRST)
enum Valid { v1 = (struct S*)0 == (struct S*)0 };
#elif defined(SECOND)
struct S {};
enum Valid { v1 = (struct S*)0 == (struct S*)0 };
#else
Valid V;
#endif
}  // namespace Enums

// Collection of interesting cases below.

// Naive parsing of AST can lead to cycles in processing.  Ensure
// self-references don't trigger an endless cycles of AST node processing.
namespace SelfReference {
#if defined(FIRST)
template <template <int> class T> class Wrapper {};

template <int N> class S {
  S(Wrapper<::SelfReference::S> &Ref) {}
};

struct Xx {
  struct Yy {
  };
};

Xx::Xx::Xx::Yy yy;

namespace NNS {
template <typename> struct Foo;
template <template <class> class T = NNS::Foo>
struct NestedNamespaceSpecifier {};
}
#endif
}  // namespace SelfReference

namespace FriendFunction {
#if defined(FIRST)
void F(int = 0);
struct S { friend void F(int); };
#elif defined(SECOND)
void F(int);
struct S { friend void F(int); };
#else
S s;
#endif

#if defined(FIRST)
void G(int = 0);
struct T {
  friend void G(int);

  private:
};
#elif defined(SECOND)
void G(int);
struct T {
  friend void G(int);

  public:
};
#else
T t;
// expected-error@second.h:* {{'FriendFunction::T' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found private access specifier}}
#endif
}  // namespace FriendFunction

namespace ImplicitDecl {
#if defined(FIRST)
struct S { };
void S_Constructors() {
  // Trigger creation of implicit contructors
  S foo;
  S bar = foo;
  S baz(bar);
}
#elif defined(SECOND)
struct S { };
#else
S s;
#endif

#if defined(FIRST)
struct T {
  private:
};
void T_Constructors() {
  // Trigger creation of implicit contructors
  T foo;
  T bar = foo;
  T baz(bar);
}
#elif defined(SECOND)
struct T {
  public:
};
#else
T t;
// expected-error@first.h:* {{'ImplicitDecl::T' has different definitions in different modules; first difference is definition in module 'FirstModule' found private access specifier}}
// expected-note@second.h:* {{but in 'SecondModule' found public access specifier}}
#endif

}  // namespace ImplicitDecl

namespace TemplatedClass {
#if defined(FIRST)
template <class>
struct S {};
#elif defined(SECOND)
template <class>
struct S {};
#else
S<int> s;
#endif

#if defined(FIRST)
template <class>
struct T {
  private:
};
#elif defined(SECOND)
template <class>
struct T {
  public:
};
#else
T<int> t;
// expected-error@second.h:* {{'TemplatedClass::T' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found private access specifier}}
#endif
}  // namespace TemplatedClass

namespace TemplateClassWithField {
#if defined(FIRST)
template <class A>
struct S {
  A a;
};
#elif defined(SECOND)
template <class A>
struct S {
  A a;
};
#else
S<int> s;
#endif

#if defined(FIRST)
template <class A>
struct T {
  A a;

  private:
};
#elif defined(SECOND)
template <class A>
struct T {
  A a;

  public:
};
#else
T<int> t;
// expected-error@second.h:* {{'TemplateClassWithField::T' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found private access specifier}}
#endif
}  // namespace TemplateClassWithField

namespace TemplateClassWithTemplateField {
#if defined(FIRST)
template <class A>
class WrapperS;
template <class A>
struct S {
  WrapperS<A> a;
};
#elif defined(SECOND)
template <class A>
class WrapperS;
template <class A>
struct S {
  WrapperS<A> a;
};
#else
template <class A>
class WrapperS{};
S<int> s;
#endif

#if defined(FIRST)
template <class A>
class WrapperT;
template <class A>
struct T {
  WrapperT<A> a;

  public:
};
#elif defined(SECOND)
template <class A>
class WrapperT;
template <class A>
struct T {
  WrapperT<A> a;

  private:
};
#else
template <class A>
class WrapperT{};
T<int> t;
// expected-error@second.h:* {{'TemplateClassWithTemplateField::T' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
}  // namespace TemplateClassWithTemplateField

namespace EnumWithForwardDeclaration {
#if defined(FIRST)
enum E : int;
struct S {
  void get(E) {}
};
#elif defined(SECOND)
enum E : int { A, B };
struct S {
  void get(E) {}
};
#else
S s;
#endif

#if defined(FIRST)
struct T {
  void get(E) {}
  public:
};
#elif defined(SECOND)
struct T {
  void get(E) {}
  private:
};
#else
T t;
// expected-error@second.h:* {{'EnumWithForwardDeclaration::T' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
}  // namespace EnumWithForwardDeclaration

namespace StructWithForwardDeclaration {
#if defined(FIRST)
struct P {};
struct S {
  struct P *ptr;
};
#elif defined(SECOND)
struct S {
  struct P *ptr;
};
#else
S s;
#endif

#if defined(FIRST)
struct Q {};
struct T {
  struct Q *ptr;
  public:
};
#elif defined(SECOND)
struct T {
  struct Q *ptr;
  private:
};
#else
T t;
// expected-error@second.h:* {{'StructWithForwardDeclaration::T' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
}  // namespace StructWithForwardDeclaration

namespace StructWithForwardDeclarationNoDefinition {
#if defined(FIRST)
struct P;
struct S {
  struct P *ptr;
};
#elif defined(SECOND)
struct S {
  struct P *ptr;
};
#else
S s;
#endif

#if defined(FIRST)
struct Q;
struct T {
  struct Q *ptr;

  public:
};
#elif defined(SECOND)
struct T {
  struct Q *ptr;

  private:
};
#else
T t;
// expected-error@second.h:* {{'StructWithForwardDeclarationNoDefinition::T' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}}
#endif
}  // namespace StructWithForwardDeclarationNoDefinition

namespace LateParsedDefaultArgument {
#if defined(FIRST)
template <typename T>
struct S {
  struct R {
    void foo(T x = 0) {}
  };
};
#elif defined(SECOND)
#else
void run() {
  S<int>::R().foo();
}
#endif
}  // namespace LateParsedDefaultArgument

namespace LateParsedDefaultArgument {
#if defined(FIRST)
template <typename alpha> struct Bravo {
  void charlie(bool delta = false) {}
};
typedef Bravo<char> echo;
echo foxtrot;

Bravo<char> golf;
#elif defined(SECOND)
#else
#endif
}  // LateParsedDefaultArgument

namespace DifferentParameterNameInTemplate {
#if defined(FIRST) || defined(SECOND)
template <typename T>
struct S {
  typedef T Type;

  static void Run(const Type *name_one);
};

template <typename T>
void S<T>::Run(const T *name_two) {}

template <typename T>
struct Foo {
  ~Foo() { Handler::Run(nullptr); }
  Foo() {}

  class Handler : public S<T> {};

  void Get(typename Handler::Type *x = nullptr) {}
  void Add() { Handler::Run(nullptr); }
};
#endif

#if defined(FIRST)
struct Beta;

struct Alpha {
  Alpha();
  void Go() { betas.Get(); }
  Foo<Beta> betas;
};

#elif defined(SECOND)
struct Beta {};

struct BetaHelper {
  void add_Beta() { betas.Add(); }
  Foo<Beta> betas;
};

#else
Alpha::Alpha() {}
#endif
}  // DifferentParameterNameInTemplate

namespace ParameterTest {
#if defined(FIRST)
class X {};
template <typename G>
class S {
  public:
   typedef G Type;
   static inline G *Foo(const G *a, int * = nullptr);
};

template<typename G>
G* S<G>::Foo(const G* aaaa, int*) {}
#elif defined(SECOND)
template <typename G>
class S {
  public:
   typedef G Type;
   static inline G *Foo(const G *a, int * = nullptr);
};

template<typename G>
G* S<G>::Foo(const G* asdf, int*) {}
#else
S<X> s;
#endif
}  // ParameterTest

namespace MultipleTypedefs {
#if defined(FIRST)
typedef int B1;
typedef B1 A1;
struct S1 {
  A1 x;
};
#elif defined(SECOND)
typedef int A1;
struct S1 {
  A1 x;
};
#else
S1 s1;
#endif

#if defined(FIRST)
struct T2 { int x; };
typedef T2 B2;
typedef B2 A2;
struct S2 {
  T2 x;
};
#elif defined(SECOND)
struct T2 { int x; };
typedef T2 A2;
struct S2 {
  T2 x;
};
#else
S2 s2;
#endif

#if defined(FIRST)
using A3 = const int;
using B3 = volatile A3;
struct S3 {
  B3 x = 1;
};
#elif defined(SECOND)
using A3 = volatile const int;
using B3 = A3;
struct S3 {
  B3 x = 1;
};
#else
S3 s3;
#endif

#if defined(FIRST)
using A4 = int;
using B4 = A4;
struct S4 {
  B4 x;
};
#elif defined(SECOND)
using A4 = int;
using B4 = ::MultipleTypedefs::A4;
struct S4 {
  B4 x;
};
#else
S4 s4;
#endif

#if defined(FIRST)
using A5 = int;
using B5 = MultipleTypedefs::A5;
struct S5 {
  B5 x;
};
#elif defined(SECOND)
using A5 = int;
using B5 = ::MultipleTypedefs::A5;
struct S5 {
  B5 x;
};
#else
S5 s5;
#endif
}  // MultipleTypedefs

namespace DefaultArguments {
#if defined(FIRST)
template <typename T>
struct S {
  struct R {
    void foo(T x = 0);
  };
};
#elif defined(SECOND)
template <typename T>
struct S {
  struct R {
    void foo(T x = 1);
  };
};
#else
void run() {
  S<int>::R().foo();
}
// expected-error@second.h:* {{'DefaultArguments::S::R' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'foo' with 1st parameter with a default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'foo' with 1st parameter with a different default argument}}
#endif

#if defined(FIRST)
template <typename alpha> struct Bravo {
  void charlie(bool delta = false);
};
typedef Bravo<char> echo;
echo foxtrot;
#elif defined(SECOND)
template <typename alpha> struct Bravo {
  void charlie(bool delta = (false));
};
typedef Bravo<char> echo;
echo foxtrot;
#else
Bravo<char> golf;
// expected-error@second.h:* {{'DefaultArguments::Bravo' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'charlie' with 1st parameter with a default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'charlie' with 1st parameter with a different default argument}}
#endif
}  // namespace DefaultArguments

namespace FunctionDecl {
#if defined(FIRST)
struct S1 {};
S1 s1a;
#elif defined(SECOND)
struct S1 {};
#else
S1 s1;
#endif

#if defined(FIRST)
struct S2 {
  S2() = default;
};
S2 s2a = S2();
#elif defined(SECOND)
struct S2 {
  S2() = default;
};
#else
S2 s2;
#endif

#if defined(FIRST)
struct S3 {
  S3() = delete;
};
S3* s3c;
#elif defined(SECOND)
struct S3 {
  S3() = delete;
};
#else
S3* s3;
#endif

#if defined(FIRST) || defined(SECOND)
int F1(int x, float y = 2.7) { return 1; }
#else
int I1 = F1(1);
#endif

#if defined(FIRST)
int F2() { return 1; }
#elif defined(SECOND)
double F2() { return 1; }
#else
int I2 = F2();
// expected-error@-1 {{call to 'F2' is ambiguous}}
// expected-note@first.h:* {{candidate function}}
// expected-note@second.h:* {{candidate function}}
#endif

#if defined(FIRST)
int F3(float) { return 1; }
#elif defined(SECOND)
int F3(double) { return 1; }
#else
int I3 = F3(1);
// expected-error@-1 {{call to 'F3' is ambiguous}}
// expected-note@first.h:* {{candidate function}}
// expected-note@second.h:* {{candidate function}}
#endif

#if defined(FIRST)
int F4(int x) { return 1; }
#elif defined(SECOND)
int F4(int y) { return 1; }
#else
int I4 = F4(1);
// expected-error@second.h:* {{'FunctionDecl::F4' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with name 'y'}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with name 'x'}}
#endif

#if defined(FIRST)
int F5(int x) { return 1; }
#elif defined(SECOND)
int F5(int x = 1) { return 1; }
#else
int I5 = F6(1);
// expected-error@second.h:* {{'FunctionDecl::F5' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter without a default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with a default argument}}
#endif

#if defined(FIRST)
int F6(int x = 2) { return 1; }
#elif defined(SECOND)
int F6(int x = 1) { return 1; }
#else
int I6 = F6(1);
// expected-error@second.h:* {{'FunctionDecl::F6' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with a default argument}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with a different default argument}}
#endif

using I = int;
#if defined(FIRST)
I F7() { return 0; }
#elif defined(SECOND)
int F7() { return 0; }
#else
int I7 = F7();
// expected-error@second.h:* {{'FunctionDecl::F7' has different definitions in different modules; definition in module 'SecondModule' first difference is return type is 'int'}}
// expected-note@first.h:* {{but in 'FirstModule' found different return type 'FunctionDecl::I' (aka 'int')}}
#endif

#if defined(FIRST)
int F8(int) { return 0; }
#elif defined(SECOND)
int F8(I) { return 0; }
#else
int I8 = F8(1);
// expected-error@second.h:* {{'FunctionDecl::F8' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with type 'FunctionDecl::I' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with type 'int'}}
#endif

#if defined(FIRST)
int F9(int[1]) { return 0; }
#elif defined(SECOND)
int F9(int[2]) { return 0; }
#else
int I9 = F9(nullptr);
// expected-error@second.h:* {{'FunctionDecl::F9' has different definitions in different modules; definition in module 'SecondModule' first difference is 1st parameter with type 'int *' decayed from 'int [2]'}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st parameter with type 'int *' decayed from 'int [1]'}}
#endif

#if defined(FIRST)
int F10() { return 1; }
#elif defined(SECOND)
int F10() { return 2; }
#else
int I10 = F10();
#endif
// expected-error@second.h:* {{'FunctionDecl::F10' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
// expected-note@first.h:* {{but in 'FirstModule' found a different body}}

#if defined(FIRST)
struct S11 {
  template <int> void foo();
};
#elif defined(SECOND)
struct S11 {
  template <int> void foo();
};
template <int> void S11::foo() {}
#else
S11 s11;
#endif

#if defined(FIRST)
struct S12 {
  void foo(int x);
};
#elif defined(SECOND)
struct S12 {
  void foo(int x);
};
void S12::foo(int y) {}
#else
S12 s12;
#endif

#if defined(FIRST)
struct S13 {
  void foo(int x);
};
void S13::foo(int y) {}
#elif defined(SECOND)
struct S13 {
  void foo(int x);
};
void S13::foo(int y) {}
#else
S13 s13;
#endif
}  // namespace FunctionDecl

namespace DeclTemplateArguments {
#if defined(FIRST)
int foo() { return 1; }
int bar() { return foo(); }
#elif defined(SECOND)
template <class T = int>
int foo() { return 2; }
int bar() { return foo<>(); }
#else
int num = bar();
// expected-error@second.h:* {{'DeclTemplateArguments::bar' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
#endif
}

// Keep macros contained to one file.
#ifdef FIRST
#undef FIRST
#endif

#ifdef SECOND
#undef SECOND
#endif

#ifdef ACCESS
#undef ACCESS
#endif
