diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-06-29 17:53:46 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-06-29 17:53:46 +0000 |
commit | 6699220f73f11e471b5e5aa42eaf064afeaa079e (patch) | |
tree | 6663c5dc426db19b2be9abbc586ad8799806c94a /lib/Sema/SemaDeclCXX.cpp | |
parent | 6623584c0ec508110d75572eef092bf98fedf3f4 (diff) |
Allow a using directive to refer to the implicitly-defined namespace
"std", with a warning, to improve GCC compatibility. Fixes PR7517.
As a drive-by, add typo correction for using directives.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107172 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index c6f149e8fe..66d0bf5bd4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3452,6 +3452,21 @@ void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) { PopDeclContext(); } +/// \brief Retrieve the special "std" namespace, which may require us to +/// implicitly define the namespace. +NamespaceDecl *Sema::getStdNamespace() { + if (!StdNamespace) { + // The "std" namespace has not yet been defined, so build one implicitly. + StdNamespace = NamespaceDecl::Create(Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + &PP.getIdentifierTable().get("std")); + StdNamespace->setImplicit(true); + } + + return StdNamespace; +} + Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -3465,13 +3480,46 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); UsingDirectiveDecl *UDir = 0; - + NestedNameSpecifier *Qualifier = 0; + if (SS.isSet()) + Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + // Lookup namespace name. LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); LookupParsedName(R, S, &SS); if (R.isAmbiguous()) return DeclPtrTy(); + if (R.empty()) { + // Allow "using namespace std;" or "using namespace ::std;" even if + // "std" hasn't been defined yet, for GCC compatibility. + if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && + NamespcName->isStr("std")) { + Diag(IdentLoc, diag::ext_using_undefined_std); + R.addDecl(getStdNamespace()); + R.resolveKind(); + } + // Otherwise, attempt typo correction. + else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, + CTC_NoKeywords, 0)) { + if (R.getAsSingle<NamespaceDecl>() || + R.getAsSingle<NamespaceAliasDecl>()) { + if (DeclContext *DC = computeDeclContext(SS, false)) + Diag(IdentLoc, diag::err_using_directive_member_suggest) + << NamespcName << DC << Corrected << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + else + Diag(IdentLoc, diag::err_using_directive_suggest) + << NamespcName << Corrected + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here) + << Corrected; + + NamespcName = Corrected.getAsIdentifierInfo(); + } + } + } + if (!R.empty()) { NamedDecl *Named = R.getFoundDecl(); assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named)) |