[PATCH] ms-compat: Fix taking the address of a member of a dependent base

Reid Kleckner rnk at google.com
Mon Oct 14 14:41:43 PDT 2013


    - Explicitly assume that unresolved unqualified id exprs are members of dependent bases.

Hi rsmith,

http://llvm-reviews.chandlerc.com/D1892

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1892?vs=4823&id=4901#toc

Files:
  lib/AST/ExprCXX.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/TreeTransform.h
  test/SemaTemplate/ms-lookup-template-base-classes.cpp

Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp
+++ lib/AST/ExprCXX.cpp
@@ -456,6 +456,7 @@
                                   SourceLocation TemplateKWLoc,
                                   const DeclarationNameInfo &NameInfo,
                                   const TemplateArgumentListInfo *Args) {
+  assert(QualifierLoc && "should be created for dependent qualifiers");
   std::size_t size = sizeof(DependentScopeDeclRefExpr);
   if (Args)
     size += ASTTemplateKWAndArgsInfo::sizeFor(Args->size());
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -2020,14 +2020,26 @@
     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 type dependent.  The
-      // goal is to postpone name lookup to instantiation time to be able to
-      // search into the type dependent base classes.
+      // 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.
+      // 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().MicrosoftMode) {
         CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
-        if (MD && MD->getParent()->hasAnyDependentBases())
-          return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
-                                            IsAddressOfOperand, TemplateArgs);
+        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.
+          NamedDecl *FirstQualifierInScope = 0;
+          return Owned(CXXDependentScopeMemberExpr::Create(
+              Context, /*This=*/0, ThisType, /*IsArrow=*/true,
+              /*Op=*/SourceLocation(), SS.getWithLocInContext(Context),
+              TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs));
+        }
       }
 
       // Don't diagnose an empty lookup for inline assmebly.
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -8127,6 +8127,7 @@
 TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
                                                DependentScopeDeclRefExpr *E,
                                                bool IsAddressOfOperand) {
+  assert(E->getQualifierLoc());
   NestedNameSpecifierLoc QualifierLoc
   = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc());
   if (!QualifierLoc)
Index: test/SemaTemplate/ms-lookup-template-base-classes.cpp
===================================================================
--- test/SemaTemplate/ms-lookup-template-base-classes.cpp
+++ test/SemaTemplate/ms-lookup-template-base-classes.cpp
@@ -196,3 +196,43 @@
 }
 
 }  // namespace PR12701
+
+namespace PR16014 {
+
+struct A {
+  int a;
+  static int sa;
+};
+template <typename T> struct B : T {
+  int     foo() { return a; }
+  int    *bar() { return &a; }
+  int     baz() { return T::a; }
+  int T::*qux() { return &T::a; }
+  static int T::*stuff() { return &T::a; }
+  static int stuff1() { return T::sa; }
+  static int *stuff2() { return &T::sa; }
+};
+
+template <typename T> struct C : T {
+  int     foo() { return b; }      // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}}
+  int    *bar() { return &b; }     // expected-error {{no member named 'b' in 'PR16014::C<PR16014::A>'}}
+  int     baz() { return T::b; }   // expected-error {{no member named 'b' in 'PR16014::A'}}
+  int T::*qux() { return &T::b; }  // expected-error {{no member named 'b' in 'PR16014::A'}}
+  int T::*fuz() { return &U::a; }  // expected-error {{use of undeclared identifier 'U'}}
+};
+
+template struct B<A>;
+template struct C<A>;  // expected-note-re 1+ {{in instantiation of member function 'PR16014::C<PR16014::A>::.*' requested here}}
+
+template <typename T> struct D : T {
+  struct Inner {
+    int foo() {
+      // FIXME: MSVC can find this in D's base T!  Even worse, if ::sa exists,
+      // clang will use it instead.
+      return sa; // expected-error {{use of undeclared identifier 'sa'}}
+    }
+  };
+};
+template struct D<A>;
+
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1892.2.patch
Type: text/x-patch
Size: 4976 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131014/e88e3699/attachment.bin>


More information about the cfe-commits mailing list