Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -397,6 +397,8 @@ bool isInAnonymousNamespace() const; + bool isInStdNamespace(bool IncludeInlineNamespaces = false) const; + ASTContext &getASTContext() const LLVM_READONLY; void setAccess(AccessSpecifier AS) { @@ -1156,6 +1158,8 @@ return DeclKind == Decl::Namespace; } + bool isStdNamespace(bool IncludeInlineNamespace = false) const; + bool isInlineNamespace() const; /// \brief Determines whether this context is dependent on a Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -2309,12 +2309,6 @@ return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy); } -static bool isNamespaceStd(const DeclContext *DC) { - const NamespaceDecl *ND = dyn_cast(DC->getRedeclContext()); - return ND && isNamed(ND, "std") && - ND->getParent()->getRedeclContext()->isTranslationUnit(); -} - bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) return false; @@ -2352,9 +2346,9 @@ Ty = Ty->getPointeeType(); if (Ty.getCVRQualifiers() != Qualifiers::Const) return false; - // FIXME: Recognise nothrow_t in an inline namespace inside std? const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return RD && isNamed(RD, "nothrow_t") && isNamespaceStd(RD->getDeclContext()); + return RD && isNamed(RD, "nothrow_t") && + RD->isInStdNamespace(true /*IncludeInlineNamespace*/); } FunctionDecl * Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -251,6 +251,10 @@ return false; } +bool Decl::isInStdNamespace(bool IncludeInlineNamespace) const { + return getDeclContext()->isStdNamespace(IncludeInlineNamespace); +} + TranslationUnitDecl *Decl::getTranslationUnitDecl() { if (TranslationUnitDecl *TUD = dyn_cast(this)) return TUD; @@ -795,6 +799,24 @@ cast(this)->isInline(); } +bool DeclContext::isStdNamespace(bool IncludeInlineNamespace) const { + if (!isNamespace()) + return false; + + const NamespaceDecl *ND = cast(this); + if (ND->isInline()) { + if (!IncludeInlineNamespace) + return false; + return ND->getParent()->isStdNamespace(); + } + + if (!getParent()->getRedeclContext()->isTranslationUnit()) + return false; + + const IdentifierInfo *II = ND->getIdentifier(); + return II && II->isStr("std"); +} + bool DeclContext::isDependentContext() const { if (isFileContext()) return false; Index: lib/Analysis/Consumed.cpp =================================================================== --- lib/Analysis/Consumed.cpp +++ lib/Analysis/Consumed.cpp @@ -745,16 +745,6 @@ } } -static bool isStdNamespace(const DeclContext *DC) { - if (!DC->isNamespace()) return false; - while (DC->getParent()->isNamespace()) - DC = DC->getParent(); - const NamespaceDecl *ND = dyn_cast(DC); - - return ND && ND->getName() == "std" && - ND->getDeclContext()->isTranslationUnit(); -} - void ConsumedStmtVisitor::VisitCallExpr(const CallExpr *Call) { const FunctionDecl *FunDecl = Call->getDirectCallee(); if (!FunDecl) @@ -764,7 +754,7 @@ // TODO: Make this more specific. (Deferred) if (Call->getNumArgs() == 1 && FunDecl->getNameAsString() == "move" && - isStdNamespace(FunDecl->getDeclContext())) { + FunDecl->isInStdNamespace(true /*IncludeInlineNamespace*/)) { copyInfo(Call->getArg(0), Call, CS_Consumed); return; } Index: lib/Sema/SemaExceptionSpec.cpp =================================================================== --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -469,15 +469,8 @@ IdentifierInfo* Name = ExRecord->getIdentifier(); if (Name && Name->getName() == "bad_alloc") { // It's called bad_alloc, but is it in std? - DeclContext* DC = ExRecord->getDeclContext(); - DC = DC->getEnclosingNamespaceContext(); - if (NamespaceDecl* NS = dyn_cast(DC)) { - IdentifierInfo* NSName = NS->getIdentifier(); - DC = DC->getParent(); - if (NSName && NSName->getName() == "std" && - DC->getEnclosingNamespaceContext()->isTranslationUnit()) { - return false; - } + if (ExRecord->isInStdNamespace()) { + return false; } } } Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -879,11 +879,7 @@ if (DCParent->isNamespace() && cast(DCParent)->getIdentifier() && cast(DCParent)->getIdentifier()->isStr("tr1")) { - DeclContext *DCParent2 = DCParent->getParent(); - if (DCParent2->isNamespace() && - cast(DCParent2)->getIdentifier() && - cast(DCParent2)->getIdentifier()->isStr("std") && - DCParent2->getParent()->isTranslationUnit()) + if (cast(DCParent)->isInStdNamespace()) Complain = false; } } Index: lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp +++ lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp @@ -58,7 +58,7 @@ const TypedefNameDecl *TD = TT->getDecl(); - if (!InNamespace(TD, "std")) + if (!TD->isInStdNamespace()) return false; return TD->getName() == "string"; Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1514,7 +1514,7 @@ while (const NamespaceDecl *Parent = dyn_cast(ND->getParent())) ND = Parent; - return ND->getName() == "std"; + return ND->isStdNamespace(); } Index: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -387,14 +387,14 @@ const NamespaceDecl *ND = dyn_cast(DC); if (!ND) return false; - + while (const DeclContext *Parent = ND->getParent()) { if (!isa(Parent)) break; ND = cast(Parent); } - return ND->getName() == "std"; + return ND->isStdNamespace(); } // The GDM component containing the dynamic dispatch bifurcation info. When