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() const; + ASTContext &getASTContext() const LLVM_READONLY; void setAccess(AccessSpecifier AS) { @@ -1156,6 +1158,8 @@ return DeclKind == Decl::Namespace; } + bool isStdNamespace() 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<NamespaceDecl>(DC->getRedeclContext()); - return ND && isNamed(ND, "std") && - ND->getParent()->getRedeclContext()->isTranslationUnit(); -} - bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) return false; @@ -2354,7 +2348,7 @@ 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(); } FunctionDecl * Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -251,6 +251,10 @@ return false; } +bool Decl::isInStdNamespace() const { + return getDeclContext()->isStdNamespace(); +} + TranslationUnitDecl *Decl::getTranslationUnitDecl() { if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this)) return TUD; @@ -790,6 +794,23 @@ return getParent(); } +bool DeclContext::isStdNamespace() const { + const DeclContext *DC = getRedeclContext(); + + if (!DC->isNamespace()) + return false; + + const NamespaceDecl *ND = cast<NamespaceDecl>(DC); + if (ND->isInline()) + return DC->getParent()->isStdNamespace(); + + if (!DC->getParent()->getRedeclContext()->isTranslationUnit()) + return false; + + const IdentifierInfo *II = ND->getIdentifier(); + return II && II->isStr("std"); +} + bool DeclContext::isInlineNamespace() const { return isNamespace() && cast<NamespaceDecl>(this)->isInline(); 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<NamespaceDecl>(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()) { copyInfo(Call->getArg(0), Call, CS_Consumed); return; } Index: lib/Sema/SemaExceptionSpec.cpp =================================================================== --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -471,13 +471,8 @@ // It's called bad_alloc, but is it in std? DeclContext* DC = ExRecord->getDeclContext(); DC = DC->getEnclosingNamespaceContext(); - if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) { - IdentifierInfo* NSName = NS->getIdentifier(); - DC = DC->getParent(); - if (NSName && NSName->getName() == "std" && - DC->getEnclosingNamespaceContext()->isTranslationUnit()) { - return false; - } + if (DC->isStdNamespace()) { + return false; } } } Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -880,10 +880,7 @@ cast<NamespaceDecl>(DCParent)->getIdentifier() && cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) { DeclContext *DCParent2 = DCParent->getParent(); - if (DCParent2->isNamespace() && - cast<NamespaceDecl>(DCParent2)->getIdentifier() && - cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") && - DCParent2->getParent()->isTranslationUnit()) + if (DCParent2->isStdNamespace()) 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 @@ -1503,21 +1503,6 @@ return event; } - -// FIXME: Copied from ExprEngineCallAndReturn.cpp. -static bool isInStdNamespace(const Decl *D) { - const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext(); - const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); - if (!ND) - return false; - - while (const NamespaceDecl *Parent = dyn_cast<NamespaceDecl>(ND->getParent())) - ND = Parent; - - return ND->getName() == "std"; -} - - PathDiagnosticPiece * LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, const ExplodedNode *N, @@ -1528,7 +1513,7 @@ AnalyzerOptions &Options = Eng.getAnalysisManager().options; const Decl *D = N->getLocationContext()->getDecl(); - if (isInStdNamespace(D)) { + if (D->getDeclContext()->getEnclosingNamespaceContext()->isStdNamespace()) { // Skip reports within the 'std' namespace. Although these can sometimes be // the user's fault, we currently don't report them very well, and // Note that this will not help for any other data structure libraries, like Index: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -382,21 +382,6 @@ } -static bool IsInStdNamespace(const FunctionDecl *FD) { - const DeclContext *DC = FD->getEnclosingNamespaceContext(); - const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); - if (!ND) - return false; - - while (const DeclContext *Parent = ND->getParent()) { - if (!isa<NamespaceDecl>(Parent)) - break; - ND = cast<NamespaceDecl>(Parent); - } - - return ND->getName() == "std"; -} - // The GDM component containing the dynamic dispatch bifurcation info. When // the exact type of the receiver is not known, we want to explore both paths - // one on which we do inline it and the other one on which we don't. This is @@ -760,7 +745,7 @@ // Conditionally control the inlining of C++ standard library functions. if (!Opts.mayInlineCXXStandardLibrary()) if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation())) - if (IsInStdNamespace(FD)) + if (FD->getEnclosingNamespaceContext()->isStdNamespace()) return false; // Conditionally control the inlining of methods on objects that look