r212566 - MS compat: Allow lookup of types from dependent bases in functions

Reid Kleckner reid at kleckner.net
Tue Jul 8 14:35:04 PDT 2014


Author: rnk
Date: Tue Jul  8 16:35:03 2014
New Revision: 212566

URL: http://llvm.org/viewvc/llvm-project?rev=212566&view=rev
Log:
MS compat: Allow lookup of types from dependent bases in functions

If we want to resolve the remaining FIXMEs here, we probably want to
extend the main lookup mechanism to perform lookup into dependent bases,
but we would have to tread lightly.  Adding more name lookup has major
impact on compile time.

If we did extend the main mechanism, we would add a flag to LookupResult
that allows us to find names from dependent base classes where the base
is a specialization of a known template.  The final LookupResult would
still return LookupResult::NotFoundInCurrentInstantiation, but it would
have a collection of Decls.  If we find a real lookup result, we would
clear the flag and the existing lookup results and begin accumulating
only real lookup results.

We would structure the lookup as a secondary lookup between normal
lookup and typo correction for normal compilation, but for MSVC
compatibility mode, we would always enable this extra lookup into
dependent bases.

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=212566&r1=212565&r2=212566&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jul  8 16:35:03 2014
@@ -131,8 +131,15 @@ bool Sema::isSimpleTypeSpecifier(tok::To
 static ParsedType recoverFromTypeInKnownDependentBase(Sema &S,
                                                       const IdentifierInfo &II,
                                                       SourceLocation NameLoc) {
-  auto *RD = dyn_cast<CXXRecordDecl>(S.CurContext);
-  if (!RD || !RD->getDescribedClassTemplate())
+  // Find the first parent class template context, if any.
+  // FIXME: Perform the lookup in all enclosing class templates.
+  const CXXRecordDecl *RD = nullptr;
+  for (DeclContext *DC = S.CurContext; DC; DC = DC->getParent()) {
+    RD = dyn_cast<CXXRecordDecl>(DC);
+    if (RD && RD->getDescribedClassTemplate())
+      break;
+  }
+  if (!RD)
     return ParsedType();
 
   // Look for type decls in dependent base classes that have known primary
@@ -146,6 +153,8 @@ static ParsedType recoverFromTypeInKnown
     if (!TD)
       continue;
     auto *BasePrimaryTemplate = cast<CXXRecordDecl>(TD->getTemplatedDecl());
+    // FIXME: Allow lookup into non-dependent bases of dependent bases, possibly
+    // by calling or integrating with the main LookupQualifiedName mechanism.
     for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) {
       if (FoundTypeDecl)
         return ParsedType();

Modified: cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp?rev=212566&r1=212565&r2=212566&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp (original)
+++ cfe/trunk/test/SemaTemplate/ms-lookup-template-base-classes.cpp Tue Jul  8 16:35:03 2014
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++1y -fms-compatibility -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
 
 
 template <class T>
@@ -380,6 +380,15 @@ struct B : A<T> { NameFromBase m; }; //
 struct C : A<int> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
 }
 
+namespace type_in_base_of_dependent_base {
+struct A { typedef int NameFromBase; };
+template <typename T>
+struct B : A {};
+// FIXME: MSVC accepts this.
+template <typename T>
+struct C : B<T> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
+}
+
 namespace lookup_in_function_contexts {
 template <typename T> struct A { typedef T NameFromBase; };
 template <typename T>
@@ -389,23 +398,20 @@ struct B : A<T> {
     return {};
   }
 
-  // FIXME: MSVC accepts all of the code below that isn't C++14 only.  Downgrade
-  // these errors to warnings.
-
   static void memberFunc() {
-    NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+    NameFromBase x; // expected-warning {{lookup into dependent bases}}
   }
 
   static void funcLocalClass() {
     struct X {
-      NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+      NameFromBase x; // expected-warning {{lookup into dependent bases}}
     } y;
   }
 
   void localClassMethod() {
     struct X {
       void bar() {
-        NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
+        NameFromBase m; // expected-warning {{lookup into dependent bases}}
       }
     } x;
     x.bar();
@@ -413,20 +419,18 @@ struct B : A<T> {
 
   static void funcLambda() {
     auto l = []() {
-      NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+      NameFromBase x; // expected-warning {{lookup into dependent bases}}
     };
     l();
   }
 
   static constexpr int constexprFunc() {
-    NameFromBase x = {}; // expected-error {{unknown type name 'NameFromBase'}}
-    // FIXME: Suppress this diagnostic, we have an initializer.
-    // expected-error at -2 {{variables defined in a constexpr function must be initialized}}
+    NameFromBase x = {}; // expected-warning {{lookup into dependent bases}}
     return sizeof(x);
   }
 
   static auto autoFunc() {
-    NameFromBase x; // expected-error {{unknown type name 'NameFromBase'}}
+    NameFromBase x; // expected-warning {{lookup into dependent bases}}
     return x;
   }
 };





More information about the cfe-commits mailing list