From e861bac059d598cba212b4ca447339af11fbc44e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 25 Aug 2009 22:51:20 +0000 Subject: Improve support for out-of-line definitions of nested templates and their members, including member class template, member function templates, and member classes and functions of member templates. To actually parse the nested-name-specifiers that qualify the name of an out-of-line definition of a member template, e.g., template template X Outer::Inner1::foo(Y) { return X(); } we need to look for the template names (e.g., "Inner1") as a member of the current instantiation (Outer), even before we have entered the scope of the current instantiation. Since we can't do this in general (i.e., we should not be looking into all dependent nested-name-specifiers as if they were the current instantiation), we rely on the parser to tell us when it is parsing a declaration specifier sequence, and, therefore, when we should consider the current scope specifier to be a current instantiation. Printing of complicated, dependent nested-name-specifiers may be somewhat broken by this commit; I'll add tests for this issue and fix the problem (if it still exists) in a subsequent commit. llvm-svn: 80044 --- clang/lib/Sema/SemaCXXScopeSpec.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'clang/lib/Sema/SemaCXXScopeSpec.cpp') diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 188957176b6..9c9bff8a085 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -48,11 +48,11 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, return Record; if (EnteringContext) { - // We are entering the context of the nested name specifier, so try to - // match the nested name specifier to either a primary class template - // or a class template partial specialization. if (const TemplateSpecializationType *SpecType = dyn_cast_or_null(NNS->getAsType())) { + // We are entering the context of the nested name specifier, so try to + // match the nested name specifier to either a primary class template + // or a class template partial specialization. if (ClassTemplateDecl *ClassTemplate = dyn_cast_or_null( SpecType->getTemplateName().getAsTemplateDecl())) { @@ -74,6 +74,10 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, = ClassTemplate->findPartialSpecialization(ContextType)) return PartialSpec; } + } else if (const RecordType *RecordT + = dyn_cast_or_null(NNS->getAsType())) { + // The nested name specifier refers to a member of a class template. + return RecordT->getDecl(); } std::string NNSString; @@ -260,17 +264,14 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, const CXXScopeSpec &SS, SourceLocation IdLoc, SourceLocation CCLoc, - IdentifierInfo &II) { + IdentifierInfo &II, + bool EnteringContext) { NestedNameSpecifier *Prefix = static_cast(SS.getScopeRep()); - // If the prefix already refers to an unknown specialization, there - // is no name lookup to perform. Just build the resulting - // nested-name-specifier. - if (Prefix && isUnknownSpecialization(SS)) - return NestedNameSpecifier::Create(Context, Prefix, &II); - - NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName); + NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName, + false, false, SourceLocation(), + EnteringContext); if (SD) { if (NamespaceDecl *Namespace = dyn_cast(SD)) @@ -303,13 +304,16 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, // Fall through to produce an error: we found something that isn't // a class or a namespace. - } + } else if (SS.isSet() && isDependentScopeSpecifier(SS)) + return NestedNameSpecifier::Create(Context, Prefix, &II); // If we didn't find anything during our lookup, try again with // ordinary name lookup, which can help us produce better error // messages. if (!SD) - SD = LookupParsedName(S, &SS, &II, LookupOrdinaryName); + SD = LookupParsedName(S, &SS, &II, LookupOrdinaryName, + false, false, SourceLocation(), + EnteringContext); unsigned DiagID; if (SD) DiagID = diag::err_expected_class_or_namespace; -- cgit v1.2.3