[cfe-commits] r127688 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaExceptionSpec.cpp test/CXX/except/except.spec/p3.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Tue Mar 15 12:52:30 PDT 2011
Author: cornedbee
Date: Tue Mar 15 14:52:30 2011
New Revision: 127688
URL: http://llvm.org/viewvc/llvm-project?rev=127688&view=rev
Log:
Implement a hack to work around the changing exception specification of operator new in C++0x.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
cfe/trunk/test/CXX/except/except.spec/p3.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=127688&r1=127687&r2=127688&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Mar 15 14:52:30 2011
@@ -758,7 +758,8 @@
const FunctionProtoType *New, SourceLocation NewLoc,
bool *MissingExceptionSpecification = 0,
bool *MissingEmptyExceptionSpecification = 0,
- bool AllowNoexceptAllMatchWithNoSpec = false);
+ bool AllowNoexceptAllMatchWithNoSpec = false,
+ bool IsOperatorNew = false);
bool CheckExceptionSpecSubset(
const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
const FunctionProtoType *Superset, SourceLocation SuperLoc,
Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=127688&r1=127687&r2=127688&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Tue Mar 15 14:52:30 2011
@@ -96,6 +96,8 @@
}
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 @@
New->getLocation(),
&MissingExceptionSpecification,
&MissingEmptyExceptionSpecification,
- /*AllowNoexceptAllMatchWithNoSpec=*/true))
+ /*AllowNoexceptAllMatchWithNoSpec=*/true,
+ IsOperatorNew))
return false;
// The failure was something other than an empty exception
@@ -272,7 +275,8 @@
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 @@
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) {
Modified: cfe/trunk/test/CXX/except/except.spec/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p3.cpp?rev=127688&r1=127687&r2=127688&view=diff
==============================================================================
--- cfe/trunk/test/CXX/except/except.spec/p3.cpp (original)
+++ cfe/trunk/test/CXX/except/except.spec/p3.cpp Tue Mar 15 14:52:30 2011
@@ -92,3 +92,14 @@
extern void (*r21)() throw(int); // expected-note {{previous declaration}}
extern void (*r21)() noexcept(true); // expected-error {{does not match}}
+
+
+// As a very special workaround, we allow operator new to match no spec
+// with a throw(bad_alloc) spec, because C++0x makes an incompatible change
+// here.
+namespace std { class bad_alloc {}; }
+void* operator new(unsigned long) throw(std::bad_alloc);
+void* operator new(unsigned long);
+void* operator new[](unsigned long) throw(std::bad_alloc);
+void* operator new[](unsigned long);
+
More information about the cfe-commits
mailing list