From: Douglas Gregor Date: Thu, 20 May 2010 20:58:56 +0000 (+0000) Subject: Reinstate r104117, Chandler Carruth's change that "[provides] a naming X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d2235f60e7bbd9e690c05fced371df9da76adc2b;p=clang Reinstate r104117, Chandler Carruth's change that "[provides] a naming class for UnresolvedLookupExprs, even when occuring on template names" along with a fix for an Objective-C++ crasher it introduced. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104277 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 320b24227a..9d8fe9c85f 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1079,17 +1079,12 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, // Perform the required lookup. LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); if (TemplateArgs) { - // Just re-use the lookup done by isTemplateName. - DecomposeTemplateName(R, Id); - - // Re-derive the naming class. - if (SS.isSet()) { - NestedNameSpecifier *Qualifier - = static_cast(SS.getScopeRep()); - if (const Type *Ty = Qualifier->getAsType()) - if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl()) - R.setNamingClass(NamingClass); - } + // Lookup the template name again to correctly establish the context in + // which it was found. This is really unfortunate as we already did the + // lookup to determine that it was a template name in the first place. If + // this becomes a performance hit, we can work harder to preserve those + // results until we get here but it's likely not worth it. + LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false); } else { bool IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl()); LookupParsedName(R, S, &SS, !IvarLookupFollowUp); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 774a82b7c7..4555a86e01 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -665,6 +665,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // DeclContext *OutsideOfTemplateParamDC = 0; for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { + DeclContext *Ctx = static_cast(S->getEntity()); + // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { @@ -675,10 +677,12 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { } if (Found) { R.resolveKind(); + if (S->isClassScope()) + if (CXXRecordDecl *Record = dyn_cast_or_null(Ctx)) + R.setNamingClass(Record); return true; } - DeclContext *Ctx = static_cast(S->getEntity()); if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && S->getParent() && !S->getParent()->isTemplateParamScope()) { // We've just searched the last template parameter scope and diff --git a/test/CXX/temp/temp.names/p2.cpp b/test/CXX/temp/temp.names/p2.cpp new file mode 100644 index 0000000000..93e45dd7e3 --- /dev/null +++ b/test/CXX/temp/temp.names/p2.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Ensure that when enforcing access control an unqualified template name with +// explicit template arguments, we don't lose the context of the name lookup +// because of the required early lookup to determine if it names a template. +namespace PR7163 { + template void h(R (*func)(P)) {} + class C { + template static void g(T*) {}; + public: + void f() { h(g); } + }; +} diff --git a/test/SemaObjCXX/ivar-struct.mm b/test/SemaObjCXX/ivar-struct.mm new file mode 100644 index 0000000000..3f9c7eb1a5 --- /dev/null +++ b/test/SemaObjCXX/ivar-struct.mm @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +@interface A { + struct X { + int x, y; + } X; +} +@end