]> granicus.if.org Git - clang/commitdiff
-fms-compatibility: Only form implicit member exprs for unqualified ids
authorReid Kleckner <reid@kleckner.net>
Tue, 25 Mar 2014 20:31:28 +0000 (20:31 +0000)
committerReid Kleckner <reid@kleckner.net>
Tue, 25 Mar 2014 20:31:28 +0000 (20:31 +0000)
If there are any scope specifiers, then a base class must be named or
the symbol isn't from a base class.

Fixes PR19233.

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

lib/Sema/SemaExpr.cpp
test/SemaTemplate/ms-lookup-template-base-classes.cpp

index 80220c0d14bf0ef022792f19e0c1db2591beecdb..f0e0485e2317a80d07acd892c35e5d8ce86d1f2b 100644 (file)
@@ -2044,17 +2044,17 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
     if (R.empty()) {
       // In Microsoft mode, if we are inside a template class member function
       // whose parent class has dependent base classes, and we can't resolve
-      // an identifier, then assume the identifier is a member of a dependent
-      // base class.  The goal is to postpone name lookup to instantiation time
-      // to be able to search into the type dependent base classes.
+      // an unqualified identifier, then assume the identifier is a member of a
+      // dependent base class.  The goal is to postpone name lookup to
+      // instantiation time to be able to search into the type dependent base
+      // classes.
       // FIXME: If we want 100% compatibility with MSVC, we will have delay all
       // unqualified name lookup.  Any name lookup during template parsing means
       // clang might find something that MSVC doesn't.  For now, we only handle
       // the common case of members of a dependent base class.
-      if (getLangOpts().MSVCCompat) {
+      if (SS.isEmpty() && getLangOpts().MSVCCompat) {
         CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
         if (MD && MD->isInstance() && MD->getParent()->hasAnyDependentBases()) {
-          assert(SS.isEmpty() && "qualifiers should be already handled");
           QualType ThisType = MD->getThisType(Context);
           // Since the 'this' expression is synthesized, we don't need to
           // perform the double-lookup check.
index e956cd11c54947287467c5f4b9a50dfcfb854020..8f9653da05e6cd7c7639ba2998086e38421d8f9b 100644 (file)
@@ -236,3 +236,26 @@ template <typename T> struct D : T {
 template struct D<A>;
 
 }
+
+namespace PR19233 {
+template <class T>
+struct A : T {
+  void foo() {
+    ::undef(); // expected-error {{no member named 'undef' in the global namespace}}
+  }
+  void bar() {
+    ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}}
+  }
+  void baz() {
+    B::qux(); // expected-error {{use of undeclared identifier 'B'}}
+  }
+};
+
+struct B { void qux(); };
+struct C : B { };
+template struct A<C>; // No error!  B is a base of A<C>, and qux is available.
+
+struct D { };
+template struct A<D>; // expected-note {{in instantiation of member function 'PR19233::A<PR19233::D>::baz' requested here}}
+
+}