diff options
Diffstat (limited to 'clang/lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r-- | clang/lib/Sema/SemaExceptionSpec.cpp | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index a81ef517954..74c5b420c5e 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -43,23 +43,36 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) { auto *RD = dyn_cast<CXXRecordDecl>(CurContext); // All the problem cases are member functions named "swap" within class - // templates declared directly within namespace std. - if (!RD || !getStdNamespace() || - !RD->getEnclosingNamespaceContext()->Equals(getStdNamespace()) || - !RD->getIdentifier() || !RD->getDescribedClassTemplate() || + // templates declared directly within namespace std or std::__debug or + // std::__profile. + if (!RD || !RD->getIdentifier() || !RD->getDescribedClassTemplate() || !D.getIdentifier() || !D.getIdentifier()->isStr("swap")) return false; + auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext()); + if (!ND) + return false; + + bool IsInStd = ND->isStdNamespace(); + if (!IsInStd) { + // This isn't a direct member of namespace std, but it might still be + // libstdc++'s std::__debug::array or std::__profile::array. + IdentifierInfo *II = ND->getIdentifier(); + if (!II || !(II->isStr("__debug") || II->isStr("__profile")) || + !ND->isInStdNamespace()) + return false; + } + // Only apply this hack within a system header. if (!Context.getSourceManager().isInSystemHeader(D.getLocStart())) return false; return llvm::StringSwitch<bool>(RD->getIdentifier()->getName()) .Case("array", true) - .Case("pair", true) - .Case("priority_queue", true) - .Case("stack", true) - .Case("queue", true) + .Case("pair", IsInStd) + .Case("priority_queue", IsInStd) + .Case("stack", IsInStd) + .Case("queue", IsInStd) .Default(false); } |