Semantic analysis, ASTs, and unqualified name lookup support for C++
using directives, from Piotr Rak!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63646 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 296adc1..201d8b3 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1433,21 +1433,59 @@
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(NamespcName && "Invalid NamespcName.");
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
+ assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
- // FIXME: This still requires lot more checks, and AST support.
+ UsingDirectiveDecl *UDir = 0;
// Lookup namespace name.
- Decl *NS = LookupParsedName(S, &SS, NamespcName, LookupNamespaceName, false);
-
- if (NS) {
+ LookupResult R = LookupParsedName(S, &SS, NamespcName,
+ LookupNamespaceName, false);
+ if (R.isAmbiguous()) {
+ DiagnoseAmbiguousLookup(R, NamespcName, IdentLoc);
+ return 0;
+ }
+ if (Decl *NS = R) {
assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
+ // C++ [namespace.udir]p1:
+ // A using-directive specifies that the names in the nominated
+ // namespace can be used in the scope in which the
+ // using-directive appears after the using-directive. During
+ // unqualified name lookup (3.4.1), the names appear as if they
+ // were declared in the nearest enclosing namespace which
+ // contains both the using-directive and the nominated
+ // namespace. [Note: in this context, “contains” means “contains
+ // directly or indirectly”. ]
+
+ // Find enclosing context containing both using-directive and
+ // nominated namespace.
+ DeclContext *CommonAncestor = cast<DeclContext>(NS);
+ while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
+ CommonAncestor = CommonAncestor->getParent();
+
+ UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc,
+ NamespcLoc, IdentLoc,
+ cast<NamespaceDecl>(NS),
+ CommonAncestor);
+ PushUsingDirective(S, UDir);
} else {
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
}
- // FIXME: We ignore AttrList for now, and delete it to avoid leak.
+ // FIXME: We ignore attributes for now.
delete AttrList;
- return 0;
+ return UDir;
+}
+
+void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
+ // If scope has associated entity, then using directive is at namespace
+ // or translation unit scope. We add UsingDirectiveDecls, into
+ // it's lookup structure.
+ if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()))
+ Ctx->addDecl(UDir);
+ else
+ // Otherwise it is block-sope. using-directives will affect lookup
+ // only to the end of scope.
+ S->PushUsingDirective(UDir);
}
/// AddCXXDirectInitializerToDecl - This action is called immediately after