
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:  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
5202 lines
138 KiB
C++
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
|