Matheus Izvekov 91cdd35008
[clang] Improve nested name specifier AST representation (#147835)
This is a major change on how we represent nested name qualifications in
the AST.

* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.

This patch offers a great performance benefit.

It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.

This has great results on compile-time-tracker as well:

![image](https://github.com/user-attachments/assets/700dce98-2cab-4aa8-97d1-b038c0bee831)

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.

It has some other miscelaneous drive-by fixes.

About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.

There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.

How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.

The rest and bulk of the changes are mostly consequences of the changes
in API.

PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.

Fixes #136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
2025-08-09 05:06:53 -03:00

5202 lines
138 KiB
C++

// 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++20 %t/Inputs/first.h
// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++20 %t/Inputs/second.h
// Build module map file
// RUN: echo "module FirstModule {" >> %t/Inputs/module.modulemap
// RUN: echo " header \"first.h\"" >> %t/Inputs/module.modulemap
// RUN: echo "}" >> %t/Inputs/module.modulemap
// RUN: echo "module SecondModule {" >> %t/Inputs/module.modulemap
// RUN: echo " header \"second.h\"" >> %t/Inputs/module.modulemap
// RUN: echo "}" >> %t/Inputs/module.modulemap
// Run test
// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++20 \
// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
// RUN: -I%t/Inputs -verify %s
#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 'B' (aka 'int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '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 '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 bit-field 'x'}}
// expected-note@first.h:* {{but in 'FirstModule' found non-bit-field '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 bit-field 'x' with one width expression}}
// expected-note@first.h:* {{but in 'FirstModule' found bit-field '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 bit-field 'x' with one width expression}}
// expected-note@first.h:* {{but in 'FirstModule' found bit-field '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 S9b {
mutable int x : 2;
};
#elif defined(SECOND)
struct S9b {
int x : 2;
};
#else
S9b s9b;
// expected-error@second.h:* {{'Field::S9b' 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 initializer}}
// 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]; \
mutable int g; \
mutable int h : 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;
// FIXME: We should reject the merge of `S3` due to the inconsistent definition of `T`.
#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 '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;
// FIXME: We should reject the merge of `S3` due to the inconsistent definition of `T`.
#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 '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 'DependentType::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;
#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
#if defined(FIRST)
struct S12 {
template <int> void f(){};
template <> void f<1>(){};
};
#elif defined(SECOND)
struct S12 {
template <int> void f(){};
template <> void f<2>(){};
};
#else
S12 s12;
// expected-error@second.h:* {{'TemplateArgument::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 2 for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 1 for 1st template argument}}
#endif
#if defined(FIRST)
struct S13 {
template <int> void f(){};
template <> void f<10>(){};
};
#elif defined(SECOND)
struct S13 {
template <int> void f(){};
template <> void f<10>(){};
};
#else
S13 s13;
#endif
#if defined(FIRST)
struct S14 {
template <bool, bool> void f(){};
template <> void f<true, false>(){};
};
#elif defined(SECOND)
struct S14 {
template <bool, bool> void f(){};
template <> void f<false, true>(){};
};
#else
S14 s14;
// expected-error@second.h:* {{'TemplateArgument::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 0 for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 1 for 1st template argument}}
#endif
#if defined(FIRST)
struct S15 {
template <bool, bool> void f(){};
template <> void f<true, true>(){};
};
#elif defined(SECOND)
struct S15 {
template <bool, bool> void f(){};
template <> void f<true, true>(){};
};
#else
S15 s15;
#endif
#if defined(FIRST)
struct S16 {
template <int *> void f(){};
template <> void f<nullptr>(){};
};
#elif defined(SECOND)
struct S16 {
template <int *> void f(){};
template <> void f<nullptr>(){};
};
#else
S16 s16;
#endif
#if defined(FIRST)
struct S17 {
static int x;
template <int *> void f(){};
template <> void f<&x>(){};
};
#elif defined(SECOND)
struct S17 {
static int x;
template <int *> void f(){};
template <> void f<nullptr>(){};
};
#else
S17 s17;
// expected-error@second.h:* {{'TemplateArgument::S17' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with nullptr for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 'x' for 1st template argument}}
#endif
#if defined(FIRST)
struct S18 {
static int x;
template <int *> void f(){};
template <> void f<&x>(){};
};
#elif defined(SECOND)
struct S18 {
static int x;
template <int *> void f(){};
template <> void f<&x>(){};
};
#else
S18 s18;
#endif
#if defined(FIRST)
struct S19 {
static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1);
template <_BitInt(128)> void f(){};
template <> void f<x + x>(){};
};
#elif defined(SECOND)
struct S19 {
static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1);
template <_BitInt(128)> void f(){};
template <> void f<x + x>(){};
};
#else
S19 s19;
#endif
#if defined(FIRST)
struct S20 {
static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1);
template <_BitInt(128)> void f(){};
template <> void f<x + x>(){};
};
#elif defined(SECOND)
struct S20 {
static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1);
template <_BitInt(128)> void f(){};
template <> void f<x>(){};
};
#else
S20 s20;
// expected-error@second.h:* {{'TemplateArgument::S20' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 18446744073709551615 for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 36893488147419103230 for 1st template argument}}
#endif
#if defined(FIRST)
struct S21 {
static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1);
template <_BitInt(128)> void f(){};
template <> void f<x + 0>(){};
};
#elif defined(SECOND)
struct S21 {
static constexpr _BitInt(128) x = static_cast<_BitInt(128)>((unsigned long long)-1);
template <_BitInt(128)> void f(){};
template <> void f<(unsigned long long)-1>(){};
};
#else
S21 s21;
#endif
#if defined(FIRST)
struct S22 {
template <double> void f(){};
template <> void f<1.5>(){};
};
#elif defined(SECOND)
struct S22 {
template <double> void f(){};
template <> void f<1.7>(){};
};
#else
S22 s22;
// expected-error@second.h:* {{'TemplateArgument::S22' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with 1.700000e+00 for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with 1.500000e+00 for 1st template argument}}
#endif
#if defined(FIRST)
struct S23 {
template <double> void f(){};
template <> void f<2.7>(){};
};
#elif defined(SECOND)
struct S23 {
template <double> void f(){};
template <> void f<2.7>(){};
};
#else
S23 s23;
#endif
#if defined(FIRST) || defined(SECOND)
struct Composite {
int n1[4];
int n2[4];
};
extern Composite composite;
#endif
#if defined(FIRST)
struct S24 {
template <int&> void f(){};
template <> void f<composite.n1[1]>(){};
};
#elif defined(SECOND)
struct S24 {
template <int&> void f(){};
template <> void f<composite.n1[2]>(){};
};
#else
S24 s24;
// expected-error@second.h:* {{'TemplateArgument::S24' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with composite.n1[2] for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with composite.n1[1] for 1st template argument}}
#endif
#if defined(FIRST) || defined(SECOND)
struct S25 {
template <int&> void f();
template <> void f<composite.n1[2]>();
};
#else
S25 s25;
#endif
#if defined(FIRST)
struct S26 {
template <int*> void f(){};
template <> void f<&composite.n1[4]>(){}; // Past-the-end pointer.
};
#elif defined(SECOND)
struct S26 {
template <int*> void f(){};
template <> void f<&composite.n2[0]>(){};
};
#else
S26 s26;
// expected-error@second.h:* {{'TemplateArgument::S26' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &composite.n2[0] for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with &composite.n1[4] for 1st template argument}}
#endif
#if defined(FIRST) || defined(SECOND)
union Union {
int i1;
int i2;
};
extern Union u;
#endif
#if defined(FIRST)
struct S27 {
template <int&> void f(){};
template <> void f<u.i1>(){};
};
#elif defined(SECOND)
struct S27 {
template <int&> void f(){};
template <> void f<u.i2>(){};
};
#else
S27 s27;
// expected-error@second.h:* {{'TemplateArgument::S27' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with u.i2 for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with u.i1 for 1st template argument}}
#endif
#if defined(FIRST) || defined(SECOND)
struct S28 {
template <int&> void f(){};
template <> void f<u.i1>(){};
};
#else
S28 s28;
#endif
#if defined(FIRST) || defined(SECOND)
struct A {
int a;
};
struct B : A {};
struct C : A {};
struct D : B, C {};
#endif
#if defined(FIRST)
struct S29 {
template <int D::*> void f(){};
template <> void f<(int D::*)(int B::*)&A::a>(){};
};
#elif defined(SECOND)
struct S29 {
template <int D::*> void f(){};
template <> void f<(int D::*)(int C::*)&A::a>(){};
};
#else
S29 s29;
// expected-error@second.h:* {{'TemplateArgument::S29' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &A::a for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with &A::a for 1st template argument}}
#endif
#if defined(FIRST) || defined(SECOND)
struct S30 {
template <int D::*> void f(){};
template <> void f<(int D::*)(int B::*)&A::a>(){};
};
#else
S30 s30;
#endif
#if defined(FIRST)
struct S31 {
template <auto*> void f(){};
template <> void f<&composite.n1[2]>(){};
};
#elif defined(SECOND)
struct S31 {
template <auto*> void f(){};
template <> void f<(void*)&composite.n1[2]>(){};
};
#else
S31 s31;
// expected-error@second.h:* {{'TemplateArgument::S31' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with &composite.n1[2] for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with &composite.n1[2] for 1st template argument}}
#endif
#if defined(FIRST)
struct S32 {
template <int*> void f(){};
template <> void f<__builtin_constant_p(0) ? (int*)1 : (int*)1>(){};
};
#elif defined(SECOND)
struct S32 {
template <int*> void f(){};
template <> void f<__builtin_constant_p(0) ? (int*)2 : (int*)2>(){};
};
#else
S32 s32;
// expected-error@second.h:* {{'TemplateArgument::S32' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'f' with (int *)2 for 1st template argument}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'f' with (int *)1 for 1st template argument}}
#endif
#if defined(FIRST) || defined(SECOND)
struct S33 {
template <int*> void f(){};
template <> void f<__builtin_constant_p(0) ? (int*)1 : (int*)1>(){};
};
#else
S33 s33;
#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 'TemplateTypeParmType::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 'TemplateTypeParmType::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 'TemplateTypeParmType::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 '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 '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 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 void Function();
#if defined(FIRST) || defined(SECOND)
class FriendA {};
class FriendB {};
class FriendC {};
#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
#if defined(FIRST)
template <int A = 7>
struct S7 {};
#elif defined(SECOND)
template <int A = 8>
struct S7 {};
#else
using TemplateParameters::S7;
// expected-error@second.h:* {{'TemplateParameters::S7' 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 <int* A = nullptr>
struct S8 {};
#elif defined(SECOND)
inline int S8_default_arg = 0x12345;
template <int* A = &S8_default_arg>
struct S8 {};
#else
using TemplateParameters::S8;
// expected-error@second.h:* {{'TemplateParameters::S8' 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 <int A = 43>
struct S9 {};
#elif defined(SECOND)
template <int A = 43>
struct S9 {};
#else
using TemplateParameters::S9;
#endif
#if defined(FIRST)
template <class A = double>
struct S10 {};
#elif defined(SECOND)
template <class A = double>
struct S10 {};
#else
using TemplateParameters::S10;
#endif
#if defined(FIRST)
template <template<int> class A = S9>
struct S11 {};
#elif defined(SECOND)
template <template<int> class A = S9>
struct S11 {};
#else
using TemplateParameters::S11;
#endif
// FIXME: It looks like we didn't implement ODR check for template variables.
// S12, S13 and S14 show this.
#if defined(FIRST)
template <int A = 43>
int S12 {};
#elif defined(SECOND)
template <int A = 44>
int S12 {};
#else
using TemplateParameters::S12;
#endif
#if defined(FIRST)
template <class A = double>
int S13 {};
#elif defined(SECOND)
template <class A = int>
int S13 {};
#else
using TemplateParameters::S13;
#endif
#if defined(FIRST)
template <class A>
int S14 {};
#elif defined(SECOND)
template <class B>
int S14 {};
#else
using TemplateParameters::S14;
#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 'B4b'}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class with different type '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 'B7a' with no access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class '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 'B8a' with private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class '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 'B9a' with public access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class '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 'B10a' with protected access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found 1st base class '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@first.h:* {{'PointersAndReferences::S5::x' from module 'FirstModule' is not present in definition of 'PointersAndReferences::S5' in module 'SecondModule'}}
// expected-note@second.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 initializer}}
// 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 initializer}}
// 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
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;
// FIXME: We should reject the merge of `invalid2` and diagnose about the
// inconsistent definition of `global`.
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;
// FIXME: We should reject the merge of `invalid1` due to the inconsistent definition.
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 'Types::InjectedClassName::Invalid::L2::L3<value-parameter-1-0>' 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(E2b)' (aka 'unsigned int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(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(E4b)' (aka 'unsigned int')}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(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 'Types::UnresolvedUsing::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
// 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;
// expected-error@first.h:* {{'ParameterTest::S::Foo' has different definitions in different modules; definition in module 'FirstModule' first difference is 1st parameter with name 'aaaa'}}
// expected-note@second.h:* {{but in 'SecondModule' found 1st parameter with name 'asdf'}}
#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 '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 '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
}
namespace FunctionProtoTypeDecay {
#if defined(FIRST)
struct S1 {
struct X {};
using Y = X(X());
};
#elif defined(SECOND)
struct S1 {
struct X {};
using Y = X(X(X()));
};
#else
S1 s1;
// expected-error@first.h:* {{'FunctionProtoTypeDecay::S1::Y' from module 'FirstModule' is not present in definition of 'FunctionProtoTypeDecay::S1' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 'Y' does not match}}
#endif
#if defined(FIRST)
struct S2 {
struct X {};
using Y =
X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(X(
))))))))))))))))
))))))))))))))))
))))))))))))))))
))))))))))))))));
};
#elif defined(SECOND)
#else
S2 s2;
#endif
}
namespace TypedefStruct {
#if defined(FIRST)
struct T1;
class S1 {
T1* t;
};
#elif defined(SECOND)
typedef struct T1 {} T1;
class S1 {
T1* t;
};
#else
S1 s1;
#endif
#if defined(FIRST)
struct T2;
class S2 {
const T2* t = nullptr;
};
#elif defined(SECOND)
typedef struct T2 {} T2;
class S2 {
const T2* t = nullptr;
};
#else
S2 s2;
#endif
#if defined(FIRST)
struct T3;
class S3 {
T3* const t = nullptr;
};
#elif defined(SECOND)
typedef struct T3 {} T3;
class S3 {
T3* const t = nullptr;
};
#else
S3 s3;
#endif
#if defined(FIRST)
namespace NS4 {
struct T4;
} // namespace NS4
class S4 {
NS4::T4* t = 0;
};
#elif defined(SECOND)
namespace NS4 {
typedef struct T4 {} T4;
} // namespace NS4
class S4 {
NS4::T4* t = 0;
};
#else
S4 s4;
#endif
#if defined(FIRST)
namespace NS5 {
struct T5;
} // namespace NS5
class S5 {
NS5::T5* t = 0;
};
#elif defined(SECOND)
namespace NS5 {
typedef struct T5_Other {} T5;
} // namespace NS4
class S5 {
NS5::T5* t = 0;
};
#else
S5 s5;
// expected-error@first.h:* {{'TypedefStruct::S5::t' from module 'FirstModule' is not present in definition of 'TypedefStruct::S5' in module 'SecondModule'}}
// expected-note@second.h:* {{declaration of 't' does not match}}
#endif
} // namespace TypedefStruct
#if defined (FIRST)
typedef int T;
namespace A {
struct X { T n; };
}
#elif defined(SECOND)
namespace A {
typedef int T;
struct X { T n; };
}
#else
A::X x;
#endif
namespace TemplateDecltypeOperator {
#if defined(FIRST) || defined(SECOND)
template <class T6>
T6 func();
#endif
#if defined(SECOND)
template <class UnrelatedT>
using UnrelatedAlias = decltype(func<UnrelatedT>())();
#endif
#if defined(FIRST) || defined(SECOND)
class A {
template <class T6>
operator decltype(func<T6>()) () {}
};
#else
A a;
#endif
}
// Keep macros contained to one file.
#ifdef FIRST
#undef FIRST
#endif
#ifdef SECOND
#undef SECOND
#endif
#ifdef ACCESS
#undef ACCESS
#endif