WG14 adopted the _ExtInt feature from Clang for C23, but renamed the type to be _BitInt. This patch does the vast majority of the work to rename _ExtInt to _BitInt, which accounts for most of its size. The new type is exposed in older C modes and all C++ modes as a conforming extension. However, there are functional changes worth calling out: * Deprecates _ExtInt with a fix-it to help users migrate to _BitInt. * Updates the mangling for the type. * Updates the documentation and adds a release note to warn users what is going on. * Adds new diagnostics for use of _BitInt to call out when it's used as a Clang extension or as a pre-C23 compatibility concern. * Adds new tests for the new diagnostic behaviors. I want to call out the ABI break specifically. We do not believe that this break will cause a significant imposition for early adopters of the feature, and so this is being done as a full break. If it turns out there are critical uses where recompilation is not an option for some reason, we can consider using ABI tags to ease the transition.
127 lines
5.8 KiB
C++
127 lines
5.8 KiB
C++
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 -std=c++98 %s -Wno-c++11-extensions
|
|
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17 -std=c++17 %s
|
|
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
|
|
|
|
// C++98:
|
|
// A non-type template-parameter shall not be declared to have
|
|
// floating point, class, or void type.
|
|
struct A; // expected-note {{forward declaration}}
|
|
|
|
template<double d> class X; // cxx17-error{{cannot have type}}
|
|
template<double* pd> class Y; //OK
|
|
template<double& rd> class Z; //OK
|
|
|
|
template<A a> class X0; // expected-error{{has incomplete type 'A'}}
|
|
|
|
struct A {};
|
|
|
|
template<A a> class X0b; // cxx17-error{{cannot have type 'A' before C++20}}
|
|
|
|
typedef void VOID;
|
|
template<VOID a> class X01; // expected-error{{has incomplete type 'VOID'}}
|
|
|
|
// C++11 disallows rvalue references.
|
|
|
|
template<int &R> struct lval_ref;
|
|
template<int &&R> struct rval_ref; // expected-warning 0-1{{extension}} expected-error {{non-type template parameter has rvalue reference type 'int &&'}}
|
|
|
|
// C++20 requires a structural type. In addition to the above cases, this allows:
|
|
|
|
// arbitrary scalar types; we generally include complex types in that list
|
|
template<_Complex float ci> struct ComplexFloat; // cxx17-error {{cannot have type '_Complex float' before C++20}}
|
|
template<_Complex int ci> struct ComplexInt; // cxx17-error {{cannot have type '_Complex int' before C++20}}
|
|
template<_BitInt(42) ei> struct ExtInt;
|
|
|
|
// atomic types aren't scalar types
|
|
template<_Atomic float ci> struct AtomicFloat; // expected-error {{cannot have type '_Atomic(float)'}}
|
|
template<_Atomic int ci> struct AtomicInt; // expected-error {{cannot have type '_Atomic(int)'}}
|
|
|
|
// we allow vector types as an extension
|
|
typedef __attribute__((ext_vector_type(4))) int VI4;
|
|
typedef __attribute__((ext_vector_type(4))) float VF4;
|
|
template<VI4> struct VectorInt; // cxx17-error {{cannot have type 'VI4'}}
|
|
template<VF4> struct VectorFloat; // cxx17-error {{cannot have type 'VF4'}}
|
|
|
|
struct A2 {};
|
|
|
|
struct RRef {
|
|
int &&r; // cxx20-note 1+{{'RRef' is not a structural type because it has a non-static data member of rvalue reference type}}
|
|
};
|
|
|
|
// class types with all public members and bases, no mutable state, and no rvalue references.
|
|
struct B : A, public A2 {
|
|
int a;
|
|
private:
|
|
void f();
|
|
static int s;
|
|
public:
|
|
float g;
|
|
int &r = a;
|
|
void *p;
|
|
A2 a2;
|
|
RRef *ptr_to_bad;
|
|
RRef &ref_to_bad = *ptr_to_bad;
|
|
_Complex int ci;
|
|
_Complex float cf;
|
|
_BitInt(42) ei;
|
|
VI4 vi4;
|
|
VF4 vf4;
|
|
};
|
|
|
|
template<B> struct ClassNTTP {}; // cxx17-error {{cannot have type 'B'}}
|
|
|
|
template<RRef> struct WithRRef {}; // cxx17-error {{cannot have type 'RRef'}}
|
|
// cxx20-error@-1 {{type 'RRef' of non-type template parameter is not a structural type}}
|
|
|
|
struct BadBase
|
|
: RRef {}; // cxx20-note {{'BadBase' is not a structural type because it has a base class of non-structural type 'RRef'}}
|
|
template<BadBase> struct WithBadBase {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
struct BadField {
|
|
RRef r; // cxx20-note {{'BadField' is not a structural type because it has a non-static data member of non-structural type 'RRef'}}
|
|
};
|
|
template<BadField> struct WithBadField {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
struct BadFieldArray {
|
|
RRef r[3][2]; // cxx20-note {{'BadFieldArray' is not a structural type because it has a non-static data member of non-structural type 'RRef'}}
|
|
};
|
|
template<BadFieldArray> struct WithBadFieldArray {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
struct ProtectedBase
|
|
: protected A {}; // cxx20-note {{'ProtectedBase' is not a structural type because it has a base class that is not public}}
|
|
template<ProtectedBase> struct WithProtectedBase {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
struct PrivateBase
|
|
: private A {}; // cxx20-note {{'PrivateBase' is not a structural type because it has a base class that is not public}}
|
|
template<PrivateBase> struct WithPrivateBase {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
class Private2Base
|
|
: A {}; // cxx20-note {{'Private2Base' is not a structural type because it has a base class that is not public}}
|
|
template<Private2Base> struct WithPrivate2Base {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
struct ProtectedField {
|
|
protected:
|
|
A r; // cxx20-note {{'ProtectedField' is not a structural type because it has a non-static data member that is not public}}
|
|
};
|
|
template<ProtectedField> struct WithProtectedField {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
struct PrivateField {
|
|
private:
|
|
A r; // cxx20-note {{'PrivateField' is not a structural type because it has a non-static data member that is not public}}
|
|
};
|
|
template<PrivateField> struct WithPrivateField {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
class Private2Field {
|
|
A r; // cxx20-note {{'Private2Field' is not a structural type because it has a non-static data member that is not public}}
|
|
};
|
|
template<Private2Field> struct WithPrivate2Field {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
struct MutableField {
|
|
mutable int n; // cxx20-note {{'MutableField' is not a structural type because it has a mutable non-static data member}}
|
|
};
|
|
template<MutableField> struct WithMutableField {}; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
|
|
template<typename T> struct BadExtType { T t; }; // cxx20-note 2{{has a non-static data member of non-structural type}}
|
|
template<BadExtType<_Atomic float> > struct AtomicFloatField; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|
|
template<BadExtType<_Atomic int> > struct AtomicInt; // cxx17-error {{cannot have type}} cxx20-error {{is not a structural type}}
|