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

Reid Kleckner rnk at google.com
Thu Oct 10 18:55:35 PDT 2013


Hi rsmith,

Clang currently sees the unary ampersand and builds a
DependentDeclRefExpr when taking the address of a member of a dependent
base.  The resulting expr lacks any valid name qualifier location, which
TreeTransform::TransformDependentDeclRefExpr() treats as an error,
causing it to return early without any diagnostic indicating that no
code would be generated.

Clang should be detecting the nested name specifiers earlier, so even if
there is an ampersand we should override that and consider an
unqualified id-expression to be a member of a dependent base.

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

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
@@ -2025,9 +2025,15 @@
       // search into the type dependent base classes.
       if (getLangOpts().MicrosoftMode) {
         CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
-        if (MD && MD->getParent()->hasAnyDependentBases())
+        if (MD && MD->getParent()->hasAnyDependentBases()) {
+          // At this point, we should already have handled taking the address of
+          // something with nested name specifiers, so make IsAddressOfOperand
+          // false and make any id-expression a member expression.
+          assert(SS.isEmpty() && "qualifiers should be already handled");
           return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
-                                            IsAddressOfOperand, TemplateArgs);
+                                            /*IsAddressOfOperand=*/false,
+                                            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,32 @@
 }
 
 }  // 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}}
+
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1892.1.patch
Type: text/x-patch
Size: 3639 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131010/8872e6d3/attachment.bin>


More information about the cfe-commits mailing list