blob: 46986a68e9438297c5275b63ddae3379ef027a7b [file] [edit]
// RUN: split-file %s %t
// RUN: %clang_cc1 -std=c++20 -fno-skip-odr-check-in-gmf -emit-module-interface %t/part.cppm -o %t/part.pcm
// RUN: %clang_cc1 -std=c++20 -fno-skip-odr-check-in-gmf -fmodule-file=repro:part=%t/part.pcm -emit-module-interface %t/module.cppm -o %t/module.pcm -verify
// RUN: %clang_cc1 -std=c++20 -DREVERSE -fno-skip-odr-check-in-gmf -emit-module-interface %t/part.cppm -o %t/part.pcm
// RUN: %clang_cc1 -std=c++20 -DREVERSE -fno-skip-odr-check-in-gmf -fmodule-file=repro:part=%t/part.pcm -emit-module-interface %t/module.cppm -o %t/module.pcm -verify
// RUN: %clang_cc1 -std=c++20 -fno-skip-odr-check-in-gmf -emit-module-interface %t/first.cppm -o %t/first.pcm
// RUN: %clang_cc1 -std=c++20 -fno-skip-odr-check-in-gmf -emit-module-interface %t/second.cppm -o %t/second.pcm
// RUN: not %clang_cc1 -std=c++20 -fno-skip-odr-check-in-gmf -fprebuilt-module-path=%t -fsyntax-only %t/bad.cpp 2>&1 | FileCheck %s --check-prefix=BAD
// BAD-DAG: error: 'different_spelling::qualification' has different definitions
// BAD-DAG: error: 'different_spelling::keyword' has different definitions
// BAD-DAG: error: 'different_spelling::cv' has different definitions
//--- declarations.h
typedef long T;
using Qualified = const volatile long;
struct Record { int value; };
enum class Kind { value };
typedef struct CRecord { int value; } CRecord;
namespace chain {
using ::T;
}
namespace ns {
#ifdef INDIRECT
using chain::T;
using ::Qualified;
using ::Record;
using ::Kind;
using ::CRecord;
#endif
inline void fun() { (void)(T)0; }
inline Qualified *pointer(Qualified *p) { return p; }
inline Record make() { return Record{0}; }
inline unsigned sizes() {
return sizeof(T) + sizeof(Record) + sizeof(Kind) + sizeof(CRecord);
}
struct Fields {
T value;
Qualified *pointer;
Record record;
Kind kind;
};
template <class U> inline void templ(U) {
const T value = 0;
(void)value;
}
}
//--- part.cppm
module;
#ifdef REVERSE
#define INDIRECT
#endif
#include "declarations.h"
export module repro:part;
export void use() {
ns::Fields fields{};
ns::fun();
ns::pointer(nullptr);
ns::make();
ns::sizes();
ns::templ(0);
}
//--- module.cppm
// expected-no-diagnostics
module;
#ifndef REVERSE
#define INDIRECT
#endif
#include "declarations.h"
export module repro;
export import :part;
//--- bad.h
namespace types {
using Scalar = int;
struct Record {};
}
namespace different_spelling {
using types::Scalar;
using types::Record;
inline int qualification() {
#ifdef FIRST
return sizeof(Scalar);
#else
return sizeof(different_spelling::Scalar);
#endif
}
inline int keyword() {
#ifdef FIRST
return sizeof(Record);
#else
return sizeof(struct Record);
#endif
}
inline int cv() {
#ifdef FIRST
return sizeof(Scalar);
#else
return sizeof(const Scalar);
#endif
}
}
//--- first.cppm
module;
#define FIRST
#include "bad.h"
export module first;
export using different_spelling::qualification;
export using different_spelling::keyword;
export using different_spelling::cv;
//--- second.cppm
module;
#include "bad.h"
export module second;
export using different_spelling::qualification;
export using different_spelling::keyword;
export using different_spelling::cv;
//--- bad.cpp
import first;
import second;
int use() { return qualification() + keyword() + cv(); }