diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-09-15 22:30:29 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-09-15 22:30:29 +0000 |
commit | 7adb10fa317cd7eacb0959f775e77353d4f24ad1 (patch) | |
tree | 80296249b2d8d4f099fd9e8646743e59f91f342a /lib/Sema/SemaDecl.cpp | |
parent | 291fbde2da2e022e47127472f3b5be8747d22c27 (diff) |
When implicitly declaring operators new, new[], delete, and delete[],
give them the appropriate exception specifications. This,
unfortunately, requires us to maintain and/or implicitly generate
handles to namespace "std" and the class "std::bad_alloc". However,
every other approach I've come up with was more hackish, and this
standard requirement itself is quite the hack.
Fixes PR4829.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81939 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c7bd31160a..696c10a941 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -521,18 +521,6 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } -/// GetStdNamespace - This method gets the C++ "std" namespace. This is where -/// everything from the standard library is defined. -NamespaceDecl *Sema::GetStdNamespace() { - if (!StdNamespace) { - IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std"); - DeclContext *Global = Context.getTranslationUnitDecl(); - Decl *Std = LookupQualifiedName(Global, StdIdent, LookupNamespaceName); - StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std); - } - return StdNamespace; -} - /// MergeTypeDefDecl - We just parsed a typedef 'New' which has the /// same name and scope as a previous declaration 'Old'. Figure out /// how to resolve this situation, merging decls or emitting @@ -3990,7 +3978,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; NamedDecl *PrevDecl = 0; - + bool isStdBadAlloc = false; bool Invalid = false; if (Name && SS.isNotEmpty()) { @@ -4067,6 +4055,19 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, PrevDecl = 0; } + if (getLangOptions().CPlusPlus && Name && DC && StdNamespace && + DC->Equals(StdNamespace) && Name->isStr("bad_alloc")) { + // This is a declaration of or a reference to "std::bad_alloc". + isStdBadAlloc = true; + + if (!PrevDecl && StdBadAlloc) { + // std::bad_alloc has been implicitly declared (but made invisible to + // name lookup). Fill in this implicit declaration as the previous + // declaration, so that the declarations get chained appropriately. + PrevDecl = StdBadAlloc; + } + } + if (PrevDecl) { // Check whether the previous declaration is usable. (void)DiagnoseUseOfDecl(PrevDecl, NameLoc); @@ -4253,11 +4254,14 @@ CreateNewDecl: // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: // struct X { int A; } D; D should chain to X. - if (getLangOptions().CPlusPlus) + if (getLangOptions().CPlusPlus) { // FIXME: Look for a way to use RecordDecl for simple structs. New = CXXRecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, cast_or_null<CXXRecordDecl>(PrevDecl)); - else + + if (isStdBadAlloc && (!StdBadAlloc || StdBadAlloc->isImplicit())) + StdBadAlloc = cast<CXXRecordDecl>(New); + } else New = RecordDecl::Create(Context, Kind, SearchDC, Loc, Name, KWLoc, cast_or_null<RecordDecl>(PrevDecl)); } |