aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td12
-rw-r--r--lib/Sema/SemaDeclCXX.cpp1
-rw-r--r--lib/Sema/SemaInit.cpp3
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp6
4 files changed, 15 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index af64ccbc54..7cd8d29051 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -560,14 +560,14 @@ def err_invalid_initialization : Error<
def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue "
"due to multiple conversion functions">;
def err_not_reference_to_const_init : Error<
- "non-const lvalue reference to type %0 cannot be initialized "
- "with a %select{value|temporary}1 of type %2">;
+ "%select{non-const|volatile}0 lvalue reference to type %1 cannot be "
+ "initialized with a %select{value|temporary}2 of type %3">;
def err_lvalue_reference_bind_to_temporary : Error<
- "non-const lvalue reference to type %0 cannot bind to a temporary of type "
- "%1">;
+ "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
+ "temporary of type %2">;
def err_lvalue_reference_bind_to_unrelated : Error<
- "non-const lvalue reference to type %0 cannot bind to a value of unrelated "
- "type %1">;
+ "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
+ "value of unrelated type %2">;
def err_reference_bind_drops_quals : Error<
"binding of reference to type %0 to a value of type %1 drops qualifiers">;
def err_reference_bind_failed : Error<
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 566e915bc0..130bf4dbdf 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4616,6 +4616,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
if (!ICS)
Diag(DeclLoc, diag::err_not_reference_to_const_init)
+ << T1.isVolatileQualified()
<< T1 << int(InitLvalue != Expr::LV_Valid)
<< T2 << Init->getSourceRange();
return true;
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 1a588094cd..910d3f6469 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2369,7 +2369,7 @@ static void TryReferenceInitialization(Sema &S,
// non-volatile const type (i.e., cv1 shall be const), or the reference
// shall be an rvalue reference and the initializer expression shall
// be an rvalue.
- if (!((isLValueRef && T1Quals.hasConst()) ||
+ if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) ||
(isRValueRef && InitLvalue != Expr::LV_Valid))) {
if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
Sequence.SetOverloadFailure(
@@ -3556,6 +3556,7 @@ bool InitializationSequence::Diagnose(Sema &S,
Failure == FK_NonConstLValueReferenceBindingToTemporary
? diag::err_lvalue_reference_bind_to_temporary
: diag::err_lvalue_reference_bind_to_unrelated)
+ << DestType.getNonReferenceType().isVolatileQualified()
<< DestType.getNonReferenceType()
<< Args[0]->getType()
<< Args[0]->getSourceRange();
diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
index cf3db5175f..d9c5d01401 100644
--- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
+++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp
@@ -68,17 +68,23 @@ void bind_lvalue_quals(volatile Base b, volatile Derived d,
volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'struct Base volatile' to a value of type 'struct Derived const volatile' drops qualifiers}}
volatile int &ir = ivc; // expected-error{{binding of reference to type 'int volatile' to a value of type 'int const volatile' drops qualifiers}}
+
+ const volatile Base &bcvr1 = b;
+ const volatile Base &bcvr2 = d;
}
void bind_lvalue_to_rvalue() {
Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Base'}}
Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a temporary of type 'struct Derived'}}
+ const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a temporary of type 'struct Base'}}
+ const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a temporary of type 'struct Derived'}}
int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
}
void bind_lvalue_to_unrelated(Unrelated ur) {
Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'struct Base' cannot bind to a value of unrelated type 'struct Unrelated'}}
+ const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'struct Base const volatile' cannot bind to a value of unrelated type 'struct Unrelated'}}
}
void bind_lvalue_to_conv_lvalue() {