[cfe-commits] r101065 - in /cfe/trunk: lib/Sema/Lookup.h lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.res/temp.local/p3.cpp

Douglas Gregor dgregor at apple.com
Mon Apr 12 13:54:26 PDT 2010


Author: dgregor
Date: Mon Apr 12 15:54:26 2010
New Revision: 101065

URL: http://llvm.org/viewvc/llvm-project?rev=101065&view=rev
Log:
Implement C++ [temp.local]p4, which specifies how we eliminate
name-lookup ambiguities when there are multiple base classes that are
all specializations of the same class template. This is part of a
general cleanup for ambiguities in template-name lookup. Fixes
PR6717.


Added:
    cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp
Modified:
    cfe/trunk/lib/Sema/Lookup.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/lib/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Lookup.h?rev=101065&r1=101064&r2=101065&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Lookup.h (original)
+++ cfe/trunk/lib/Sema/Lookup.h Mon Apr 12 15:54:26 2010
@@ -343,6 +343,11 @@
     } else {
       ResultKind = Found;
       resolveKind();
+      
+      if (Paths && (ResultKind != Ambiguous)) {
+        deletePaths(Paths);
+        Paths = 0;
+      }
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=101065&r1=101064&r2=101065&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Apr 12 15:54:26 2010
@@ -2454,7 +2454,8 @@
     }
   }
 
-  assert(BaseType->isDependentType() || Name.isDependentName());
+  assert(BaseType->isDependentType() || Name.isDependentName() || 
+         isDependentScopeSpecifier(SS));
 
   // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr
   // must have pointer type, and the accessed type is the pointee.
@@ -3200,7 +3201,8 @@
 
   Expr *Base = BaseArg.takeAs<Expr>();
   OwningExprResult Result(*this);
-  if (Base->getType()->isDependentType() || Name.isDependentName()) {
+  if (Base->getType()->isDependentType() || Name.isDependentName() ||
+      isDependentScopeSpecifier(SS)) {
     Result = ActOnDependentMemberExpr(ExprArg(*this, Base), Base->getType(),
                                       IsArrow, OpLoc,
                                       SS, FirstQualifierInScope,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=101065&r1=101064&r2=101065&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Apr 12 15:54:26 2010
@@ -63,14 +63,34 @@
 }
 
 static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
+  // The set of class templates we've already seen.
+  llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
   LookupResult::Filter filter = R.makeFilter();
   while (filter.hasNext()) {
     NamedDecl *Orig = filter.next();
     NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl());
     if (!Repl)
       filter.erase();
-    else if (Repl != Orig)
+    else if (Repl != Orig) {
+
+      // C++ [temp.local]p3:
+      //   A lookup that finds an injected-class-name (10.2) can result in an 
+      //   ambiguity in certain cases (for example, if it is found in more than
+      //   one base class). If all of the injected-class-names that are found 
+      //   refer to specializations of the same class template, and if the name 
+      //   is followed by a template-argument-list, the reference refers to the 
+      //   class template itself and not a specialization thereof, and is not 
+      //   ambiguous.
+      //
+      // FIXME: Will we eventually have to do the same for alias templates?
+      if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl))
+        if (!ClassTemplates.insert(ClassTmpl)) {
+          filter.erase();
+          continue;
+        }
+          
       filter.replace(Repl);
+    }
   }
   filter.done();
 }
@@ -109,7 +129,7 @@
                  LookupOrdinaryName);
   R.suppressDiagnostics();
   LookupTemplateName(R, S, SS, ObjectType, EnteringContext);
-  if (R.empty())
+  if (R.empty() || R.isAmbiguous())
     return TNK_Non_template;
 
   TemplateName Template;
@@ -227,10 +247,6 @@
     LookupName(Found, S);
   }
 
-  // FIXME: Cope with ambiguous name-lookup results.
-  assert(!Found.isAmbiguous() &&
-         "Cannot handle template name-lookup ambiguities");
-
   if (Found.empty() && !isDependent) {
     // If we did not find any names, attempt to correct any typos.
     DeclarationName Name = Found.getLookupName();
@@ -271,8 +287,7 @@
                             LookupOrdinaryName);
     LookupName(FoundOuter, S);
     FilterAcceptableTemplateNames(Context, FoundOuter);
-    // FIXME: Handle ambiguities in this lookup better
-
+    
     if (FoundOuter.empty()) {
       //   - if the name is not found, the name found in the class of the
       //     object expression is used, otherwise

Added: cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp?rev=101065&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.res/temp.local/p3.cpp Mon Apr 12 15:54:26 2010
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -verify %s
+
+template <class T> struct Base { // expected-note 4 {{member found by ambiguous name lookup}}
+  static void f();
+}; 
+
+struct X0 { };
+
+template <class T> struct Derived: Base<int>, Base<char> {
+  typename Derived::Base b;	// expected-error{{member 'Base' found in multiple base classes of different types}}
+  typename Derived::Base<double> d;	// OK
+
+  void g(X0 *t) {
+    t->Derived::Base<T>::f();
+    t->Base<T>::f();
+    t->Base::f(); // expected-error{{member 'Base' found in multiple base classes of different types}} \
+    // expected-error{{no member named 'f' in 'X0'}} \
+    // expected-error{{expected a class or namespace}}
+  }
+};
+
+namespace PR6717 {
+  template <typename T>
+  class WebVector {
+  }
+
+    WebVector(const WebVector<T>& other) { } 
+
+  template <typename C>
+  WebVector<T>& operator=(const C& other) { } // expected-error{{unknown type name 'WebVector'}} \
+  // expected-error{{unqualified-id}}
+}





More information about the cfe-commits mailing list