diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-09-30 00:48:50 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-09-30 00:48:50 +0000 |
commit | a91de375f2785352fa26407ef85a4347bccea98e (patch) | |
tree | 8d42f3d0cd42c6387dc7fc3fa077af01b61a994e /clang/lib/Sema/SemaExceptionSpec.cpp | |
parent | b189b5c5359e2bd2143bacde3d73459fd84186bf (diff) | |
download | bcm5719-llvm-a91de375f2785352fa26407ef85a4347bccea98e.tar.gz bcm5719-llvm-a91de375f2785352fa26407ef85a4347bccea98e.zip |
Promote a warning on ill-formed code (redeclaration missing an exception
specification) to an error. No compiler other than Clang seems to allow this,
and it doesn't seem like a useful thing to accept as an extension in general.
The current behavior was added for PR5957, where the problem was specifically
related to mismatches of the exception specification on the implicitly-declared
global operator new and delete. To retain that workaround, we downgrade the
error to an ExtWarn when the declaration is of a replaceable global allocation
function.
Now that this is an error, stop trying (and failing) to recover from a missing
computed noexcept specification. That recovery didn't work, and led to crashes
in code like the added testcase.
llvm-svn: 248867
Diffstat (limited to 'clang/lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 6182ad934e8..8e1c88458e3 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -270,16 +270,31 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { FunctionProtoType::ExceptionSpecInfo ESI = OldProto->getExceptionSpecType(); if (ESI.Type == EST_Dynamic) { ESI.Exceptions = OldProto->exceptions(); - } else if (ESI.Type == EST_ComputedNoexcept) { - // FIXME: We can't just take the expression from the old prototype. It - // likely contains references to the old prototype's parameters. } - // Update the type of the function with the appropriate exception - // specification. - New->setType(Context.getFunctionType( - NewProto->getReturnType(), NewProto->getParamTypes(), - NewProto->getExtProtoInfo().withExceptionSpec(ESI))); + if (ESI.Type == EST_ComputedNoexcept) { + // For computed noexcept, we can't just take the expression from the old + // prototype. It likely contains references to the old prototype's + // parameters. + New->setInvalidDecl(); + } else { + // Update the type of the function with the appropriate exception + // specification. + New->setType(Context.getFunctionType( + NewProto->getReturnType(), NewProto->getParamTypes(), + NewProto->getExtProtoInfo().withExceptionSpec(ESI))); + } + + // Allow missing exception specifications in redeclarations as an extension, + // when declaring a replaceable global allocation function. + if (New->isReplaceableGlobalAllocationFunction() && + ESI.Type != EST_ComputedNoexcept) { + DiagID = diag::ext_missing_exception_specification; + ReturnValueOnError = false; + } else { + DiagID = diag::err_missing_exception_specification; + ReturnValueOnError = true; + } // Warn about the lack of exception specification. SmallString<128> ExceptionSpecString; @@ -322,17 +337,18 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { SourceLocation FixItLoc; if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); - if (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) - FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd()); + // FIXME: Preserve enough information so that we can produce a correct fixit + // location when there is a trailing return type. + if (auto FTLoc = TL.getAs<FunctionProtoTypeLoc>()) + if (!FTLoc.getTypePtr()->hasTrailingReturn()) + FixItLoc = getLocForEndOfToken(FTLoc.getLocalRangeEnd()); } if (FixItLoc.isInvalid()) - Diag(New->getLocation(), diag::warn_missing_exception_specification) + Diag(New->getLocation(), DiagID) << New << OS.str(); else { - // FIXME: This will get more complicated with C++0x - // late-specified return types. - Diag(New->getLocation(), diag::warn_missing_exception_specification) + Diag(New->getLocation(), DiagID) << New << OS.str() << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); } @@ -340,7 +356,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { if (!Old->getLocation().isInvalid()) Diag(Old->getLocation(), diag::note_previous_declaration); - return false; + return ReturnValueOnError; } /// CheckEquivalentExceptionSpec - Check if the two types have equivalent |