]> granicus.if.org Git - clang/commitdiff
Improve our handling of the current instantiation for qualified
authorDouglas Gregor <dgregor@apple.com>
Fri, 4 Feb 2011 13:35:07 +0000 (13:35 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 4 Feb 2011 13:35:07 +0000 (13:35 +0000)
id-expression, e.g.,

  CurrentClass<T>::member

Previously, if CurrentClass<T> was dependent and not complete, we
would treat it as a dependent-scoped declaration reference expression,
even if CurrentClass<T> referred to the current instantiation.

Fixes PR8966 and improves type checking of templates.

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

lib/Sema/SemaExpr.cpp
test/SemaTemplate/dependent-names.cpp

index 0d4950fd16caa0cb0054326d0b25fa90560a0c45..a4649777792e00f5b766312be79337a74d9577f4 100644 (file)
@@ -1035,28 +1035,6 @@ static void DecomposeUnqualifiedId(Sema &SemaRef,
   }
 }
 
-/// Determines whether the given record is "fully-formed" at the given
-/// location, i.e. whether a qualified lookup into it is assured of
-/// getting consistent results already.
-static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
-  if (!Record->hasDefinition())
-    return false;
-
-  for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(),
-         E = Record->bases_end(); I != E; ++I) {
-    CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType());
-    CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>();
-    if (!BaseRT) return false;
-
-    CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl());
-    if (!BaseRecord->hasDefinition() ||
-        !IsFullyFormedScope(SemaRef, BaseRecord))
-      return false;
-  }
-
-  return true;
-}
-
 /// Determines if the given class is provably not derived from all of
 /// the prospective base classes.
 static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
@@ -1489,9 +1467,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
     if (DC) {
       if (RequireCompleteDeclContext(SS, DC))
         return ExprError();
-      // FIXME: We should be checking whether DC is the current instantiation.
-      if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
-        DependentID = !IsFullyFormedScope(*this, RD);
     } else {
       DependentID = true;
     }
@@ -1513,10 +1488,21 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
     bool MemberOfUnknownSpecialization;
     LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
                        MemberOfUnknownSpecialization);
+    
+    if (MemberOfUnknownSpecialization ||
+        (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
+      return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand,
+                                        TemplateArgs);
   } else {
     IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl());
     LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
 
+    // If the result might be in a dependent base class, this is a dependent 
+    // id-expression.
+    if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
+      return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand,
+                                        TemplateArgs);
+      
     // If this reference is in an Objective-C method, then we need to do
     // some special Objective-C lookup, too.
     if (IvarLookupFollowUp) {
index 77961069c5a22fad4b72c6a848bd5d8f92f45072..5776ddca2c49dd236f07a63c1b900065d9fd7908 100644 (file)
@@ -102,3 +102,30 @@ namespace test1 {
 
   template struct Derived<int>; // expected-note {{requested here}}
 }
+
+namespace PR8966 {
+  template <class T>
+  class MyClassCore
+  {
+  };
+
+  template <class T>
+  class MyClass : public MyClassCore<T>
+  {
+  public:
+    enum  {
+      N
+    };
+
+    // static member declaration
+    static const char* array [N];
+
+    void f() {
+      MyClass<T>::InBase = 17;
+    }
+  };
+
+  // static member definition
+  template <class T>
+  const char* MyClass<T>::array [MyClass<T>::N] = { "A", "B", "C" };
+}