forked from OSchip/llvm-project
Improve diagnostic on default-initializing const variables (PR20208).
This tweaks the diagnostic wording slighly, and adds a fixit on a note. An alternative would be to add the fixit directly on the diagnostic, see the review thread linked to from the bug for a few notes on that approach. llvm-svn: 213725
This commit is contained in:
parent
bb3d7b5e81
commit
9386c82d56
|
@ -5203,7 +5203,9 @@ def err_address_space_qualified_delete : Error<
|
|||
|
||||
def err_default_init_const : Error<
|
||||
"default initialization of an object of const type %0"
|
||||
"%select{| requires a user-provided default constructor}1">;
|
||||
"%select{| without a user-provided default constructor}1">;
|
||||
def note_add_initializer : Note<
|
||||
"add an explicit initializer to initialize %0">;
|
||||
def err_delete_operand : Error<"cannot delete expression of type %0">;
|
||||
def ext_delete_void_ptr_operand : ExtWarn<
|
||||
"cannot delete expression with pointer-to-'void' type %0">;
|
||||
|
|
|
@ -6455,6 +6455,26 @@ static void diagnoseListInit(Sema &S, const InitializedEntity &Entity,
|
|||
"Inconsistent init list check result.");
|
||||
}
|
||||
|
||||
/// Prints a fixit for adding a null initializer for |Entity|. Call this only
|
||||
/// right after emitting a diagnostic.
|
||||
static void maybeEmitZeroInitializationFixit(Sema &S,
|
||||
InitializationSequence &Sequence,
|
||||
const InitializedEntity &Entity) {
|
||||
if (Entity.getKind() != InitializedEntity::EK_Variable)
|
||||
return;
|
||||
|
||||
VarDecl *VD = cast<VarDecl>(Entity.getDecl());
|
||||
if (VD->getInit() || VD->getLocEnd().isMacroID())
|
||||
return;
|
||||
|
||||
QualType VariableTy = VD->getType().getCanonicalType();
|
||||
SourceLocation Loc = S.getLocForEndOfToken(VD->getLocEnd());
|
||||
std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc);
|
||||
|
||||
S.Diag(Loc, diag::note_add_initializer)
|
||||
<< VD << FixItHint::CreateInsertion(Loc, Init);
|
||||
}
|
||||
|
||||
bool InitializationSequence::Diagnose(Sema &S,
|
||||
const InitializedEntity &Entity,
|
||||
const InitializationKind &Kind,
|
||||
|
@ -6786,6 +6806,7 @@ bool InitializationSequence::Diagnose(Sema &S,
|
|||
} else {
|
||||
S.Diag(Kind.getLocation(), diag::err_default_init_const)
|
||||
<< DestType << (bool)DestType->getAs<RecordType>();
|
||||
maybeEmitZeroInitializationFixit(S, *this, Entity);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ extern int (*const d)(int);
|
|||
|
||||
// A variable declaration which uses the constexpr specifier shall have an
|
||||
// initializer and shall be initialized by a constant expression.
|
||||
constexpr int ni1; // expected-error {{default initialization of an object of const type 'const int'}}
|
||||
constexpr int ni1; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'ni1'}}
|
||||
constexpr struct C { C(); } ni2; // expected-error {{cannot have non-literal type 'const struct C'}} expected-note 3{{has no constexpr constructors}}
|
||||
constexpr double &ni3; // expected-error {{declaration of reference variable 'ni3' requires an initializer}}
|
||||
|
||||
|
@ -34,4 +34,4 @@ struct pixel {
|
|||
int x, y;
|
||||
};
|
||||
constexpr pixel ur = { 1294, 1024 }; // ok
|
||||
constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' requires a user-provided default constructor}}
|
||||
constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'origin'}}
|
||||
|
|
|
@ -36,7 +36,7 @@ struct S3 {
|
|||
constexpr S3 s3a = S3(0);
|
||||
constexpr S3 s3b = s3a;
|
||||
constexpr S3 s3c = S3();
|
||||
constexpr S3 s3d; // expected-error {{default initialization of an object of const type 'const S3' requires a user-provided default constructor}}
|
||||
constexpr S3 s3d; // expected-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 's3d'}}
|
||||
|
||||
struct S4 {
|
||||
S4() = default;
|
||||
|
@ -119,6 +119,6 @@ namespace PR13492 {
|
|||
};
|
||||
|
||||
void f() {
|
||||
const B b; // expected-error {{default initialization of an object of const type 'const PR13492::B' requires a user-provided default constructor}}
|
||||
const B b; // expected-error {{default initialization of an object of const type 'const PR13492::B' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'b'}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,15 +10,15 @@ struct NoUserDefault : public MakeNonPOD { };
|
|||
struct HasUserDefault { HasUserDefault(); };
|
||||
|
||||
void test_const_default_init() {
|
||||
const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'const NoUserDefault' requires a user-provided default constructor}}
|
||||
const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'const NoUserDefault' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'x1'}}
|
||||
const HasUserDefault x2;
|
||||
const int x3; // expected-error{{default initialization of an object of const type 'const int'}}
|
||||
const int x3; // expected-error{{default initialization of an object of const type 'const int'}} expected-note{{add an explicit initializer to initialize 'x3'}}
|
||||
}
|
||||
|
||||
// rdar://8501008
|
||||
struct s0 {};
|
||||
struct s1 { static const s0 foo; };
|
||||
const struct s0 s1::foo; // expected-error{{default initialization of an object of const type 'const struct s0' requires a user-provided default constructor}}
|
||||
const struct s0 s1::foo; // expected-error{{default initialization of an object of const type 'const struct s0' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'foo'}}
|
||||
|
||||
template<typename T>
|
||||
struct s2 {
|
||||
|
|
|
@ -852,7 +852,7 @@ namespace dr77 { // dr77: yes
|
|||
namespace dr78 { // dr78: sup ????
|
||||
// Under DR78, this is valid, because 'k' has static storage duration, so is
|
||||
// zero-initialized.
|
||||
const int k; // expected-error {{default initialization of an object of const}}
|
||||
const int k; // expected-error {{default initialization of an object of const}} expected-note{{add an explicit initializer to initialize 'k'}}
|
||||
}
|
||||
|
||||
// dr79: na
|
||||
|
|
|
@ -1201,7 +1201,7 @@ namespace dr497 { // dr497: yes
|
|||
struct S {
|
||||
mutable int i;
|
||||
};
|
||||
const S cs; // expected-error {{default initialization}}
|
||||
const S cs; // expected-error {{default initialization}} expected-note {{add an explicit initializer}}
|
||||
int S::*pm = &S::i;
|
||||
cs.*pm = 88;
|
||||
}
|
||||
|
|
|
@ -1177,7 +1177,7 @@ namespace ExternConstexpr {
|
|||
void f() {
|
||||
extern constexpr int i; // expected-error {{constexpr variable declaration must be a definition}}
|
||||
constexpr int j = 0;
|
||||
constexpr int k; // expected-error {{default initialization of an object of const type}}
|
||||
constexpr int k; // expected-error {{default initialization of an object of const type}} expected-note{{add an explicit initializer to initialize 'k'}}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ void f() {
|
|||
constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}}
|
||||
}
|
||||
|
||||
constexpr B b1; // expected-error {{requires a user-provided default constructor}}
|
||||
constexpr B b1; // expected-error {{without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'b1'}}
|
||||
constexpr B b2 = B(); // ok
|
||||
static_assert(b2.a.a == 1, "");
|
||||
static_assert(b2.a.b == 2, "");
|
||||
|
@ -23,9 +23,9 @@ struct C {
|
|||
int c;
|
||||
};
|
||||
struct D : C { int d; };
|
||||
constexpr C c1; // expected-error {{requires a user-provided default constructor}}
|
||||
constexpr C c1; // expected-error {{without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 'c1'}}
|
||||
constexpr C c2 = C(); // ok
|
||||
constexpr D d1; // expected-error {{requires a user-provided default constructor}}
|
||||
constexpr D d1; // expected-error {{without a user-provided default constructor}} expected-note{{add an explicit initializer to initialize 'd1'}}
|
||||
constexpr D d2 = D(); // ok with DR1452
|
||||
static_assert(D().c == 0, "");
|
||||
static_assert(D().d == 0, "");
|
||||
|
|
|
@ -25,7 +25,7 @@ void fn1 () {
|
|||
non_const_copy ncc2 = ncc;
|
||||
ncc = ncc2;
|
||||
const non_const_copy cncc{};
|
||||
const non_const_copy cncc1; // expected-error {{default initialization of an object of const type 'const non_const_copy' requires a user-provided default constructor}}
|
||||
const non_const_copy cncc1; // expected-error {{default initialization of an object of const type 'const non_const_copy' without a user-provided default constructor}} expected-note {{add an explicit initializer to initialize 'cncc1'}}
|
||||
non_const_copy ncc3 = cncc; // expected-error {{no matching}}
|
||||
ncc = cncc; // expected-error {{no viable overloaded}}
|
||||
};
|
||||
|
|
|
@ -58,13 +58,13 @@ namespace out_of_line {
|
|||
template<typename T, typename T0> static CONST T b = T(100);
|
||||
template<typename T> static CONST T b<T,int>;
|
||||
};
|
||||
template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}}
|
||||
template<typename T, typename T0> CONST T B4::a; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'a<int, char>'}}
|
||||
template<typename T> CONST T B4::a<T,int>;
|
||||
template CONST int B4::a<int,char>; // expected-note {{in instantiation of}}
|
||||
template CONST int B4::a<int,int>;
|
||||
|
||||
template<typename T, typename T0> CONST T B4::b;
|
||||
template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}}
|
||||
template<typename T> CONST T B4::b<T,int>; // expected-error {{default initialization of an object of const type 'const int'}} expected-note {{add an explicit initializer to initialize 'b<int, int>'}}
|
||||
template CONST int B4::b<int,char>;
|
||||
template CONST int B4::b<int,int>; // expected-note {{in instantiation of}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue