]> granicus.if.org Git - clang/commitdiff
Provide a naming class for UnresolvedLookupExprs, even when occuring on
authorChandler Carruth <chandlerc@gmail.com>
Wed, 19 May 2010 09:39:06 +0000 (09:39 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Wed, 19 May 2010 09:39:06 +0000 (09:39 +0000)
template names. We were completely missing naming classes for many unqualified
lookups, but this didn't trigger code paths that need it. This removes part of
an optimization that re-uses the template name lookup done by the parser to
determine if explicit template arguments actually form a template-id.
Unfortunately the technique for avoiding the duplicate lookup lost needed data
such as the class context in which the lookup succeeded.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104117 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
lib/Sema/SemaLookup.cpp
test/CXX/temp/temp.names/p2.cpp [new file with mode: 0644]

index 5e1f21b4c3b67d51778f3c1bb49931e100c64cab..94aa6b09fe6231b62a2589861839801150f518af 100644 (file)
@@ -1077,17 +1077,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<NestedNameSpecifier *>(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);
index 774a82b7c74188631316921b6909023be0153187..b25ecb1e06ef07343cd68429d0b88509c4dab647 100644 (file)
@@ -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<DeclContext*>(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,11 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
     }
     if (Found) {
       R.resolveKind();
+      if (S->isClassScope())
+        R.setNamingClass(dyn_cast<CXXRecordDecl>(Ctx));
       return true;
     }
 
-    DeclContext *Ctx = static_cast<DeclContext*>(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 (file)
index 0000000..8666b61
--- /dev/null
@@ -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 loose the context of the name lookup
+// because of the required early lookup to determine if it names a template.
+namespace PR7163 {
+  template <typename R, typename P> void h(R (*func)(P)) {}
+  class C {
+    template <typename T> static void g(T*) {};
+   public:
+    void f() { h(g<int>); }
+  };
+}