[C++11] Fix warning when dropping cv-qualifiers when assigning to a reference with a braced initializer list

llvm-svn: 336922
This commit is contained in:
Nicolas Lesser 2018-07-12 17:43:49 +00:00
parent e8c3c5fe5d
commit 8217a2ab4f
2 changed files with 48 additions and 16 deletions

View File

@ -7567,6 +7567,19 @@ bool InitializationSequence::Diagnose(Sema &S,
if (!Failed())
return false;
// When we want to diagnose only one element of a braced-init-list,
// we need to factor it out.
Expr *OnlyArg;
if (Args.size() == 1) {
auto *List = dyn_cast<InitListExpr>(Args[0]);
if (List && List->getNumInits() == 1)
OnlyArg = List->getInit(0);
else
OnlyArg = Args[0];
}
else
OnlyArg = nullptr;
QualType DestType = Entity.getType();
switch (Failure) {
case FK_TooManyInitsForReference:
@ -7627,7 +7640,7 @@ bool InitializationSequence::Diagnose(Sema &S,
? diag::err_array_init_different_type
: diag::err_array_init_non_constant_array))
<< DestType.getNonReferenceType()
<< Args[0]->getType()
<< OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
@ -7638,7 +7651,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_AddressOfOverloadFailed: {
DeclAccessPair Found;
S.ResolveAddressOfOverloadedFunction(Args[0],
S.ResolveAddressOfOverloadedFunction(OnlyArg,
DestType.getNonReferenceType(),
true,
Found);
@ -7646,9 +7659,9 @@ bool InitializationSequence::Diagnose(Sema &S,
}
case FK_AddressOfUnaddressableFunction: {
auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(Args[0])->getDecl());
auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl());
S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
Args[0]->getLocStart());
OnlyArg->getLocStart());
break;
}
@ -7658,11 +7671,11 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_Ambiguous:
if (Failure == FK_UserConversionOverloadFailed)
S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
<< Args[0]->getType() << DestType
<< OnlyArg->getType() << DestType
<< Args[0]->getSourceRange();
else
S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
<< DestType << Args[0]->getType()
<< DestType << OnlyArg->getType()
<< Args[0]->getSourceRange();
FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
@ -7672,10 +7685,10 @@ bool InitializationSequence::Diagnose(Sema &S,
if (!S.RequireCompleteType(Kind.getLocation(),
DestType.getNonReferenceType(),
diag::err_typecheck_nonviable_condition_incomplete,
Args[0]->getType(), Args[0]->getSourceRange()))
OnlyArg->getType(), Args[0]->getSourceRange()))
S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
<< (Entity.getKind() == InitializedEntity::EK_Result)
<< Args[0]->getType() << Args[0]->getSourceRange()
<< OnlyArg->getType() << Args[0]->getSourceRange()
<< DestType.getNonReferenceType();
FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
@ -7683,7 +7696,7 @@ bool InitializationSequence::Diagnose(Sema &S,
case OR_Deleted: {
S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
<< Args[0]->getType() << DestType.getNonReferenceType()
<< OnlyArg->getType() << DestType.getNonReferenceType()
<< Args[0]->getSourceRange();
OverloadCandidateSet::iterator Best;
OverloadingResult Ovl
@ -7719,7 +7732,7 @@ bool InitializationSequence::Diagnose(Sema &S,
: diag::err_lvalue_reference_bind_to_unrelated)
<< DestType.getNonReferenceType().isVolatileQualified()
<< DestType.getNonReferenceType()
<< Args[0]->getType()
<< OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
@ -7744,12 +7757,12 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_RValueReferenceBindingToLValue:
S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
<< DestType.getNonReferenceType() << Args[0]->getType()
<< DestType.getNonReferenceType() << OnlyArg->getType()
<< Args[0]->getSourceRange();
break;
case FK_ReferenceInitDropsQualifiers: {
QualType SourceType = Args[0]->getType();
QualType SourceType = OnlyArg->getType();
QualType NonRefType = DestType.getNonReferenceType();
Qualifiers DroppedQualifiers =
SourceType.getQualifiers() - NonRefType.getQualifiers();
@ -7765,18 +7778,18 @@ bool InitializationSequence::Diagnose(Sema &S,
case FK_ReferenceInitFailed:
S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
<< DestType.getNonReferenceType()
<< Args[0]->isLValue()
<< Args[0]->getType()
<< OnlyArg->isLValue()
<< OnlyArg->getType()
<< Args[0]->getSourceRange();
emitBadConversionNotes(S, Entity, Args[0]);
break;
case FK_ConversionFailed: {
QualType FromType = Args[0]->getType();
QualType FromType = OnlyArg->getType();
PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
<< (int)Entity.getKind()
<< DestType
<< Args[0]->isLValue()
<< OnlyArg->isLValue()
<< FromType
<< Args[0]->getSourceRange();
S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);

View File

@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
int g(int);
void f() {
@ -55,6 +56,24 @@ void test5() {
// const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
const volatile int cvi = 1;
const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
#if __cplusplus >= 201103L
const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
const int a = 2;
int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}}
const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}}
void func();
void func(int);
int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
// expected-note@-4{{candidate function}}
// expected-note@-4{{candidate function}}
// expected-note@-6{{candidate function}}
// expected-note@-6{{candidate function}}
#endif
}
// C++ [dcl.init.ref]p3