aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-09-15 22:30:29 +0000
committerDouglas Gregor <dgregor@apple.com>2009-09-15 22:30:29 +0000
commit7adb10fa317cd7eacb0959f775e77353d4f24ad1 (patch)
tree80296249b2d8d4f099fd9e8646743e59f91f342a /lib/Sema/SemaDecl.cpp
parent291fbde2da2e022e47127472f3b5be8747d22c27 (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.cpp34
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));
}