summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExceptionSpec.cpp
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2011-03-15 19:52:30 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2011-03-15 19:52:30 +0000
commitcb5dd007964d7cb0e50b83caf90c2d0da8fecad4 (patch)
tree395655ffd7833c255ebfff7cdfc4c8c58e993dc5 /clang/lib/Sema/SemaExceptionSpec.cpp
parentcdb2ae587a469387f845b62c4397d7eed986442c (diff)
downloadbcm5719-llvm-cb5dd007964d7cb0e50b83caf90c2d0da8fecad4.tar.gz
bcm5719-llvm-cb5dd007964d7cb0e50b83caf90c2d0da8fecad4.zip
Implement a hack to work around the changing exception specification of operator new in C++0x.
llvm-svn: 127688
Diffstat (limited to 'clang/lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp40
1 files changed, 38 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 285f400b07b..1d21b9760c7 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -96,6 +96,8 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
}
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+ OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
+ bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
bool MissingExceptionSpecification = false;
bool MissingEmptyExceptionSpecification = false;
if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec),
@@ -106,7 +108,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
New->getLocation(),
&MissingExceptionSpecification,
&MissingEmptyExceptionSpecification,
- /*AllowNoexceptAllMatchWithNoSpec=*/true))
+ /*AllowNoexceptAllMatchWithNoSpec=*/true,
+ IsOperatorNew))
return false;
// The failure was something other than an empty exception
@@ -272,7 +275,8 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
SourceLocation NewLoc,
bool *MissingExceptionSpecification,
bool*MissingEmptyExceptionSpecification,
- bool AllowNoexceptAllMatchWithNoSpec) {
+ bool AllowNoexceptAllMatchWithNoSpec,
+ bool IsOperatorNew) {
// Just completely ignore this under -fno-exceptions.
if (!getLangOptions().CXXExceptions)
return false;
@@ -374,6 +378,38 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (OldNonThrowing && NewNonThrowing)
return false;
+ // As a special compatibility feature, under C++0x we accept no spec and
+ // throw(std::bad_alloc) as equivalent for operator new and operator new[].
+ // This is because the implicit declaration changed, but old code would break.
+ if (getLangOptions().CPlusPlus0x && IsOperatorNew) {
+ const FunctionProtoType *WithExceptions = 0;
+ if (OldEST == EST_None && NewEST == EST_Dynamic)
+ WithExceptions = New;
+ else if (OldEST == EST_Dynamic && NewEST == EST_None)
+ WithExceptions = Old;
+ if (WithExceptions && WithExceptions->getNumExceptions() == 1) {
+ // One has no spec, the other throw(something). If that something is
+ // std::bad_alloc, all conditions are met.
+ QualType Exception = *WithExceptions->exception_begin();
+ if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) {
+ IdentifierInfo* Name = ExRecord->getIdentifier();
+ if (Name && Name->getName() == "bad_alloc") {
+ // It's called bad_alloc, but is it in std?
+ DeclContext* DC = ExRecord->getDeclContext();
+ while (DC && !isa<NamespaceDecl>(DC))
+ DC = DC->getParent();
+ if (DC) {
+ NamespaceDecl* NS = cast<NamespaceDecl>(DC);
+ IdentifierInfo* NSName = NS->getIdentifier();
+ if (NSName && NSName->getName() == "std" &&
+ isa<TranslationUnitDecl>(NS->getParent()))
+ return false;
+ }
+ }
+ }
+ }
+ }
+
// At this point, the only remaining valid case is two matching dynamic
// specifications. We return here unless both specifications are dynamic.
if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) {
OpenPOWER on IntegriCloud