From: Douglas Gregor Date: Sat, 26 Mar 2011 22:25:30 +0000 (+0000) Subject: Improve -Wheader-hygiene to warn about using directives inside linkage X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9172aa685f3a1cbf991a2c1cd40905e4d64bfdf6;p=clang Improve -Wheader-hygiene to warn about using directives inside linkage specifications within the global scope, from Elliot Glaysher. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128352 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b193c60218..07d60caf43 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3817,6 +3817,19 @@ NamespaceDecl *Sema::getOrCreateStdNamespace() { return getStdNamespace(); } +/// \brief Determine whether a using statement is in a context where it will be +/// apply in all contexts. +static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { + switch (CurContext->getDeclKind()) { + case Decl::TranslationUnit: + return true; + case Decl::LinkageSpec: + return IsUsingDirectiveInToplevelContext(CurContext->getParent()); + default: + return false; + } +} + Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -3902,7 +3915,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SS.getWithLocInContext(Context), IdentLoc, Named, CommonAncestor); - if (CurContext->getDeclKind() == Decl::TranslationUnit && + if (IsUsingDirectiveInToplevelContext(CurContext) && !SourceMgr.isFromMainFile(IdentLoc)) { Diag(IdentLoc, diag::warn_using_directive_in_header); } diff --git a/test/SemaCXX/warn-using-namespace-in-header.cpp b/test/SemaCXX/warn-using-namespace-in-header.cpp index 393e097df5..e040ca74cb 100644 --- a/test/SemaCXX/warn-using-namespace-in-header.cpp +++ b/test/SemaCXX/warn-using-namespace-in-header.cpp @@ -7,3 +7,21 @@ using namespace dont_warn; // Warning is actually in the header but only the cpp file gets scanned. // expected-warning {{using namespace directive in global context in header}} + + + + + + + + + +// Warn inside linkage specs too. +// expected-warning {{using namespace directive in global context in header}} + + + + + + +// expected-warning {{using namespace directive in global context in header}} diff --git a/test/SemaCXX/warn-using-namespace-in-header.h b/test/SemaCXX/warn-using-namespace-in-header.h index 677c4ac51a..57bb5d91be 100644 --- a/test/SemaCXX/warn-using-namespace-in-header.h +++ b/test/SemaCXX/warn-using-namespace-in-header.h @@ -13,3 +13,30 @@ using namespace warn_in_header_in_global_context; namespace dont_warn_here { using namespace warn_in_header_in_global_context; } + +// We should warn in toplevel extern contexts. +namespace warn_inside_linkage {} +extern "C++" { +using namespace warn_inside_linkage; +} + +// This is really silly, but we should warn on it: +extern "C++" { +extern "C" { +extern "C++" { +using namespace warn_inside_linkage; +} +} +} + +// But we shouldn't warn in extern contexts inside namespaces. +namespace dont_warn_here { +extern "C++" { +using namespace warn_in_header_in_global_context; +} +} + +// We also shouldn't warn in case of functions. +inline void foo() { + using namespace warn_in_header_in_global_context; +}