Improve -Wheader-hygiene to warn about using directives inside linkage

specifications within the global scope, from Elliot Glaysher.

llvm-svn: 128352
This commit is contained in:
Douglas Gregor 2011-03-26 22:25:30 +00:00
parent e466345675
commit a172e08824
3 changed files with 59 additions and 1 deletions

View File

@ -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);
}

View File

@ -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}}

View File

@ -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;
}