diff options
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 6 | ||||
-rw-r--r-- | test/SemaCXX/warn-using-namespace-in-header.cpp | 9 | ||||
-rw-r--r-- | test/SemaCXX/warn-using-namespace-in-header.h | 15 |
5 files changed, 34 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 87c6c2d19e..d3cc08319a 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -109,6 +109,7 @@ def : DiagGroup<"stack-protector">; def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; def TautologicalCompare : DiagGroup<"tautological-compare">; +def HeaderHygiene : DiagGroup<"header-hygiene">; // Preprocessor warnings. def : DiagGroup<"builtin-macro-redefined">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c0d0642d63..a722f0514f 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2928,6 +2928,9 @@ def warn_overloaded_virtual : Warning< InGroup<OverloadedVirtual>, DefaultIgnore; def note_hidden_overloaded_virtual_declared_here : Note< "hidden overloaded virtual function %q0 declared here">; +def warn_using_directive_in_header : Warning< + "using namespace directive in global context in header">, + InGroup<HeaderHygiene>, DefaultIgnore; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 858a5f9251..8b7bbb6954 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3922,6 +3922,12 @@ Decl *Sema::ActOnUsingDirective(Scope *S, UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, SS.getWithLocInContext(Context), IdentLoc, Named, CommonAncestor); + + if (CurContext->getDeclKind() == Decl::TranslationUnit && + !SourceMgr.isFromMainFile(IdentLoc)) { + Diag(IdentLoc, diag::warn_using_directive_in_header); + } + PushUsingDirective(S, UDir); } else { Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); diff --git a/test/SemaCXX/warn-using-namespace-in-header.cpp b/test/SemaCXX/warn-using-namespace-in-header.cpp new file mode 100644 index 0000000000..393e097df5 --- /dev/null +++ b/test/SemaCXX/warn-using-namespace-in-header.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -Wheader-hygiene -verify %s + +#include "warn-using-namespace-in-header.h" + +namespace dont_warn {} +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}} diff --git a/test/SemaCXX/warn-using-namespace-in-header.h b/test/SemaCXX/warn-using-namespace-in-header.h new file mode 100644 index 0000000000..677c4ac51a --- /dev/null +++ b/test/SemaCXX/warn-using-namespace-in-header.h @@ -0,0 +1,15 @@ + + + + + +// Lots of vertical space to make the error line match up with the line of the +// expected line in the source file. +namespace warn_in_header_in_global_context {} +using namespace warn_in_header_in_global_context; + +// While we want to error on the previous using directive, we don't when we are +// inside a namespace +namespace dont_warn_here { +using namespace warn_in_header_in_global_context; +} |