aboutsummaryrefslogtreecommitdiff
path: root/test/Modules/odr_hash.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/Modules/odr_hash.cpp')
-rw-r--r--test/Modules/odr_hash.cpp584
1 files changed, 565 insertions, 19 deletions
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index 16ddfefa53c7..e4c5ba6f82a8 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -25,7 +25,9 @@
// 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
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++1z \
+// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
+// RUN: -I%t/Inputs -verify %s
#if !defined(FIRST) && !defined(SECOND)
#include "first.h"
@@ -2244,22 +2246,6 @@ S2 s2;
#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;
@@ -2292,14 +2278,12 @@ S5 s5;
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)
@@ -3317,6 +3301,568 @@ Valid V;
#endif
} // namespace Enums
+namespace Types {
+namespace Complex {
+#if defined(FIRST)
+void invalid() {
+ _Complex float x;
+}
+void valid() {
+ _Complex float x;
+}
+#elif defined(SECOND)
+void invalid() {
+ _Complex double x;
+}
+void valid() {
+ _Complex float x;
+}
+#else
+auto function1 = invalid;
+// expected-error@second.h:* {{'Types::Complex::invalid' 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}}
+auto function2 = valid;
+#endif
+} // namespace Complex
+
+namespace Decltype {
+#if defined(FIRST)
+void invalid1() {
+ decltype(1 + 1) x;
+}
+int global;
+void invalid2() {
+ decltype(global) x;
+}
+void valid() {
+ decltype(1.5) x;
+ decltype(x) y;
+}
+#elif defined(SECOND)
+void invalid1() {
+ decltype(2) x;
+}
+float global;
+void invalid2() {
+ decltype(global) x;
+}
+void valid() {
+ decltype(1.5) x;
+ decltype(x) y;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::Decltype::invalid1' 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}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::Decltype::invalid2' 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}}
+auto function3 = valid;
+#endif
+} // namespace Decltype
+
+namespace Auto {
+#if defined(FIRST)
+void invalid1() {
+ decltype(auto) x = 1;
+}
+void invalid2() {
+ auto x = 1;
+}
+void invalid3() {
+ __auto_type x = 1;
+}
+void valid() {
+ decltype(auto) x = 1;
+ auto y = 1;
+ __auto_type z = 1;
+}
+#elif defined(SECOND)
+void invalid1() {
+ auto x = 1;
+}
+void invalid2() {
+ __auto_type x = 1;
+}
+void invalid3() {
+ decltype(auto) x = 1;
+}
+void valid() {
+ decltype(auto) x = 1;
+ auto y = 1;
+ __auto_type z = 1;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::Auto::invalid1' 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}}
+auto function2 = invalid3;
+// expected-error@second.h:* {{'Types::Auto::invalid2' 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}}
+auto function3 = invalid2;
+// expected-error@second.h:* {{'Types::Auto::invalid3' 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}}
+auto function4 = valid;
+#endif
+} // namespace Auto
+
+namespace DeducedTemplateSpecialization {
+#if defined(FIRST)
+template<typename T> struct A {};
+A() -> A<int>;
+template<typename T> struct B {};
+B() -> B<int>;
+
+void invalid1() {
+ A a{};
+}
+void invalid2() {
+ A a{};
+}
+void valid() {
+ B b{};
+}
+#elif defined(SECOND)
+template<typename T> struct A {};
+A() -> A<float>;
+template<typename T> struct B {};
+B() -> B<int>;
+
+void invalid1() {
+ A a{};
+}
+void invalid2() {
+ B a{};
+}
+void valid() {
+ B b{};
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid1' 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}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid2' 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}}
+auto function3 = valid;
+#endif
+} // namespace DeducedTemplateSpecialization
+
+namespace DependentAddressSpace {
+#if defined(FIRST)
+template <int A1, int A2>
+void invalid1() {
+ using type = int __attribute__((address_space(A1)));
+}
+template <int A1>
+void invalid2() {
+ using type = float __attribute__((address_space(A1)));
+}
+template <int A1, int A2>
+void valid() {
+ using type1 = float __attribute__((address_space(A1)));
+ using type2 = int __attribute__((address_space(A2)));
+ using type3 = int __attribute__((address_space(A1 + A2)));
+}
+#elif defined(SECOND)
+template <int A1, int A2>
+void invalid1() {
+ using type = int __attribute__((address_space(A2)));
+}
+template <int A1>
+void invalid2() {
+ using type = int __attribute__((address_space(A1)));
+}
+template <int A1, int A2>
+void valid() {
+ using type1 = float __attribute__((address_space(A1)));
+ using type2 = int __attribute__((address_space(A2)));
+ using type3 = int __attribute__((address_space(A1 + A2)));
+}
+#else
+template <int A, int B>
+class S {
+ static auto function1 = invalid1<A, B>;
+ // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto function2 = invalid2<B>;
+ // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto function3 = valid<A, B>;
+};
+#endif
+} // namespace DependentAddressSpace
+
+namespace DependentSizedExtVector {
+#if defined(FIRST)
+template<int Size>
+void invalid1() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+template<int Size>
+void invalid2() {
+ typedef int __attribute__((ext_vector_type(Size + 0))) type;
+}
+template<int Size>
+void valid() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+#elif defined(SECOND)
+template<int Size>
+void invalid1() {
+ typedef float __attribute__((ext_vector_type(Size))) type;
+}
+template<int Size>
+void invalid2() {
+ typedef int __attribute__((ext_vector_type(Size + 1))) type;
+}
+template<int Size>
+void valid() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+#else
+template <int Num>
+class S {
+ static auto Function1 = invalid1<Num>;
+ // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto Function2 = invalid2<Num>;
+ // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto Function3 = valid<Num>;
+};
+#endif
+} // namespace DependentSizedExtVector
+
+namespace InjectedClassName {
+#if defined(FIRST)
+struct Invalid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L3 *x;
+ };
+ };
+};
+struct Valid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ L3 *y;
+ };
+ };
+};
+#elif defined(SECOND)
+struct Invalid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ };
+ };
+};
+struct Valid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ L3 *y;
+ };
+ };
+};
+#else
+Invalid::L2<1>::L3<1> invalid;
+// expected-error@second.h:* {{'Types::InjectedClassName::Invalid::L2::L3::x' from module 'SecondModule' is not present in definition of 'L3<>' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Valid::L2<1>::L3<1> valid;
+#endif
+} // namespace InjectedClassName
+
+namespace MemberPointer {
+#if defined(FIRST)
+struct A {};
+struct B {};
+
+void Invalid1() {
+ int A::*x;
+};
+void Invalid2() {
+ int A::*x;
+}
+void Invalid3() {
+ int (A::*x)(int);
+}
+void Valid() {
+ int A::*x;
+ float A::*y;
+ bool B::*z;
+ void (A::*fun1)();
+ int (A::*fun2)();
+ void (B::*fun3)(int);
+ void (B::*fun4)(bool*, int);
+}
+#elif defined(SECOND)
+struct A {};
+struct B {};
+
+void Invalid1() {
+ float A::*x;
+};
+void Invalid2() {
+ int B::*x;
+}
+void Invalid3() {
+ int (A::*x)(int, int);
+}
+void Valid() {
+ int A::*x;
+ float A::*y;
+ bool B::*z;
+ void (A::*fun1)();
+ int (A::*fun2)();
+ void (B::*fun3)(int);
+ void (B::*fun4)(bool*, int);
+}
+#else
+auto function1 = Invalid1;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid1' 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}}
+auto function2 = Invalid2;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid2' 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}}
+auto function3 = Invalid3;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid3' 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}}
+auto function4 = Valid;
+#endif
+
+} // namespace MemberPointer
+
+namespace PackExpansion {
+#if defined(FIRST)
+struct Invalid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+struct Valid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+#elif defined(SECOND)
+struct Invalid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(B...);
+ void run(A...);
+ };
+ };
+};
+struct Valid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+#else
+Invalid::L2<int>::L3<short, bool> invalid;
+// expected-error@first.h:* {{'Types::PackExpansion::Invalid::L2::L3' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'run' with 1st parameter of type 'A...'}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'run' with 1st parameter of type 'B...'}}
+Valid::L2<int>::L3<short, bool> valid;
+#endif
+
+} // namespace PackExpansion
+
+namespace Paren {
+#if defined(FIRST)
+void invalid() {
+ int (*x);
+}
+void valid() {
+ int (*x);
+}
+#elif defined(SECOND)
+void invalid() {
+ float (*x);
+}
+void valid() {
+ int (*x);
+}
+#else
+auto function1 = invalid;
+// expected-error@second.h:* {{'Types::Paren::invalid' 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}}
+auto function2 = valid;
+#endif
+} // namespace Paren
+
+namespace SubstTemplateTypeParm {
+#if defined(FIRST)
+template <class> struct wrapper {};
+template <class, class, class> struct triple {};
+struct Valid {
+ template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+ struct L2 {
+ A<T, T> x;
+ };
+};
+#elif defined(SECOND)
+template <class> struct wrapper {};
+template <class, class, class> struct triple {};
+struct Valid {
+ template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+ struct L2 {
+ A<T, T> x;
+ };
+};
+#else
+template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+using V = Valid::L2<T, A>;
+#endif
+} // namespace SubstTemplateTypeParm
+
+namespace SubstTemplateTypeParmPack {
+} // namespace SubstTemplateTypeParmPack
+
+namespace UnaryTransform {
+#if defined(FIRST)
+enum class E1a : unsigned {};
+struct Invalid1 {
+ __underlying_type(E1a) x;
+};
+enum E2a : unsigned {};
+struct Invalid2 {
+ __underlying_type(E2a) x;
+};
+enum E3a {};
+struct Invalid3 {
+ __underlying_type(E3a) x;
+};
+enum E4a {};
+struct Invalid4 {
+ __underlying_type(E4a) x;
+};
+enum E1 {};
+struct Valid1 {
+ __underlying_type(E1) x;
+};
+enum E2 : unsigned {};
+struct Valid2 {
+ __underlying_type(E2) x;
+};
+enum class E3 {};
+struct Valid3 {
+ __underlying_type(E3) x;
+};
+#elif defined(SECOND)
+enum class E1b : signed {};
+struct Invalid1 {
+ __underlying_type(E1b) x;
+};
+enum class E2b : unsigned {};
+struct Invalid2 {
+ __underlying_type(E2b) x;
+};
+enum E3b : int {};
+struct Invalid3 {
+ __underlying_type(E3b) x;
+};
+enum E4b {};
+struct Invalid4 {
+ __underlying_type(E4b) x;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2b)' (aka 'unsigned int')}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2a)' (aka 'unsigned int')}}
+Invalid3 i3;
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid4 i4;
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4b)' (aka 'unsigned int')}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4a)' (aka 'unsigned int')}}
+Valid1 v1;
+Valid2 v2;
+Valid3 v3;
+#endif
+} // namespace UnaryTransform
+
+namespace UnresolvedUsing {
+#if defined(FIRST)
+template <class T> struct wrapper {};
+template <class T>
+struct Invalid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+};
+template <class T>
+struct Valid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+ T2 y;
+};
+#elif defined(SECOND)
+template <class T> struct wrapper {};
+template <class T>
+struct Invalid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T2 x;
+};
+template <class T>
+struct Valid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+ T2 y;
+};
+#else
+template <class T> using I = Invalid<T>;
+// expected-error@first.h:* {{'Types::UnresolvedUsing::Invalid::x' from module 'FirstModule' is not present in definition of 'Invalid<T>' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+
+template <class T> using V = Valid<T>;
+#endif
+
+} // namespace UnresolvedUsing
+
+// Vector
+// void invalid1() {
+// __attribute((vector_size(8))) int *x1;
+//}
+
+} // namespace Types
+
// Collection of interesting cases below.
// Naive parsing of AST can lead to cycles in processing. Ensure