diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2011-03-15 19:52:30 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2011-03-15 19:52:30 +0000 |
commit | cb5dd007964d7cb0e50b83caf90c2d0da8fecad4 (patch) | |
tree | 395655ffd7833c255ebfff7cdfc4c8c58e993dc5 /clang/lib/Sema/SemaExceptionSpec.cpp | |
parent | cdb2ae587a469387f845b62c4397d7eed986442c (diff) | |
download | bcm5719-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.cpp | 40 |
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) { |