Instantiate exception specifications when instantiating function types (other
than the type of a function declaration). We previously didn't instantiate these at all! This also covers the pathological case where the only mention of a parameter pack is within the exception specification; this gives us a second way (other than alias templates) to reach the horrible state where a type contains an unexpanded pack, but its canonical type does not. This is a re-commit of r219977: r219977 was reverted in r220038 because it hit a wrong-code bug in GCC 4.7.2. (That's gcc.gnu.org/PR56135, and affects any implicit lambda-capture of 'this' within a template.) r219977 was a re-commit of r217995, r218011, and r218053: r217995 was reverted in r218058 because it hit a rejects-valid bug in MSVC. (Incorrect overload resolution in the presence of using-declarations.) It was re-committed in r219977 with a workaround for the MSVC rejects-valid. r218011 was a workaround for an MSVC parser bug. (Incorrect desugaring of unbraced range-based for loop). llvm-svn: 221750
This commit is contained in:
@@ -720,10 +720,11 @@ static bool CheckSpecForTypesEquivalent(Sema &S,
|
||||
/// assignment and override compatibility check. We do not check the parameters
|
||||
/// of parameter function pointers recursively, as no sane programmer would
|
||||
/// even be able to write such a function type.
|
||||
bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
|
||||
const FunctionProtoType *Target, SourceLocation TargetLoc,
|
||||
const FunctionProtoType *Source, SourceLocation SourceLoc)
|
||||
{
|
||||
bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID,
|
||||
const FunctionProtoType *Target,
|
||||
SourceLocation TargetLoc,
|
||||
const FunctionProtoType *Source,
|
||||
SourceLocation SourceLoc) {
|
||||
if (CheckSpecForTypesEquivalent(
|
||||
*this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(),
|
||||
Target->getReturnType(), TargetLoc, Source->getReturnType(),
|
||||
@@ -744,23 +745,30 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
|
||||
{
|
||||
bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
|
||||
// First we check for applicability.
|
||||
// Target type must be a function, function pointer or function reference.
|
||||
const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
|
||||
if (!ToFunc)
|
||||
if (!ToFunc || ToFunc->hasDependentExceptionSpec())
|
||||
return false;
|
||||
|
||||
// SourceType must be a function or function pointer.
|
||||
const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
|
||||
if (!FromFunc)
|
||||
if (!FromFunc || FromFunc->hasDependentExceptionSpec())
|
||||
return false;
|
||||
|
||||
// Now we've got the correct types on both sides, check their compatibility.
|
||||
// This means that the source of the conversion can only throw a subset of
|
||||
// the exceptions of the target, and any exception specs on arguments or
|
||||
// return types must be equivalent.
|
||||
//
|
||||
// FIXME: If there is a nested dependent exception specification, we should
|
||||
// not be checking it here. This is fine:
|
||||
// template<typename T> void f() {
|
||||
// void (*p)(void (*) throw(T));
|
||||
// void (*q)(void (*) throw(int)) = p;
|
||||
// }
|
||||
// ... because it might be instantiated with T=int.
|
||||
return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
|
||||
PDiag(), ToFunc,
|
||||
From->getSourceRange().getBegin(),
|
||||
|
||||
Reference in New Issue
Block a user