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}}
+
+}
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}}
+
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to