[cfe-commits] r93497 - in /cfe/trunk: lib/Sema/Lookup.h lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaTemplate.cpp test/SemaTemplate/dependent-base-classes.cpp

Douglas Gregor dgregor at apple.com
Thu Jan 14 17:44:48 PST 2010


Author: dgregor
Date: Thu Jan 14 19:44:47 2010
New Revision: 93497

URL: http://llvm.org/viewvc/llvm-project?rev=93497&view=rev
Log:
When performing qualified name lookup into the current instantiation,
do not look into base classes if there are any dependent base
classes. Instead, note in the lookup result that we couldn't look into
any dependent bases. Use that new result kind to detect when this case
occurs, so that we can fall back to treating the type/value/etc. as a
member of an unknown specialization.

Fixes an issue where we were resolving lookup at template definition
time and then missing an ambiguity at template instantiation time.


Modified:
    cfe/trunk/lib/Sema/Lookup.h
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp

Modified: cfe/trunk/lib/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Lookup.h?rev=93497&r1=93496&r2=93497&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Lookup.h (original)
+++ cfe/trunk/lib/Sema/Lookup.h Thu Jan 14 19:44:47 2010
@@ -32,6 +32,11 @@
     /// @brief No entity found met the criteria.
     NotFound = 0,
 
+    /// @brief No entity found met the criteria within the current 
+    /// instantiation,, but there were dependent base classes of the 
+    /// current instantiation that could not be searched.
+    NotFoundInCurrentInstantiation,
+    
     /// @brief Name lookup found a single declaration that met the
     /// criteria.  getFoundDecl() will return this declaration.
     Found,
@@ -268,6 +273,19 @@
     Decls.set_size(N);
   }
 
+  /// \brief Determine whether no result was found because we could not
+  /// search into dependent base classes of the current instantiation.
+  bool wasNotFoundInCurrentInstantiation() const {
+    return ResultKind == NotFoundInCurrentInstantiation;
+  }
+  
+  /// \brief Note that while no result was found in the current instantiation,
+  /// there were dependent base classes that could not be searched.
+  void setNotFoundInCurrentInstantiation() {
+    assert(ResultKind == NotFound && Decls.empty());
+    ResultKind = NotFoundInCurrentInstantiation;
+  }
+  
   /// \brief Resolves the result kind of the lookup, possibly hiding
   /// decls.
   ///
@@ -278,9 +296,10 @@
   /// \brief Re-resolves the result kind of the lookup after a set of
   /// removals has been performed.
   void resolveKindAfterFilter() {
-    if (Decls.empty())
-      ResultKind = NotFound;
-    else {
+    if (Decls.empty()) {
+      if (ResultKind != NotFoundInCurrentInstantiation)
+        ResultKind = NotFound;
+    } else {
       ResultKind = Found;
       resolveKind();
     }

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=93497&r1=93496&r2=93497&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Jan 14 19:44:47 2010
@@ -1212,7 +1212,8 @@
                                 = NotForRedeclaration);
   bool LookupName(LookupResult &R, Scope *S,
                   bool AllowBuiltinCreation = false);
-  bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx);
+  bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+                           bool InUnqualifiedLookup = false);
   bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
                         bool AllowBuiltinCreation = false,
                         bool EnteringContext = false);

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=93497&r1=93496&r2=93497&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jan 14 19:44:47 2010
@@ -138,6 +138,7 @@
   NamedDecl *IIDecl = 0;
   switch (Result.getResultKind()) {
   case LookupResult::NotFound:
+  case LookupResult::NotFoundInCurrentInstantiation:
   case LookupResult::FoundOverloaded:
   case LookupResult::FoundUnresolvedValue:
     return 0;
@@ -4791,7 +4792,7 @@
       // and that current instantiation has any dependent base
       // classes, we might find something at instantiation time: treat
       // this as a dependent elaborated-type-specifier.
-      if (isCurrentInstantiationWithDependentBases(SS)) {
+      if (Previous.wasNotFoundInCurrentInstantiation()) {
         IsDependent = true;
         return DeclPtrTy();
       }

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=93497&r1=93496&r2=93497&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Jan 14 19:44:47 2010
@@ -623,7 +623,7 @@
         // example, inside a class without any base classes, we never need to
         // perform qualified lookup because all of the members are on top of the
         // identifier chain.
-        if (LookupQualifiedName(R, Ctx))
+        if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true))
           return true;
       }
     }
@@ -927,11 +927,11 @@
   return Found;
 }
 
