llvm-project/clang/test/Modules/odr_hash.cpp

1558 lines
39 KiB
C++
Raw Normal View History

// 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
// 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
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
} // 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
}
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
} // 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;
// TODO: This should produce an error.
#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;
// TODO: This should produce an error.
#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
} // namespace Method
// 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 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
} // 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
} // 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
}
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
}
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
}
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
}
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 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
}
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
}
// Interesting cases that should not cause errors. struct S should not error
// while struct T should error at the access specifier mismatch at the end.
namespace AllDecls {
#define CREATE_ALL_DECL_STRUCT(NAME, ACCESS) \
typedef int INT; \
struct NAME { \
public: \
private: \
protected: \
static_assert(1 == 1, "Message"); \
static_assert(2 == 2); \
\
int x; \
double y; \
\
INT z; \
\
unsigned a : 1; \
unsigned b : 2 * 2 + 5 / 2; \
\
mutable int c = sizeof(x + y); \
\
void method() {} \
static void static_method() {} \
virtual void virtual_method() {} \
virtual void pure_virtual_method() = 0; \
inline void inline_method() {} \
void volatile_method() volatile {} \
void const_method() const {} \
\
typedef int typedef_int; \
using using_int = int; \
\
void method_one_arg(int x) {} \
void method_one_arg_default_argument(int x = 5 + 5) {} \
void method_decayed_type(int x[5]) {} \
\
int constant_arr[5]; \
\
ACCESS: \
};
#if defined(FIRST)
CREATE_ALL_DECL_STRUCT(S, public)
#elif defined(SECOND)
CREATE_ALL_DECL_STRUCT(S, public)
#else
S *s;
#endif
#if defined(FIRST)
CREATE_ALL_DECL_STRUCT(T, private)
#elif defined(SECOND)
CREATE_ALL_DECL_STRUCT(T, public)
#else
T *t;
// expected-error@second.h:* {{'AllDecls::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 {
#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 ImplicitDelc
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 {
#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
}
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
}
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
}
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
}
// Keep macros contained to one file.
#ifdef FIRST
#undef FIRST
#endif
#ifdef SECOND
#undef SECOND
#endif