diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-10-16 23:00:46 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-10-16 23:00:46 +0000 |
commit | 4dca855aadabe4348a36e07e20e41605eedcf212 (patch) | |
tree | 10fad724ebcba8ab12d674a6bc8a933dcba3908f /lib/Sema/SemaExceptionSpec.cpp | |
parent | dc6d797fc1dcf1a26aceaf7422d0f5833108668c (diff) |
Re-commit r217995 and follow-up patches (r217997, r218011, r218053). These were
reverted in r218058 because they triggered a rejects-valid bug in MSVC.
Original commit message from r217995:
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219977 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r-- | lib/Sema/SemaExceptionSpec.cpp | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index e4963b13d6..4e4de5a3e7 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -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(), |