-/// @brief Perform qualified name lookup into a given context.
+/// \brief Perform qualified name lookup into a given context.
 ///
 /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find
 /// names when the context of those names is explicit specified, e.g.,
-/// "std::vector" or "x->member".
+/// "std::vector" or "x->member", or as part of unqualified name lookup.
 ///
 /// Different lookup criteria can find different names. For example, a
 /// particular scope can have both a struct and a function of the same
@@ -939,25 +939,18 @@
 /// information about lookup criteria, see the documentation for the
 /// class LookupCriteria.
 ///
-/// @param LookupCtx The context in which qualified name lookup will
+/// \param R captures both the lookup criteria and any lookup results found.
+///
+/// \param LookupCtx The context in which qualified name lookup will
 /// search. If the lookup criteria permits, name lookup may also search
 /// in the parent contexts or (for C++ classes) base classes.
 ///
-/// @param Name     The name of the entity that we are searching for.
-///
-/// @param Criteria The criteria that this routine will use to
-/// determine which names are visible and which names will be
-/// found. Note that name lookup will find a name that is visible by
-/// the given criteria, but the entity itself may not be semantically
-/// correct or even the kind of entity expected based on the
-/// lookup. For example, searching for a nested-name-specifier name
-/// might result in an EnumDecl, which is visible but is not permitted
-/// as a nested-name-specifier in C++03.
+/// \param InUnqualifiedLookup true if this is qualified name lookup that 
+/// occurs as part of unqualified name lookup.
 ///
-/// @returns The result of name lookup, which includes zero or more
-/// declarations and possibly additional information used to diagnose
-/// ambiguities.
-bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) {
+/// \returns true if lookup succeeded, false if it failed.
+bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+                               bool InUnqualifiedLookup) {
   assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
 
   if (!R.getLookupName())
@@ -995,11 +988,22 @@
 
   // If this isn't a C++ class, we aren't allowed to look into base
   // classes, we're done.
-  if (!isa<CXXRecordDecl>(LookupCtx))
+  CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
+  if (!LookupRec)
     return false;
 
+  // If we're performing qualified name lookup into a dependent class,
+  // then we are actually looking into a current instantiation. If we have any
+  // dependent base classes, then we either have to delay lookup until 
+  // template instantiation time (at which point all bases will be available)
+  // or we have to fail.
+  if (!InUnqualifiedLookup && LookupRec->isDependentContext() &&
+      LookupRec->hasAnyDependentBases()) {
+    R.setNotFoundInCurrentInstantiation();
+    return false;
+  }
+    
   // Perform lookup into our base classes.
-  CXXRecordDecl *LookupRec = cast<CXXRecordDecl>(LookupCtx);
   CXXBasePaths Paths;
   Paths.setOrigin(LookupRec);
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=93497&r1=93496&r2=93497&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jan 14 19:44:47 2010
@@ -4769,16 +4769,12 @@
   Decl *Referenced = 0;
   switch (Result.getResultKind()) {
   case LookupResult::NotFound:
-    if (CurrentInstantiation && CurrentInstantiation->hasAnyDependentBases()) {
-      // We performed a lookup in the current instantiation and didn't
-      // find anything. However, this current instantiation has
-      // dependent bases, so we might be able to find something at
-      // instantiation time: just build a TypenameType and move on.
-      return Context.getTypenameType(NNS, &II);
-    }
-
     DiagID = diag::err_typename_nested_not_found;
     break;
+      
+  case LookupResult::NotFoundInCurrentInstantiation:
+    // Okay, it's a member of an unknown instantiation.
+    return Context.getTypenameType(NNS, &II);
 
   case LookupResult::Found:
     if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {

Modified: cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp?rev=93497&r1=93496&r2=93497&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp (original)
+++ cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp Thu Jan 14 19:44:47 2010
@@ -63,3 +63,22 @@
     }
   };
 }
+
+namespace Ambig {
+  template<typename T>
+  struct Base1 {
+    typedef int type; // expected-note{{member found by ambiguous name lookup}}
+  };
+
+  struct Base2 {
+    typedef float type; // expected-note{{member found by ambiguous name lookup}}
+  };
+
+  template<typename T>
+  struct Derived : Base1<T>, Base2 {
+    typedef typename Derived::type type; // expected-error{{member 'type' found in multiple base classes of different types}}
+    type *foo(float *fp) { return fp; }
+  };
+
+  Derived<int> di; // expected-note{{instantiation of}}
+}





More information about the cfe-commits mailing list