From: Douglas Gregor Date: Fri, 18 Mar 2011 16:10:52 +0000 (+0000) Subject: Add an opt-in -Wheader-hygiene, which current diagnoses the use of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d6a49bb69fadcb04119433278c808797a87d2d31;p=clang Add an opt-in -Wheader-hygiene, which current diagnoses the use of global using directives in C++ headers, from Elliot Glaysher! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127881 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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, 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, 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; +}