mgehre updated this revision to Diff 64777.
mgehre added a comment.

- Properly check for being member of current instantiation.
- Add new testcase test/CXX/temp/temp.res/temp.dep/temp.dep.expr/p5.cpp
- Added assert() according to review comment


https://reviews.llvm.org/D22476

Files:
  lib/AST/Expr.cpp
  lib/Sema/SemaOverload.cpp
  test/Analysis/stack-addr-ps.cpp
  test/CXX/class.access/class.access.dcl/p1.cpp
  test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
  test/CXX/drs/dr3xx.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.expr/p5.cpp
  test/SemaTemplate/dependent-names.cpp
  test/SemaTemplate/enum-argument.cpp
  test/SemaTemplate/member-access-expr.cpp

Index: test/SemaTemplate/member-access-expr.cpp
===================================================================
--- test/SemaTemplate/member-access-expr.cpp
+++ test/SemaTemplate/member-access-expr.cpp
@@ -154,9 +154,7 @@
   template <class T> class Derived : public Base<T> {
     A *field;
     void get(B **ptr) {
-      // It's okay if at some point we figure out how to diagnose this
-      // at instantiation time.
-      *ptr = field;
+      *ptr = field; // expected-error{{assigning to 'test6::B *' from incompatible type 'test6::A *'}}
     }
   };
 }
Index: test/SemaTemplate/enum-argument.cpp
===================================================================
--- test/SemaTemplate/enum-argument.cpp
+++ test/SemaTemplate/enum-argument.cpp
@@ -31,7 +31,7 @@
     unsigned long long bitfield : e0;
 
     void f(int j) {
-      bitfield + j;
+      (void)(bitfield + j);
     }
   };
 }
Index: test/SemaTemplate/dependent-names.cpp
===================================================================
--- test/SemaTemplate/dependent-names.cpp
+++ test/SemaTemplate/dependent-names.cpp
@@ -274,7 +274,7 @@
       int e[10];
     };
     void g() {
-      S<int>().f(); // expected-note {{here}}
+      S<int>().f();
     }
   }
 
Index: test/CXX/temp/temp.res/temp.dep/temp.dep.expr/p5.cpp
===================================================================
--- /dev/null
+++ test/CXX/temp/temp.res/temp.dep/temp.dep.expr/p5.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+namespace CWG224 {
+  template <class T, int I> struct A {
+    int* i;
+    typedef T newT;
+    static const int my_I = I;
+    static const int my_I2 = I+0;
+    static const int my_I3 = my_I;
+    void f() {
+      char* j = nullptr;
+      i = j; // expected-error {{incompatible type}}
+      i = nullptr;
+      (*this).i = j; // FIXME {{incompatible type}}
+      this->i = j; // FIXME {{incompatible type}}
+      A::i = j; // expected-error {{incompatible type}}
+      A<T,I>::i = j; // expected-error {{incompatible type}}
+      A<T*,I>::i = j; // not current instantiation
+      A<newT,I>::i = j; // expected-error {{incompatible type}}
+      ::CWG224::A<newT,I>::i = j; // expected-error {{incompatible type}}
+      A<T,my_I>::i = j; // FIXME (https://reviews.llvm.org/D22587)
+      A<T,my_I2>::i = j; // not current instantiation
+      A<T,my_I3>::i = j; // FIXME (https://reviews.llvm.org/D22587)
+    }
+    struct B {
+      int* b;
+      void f() {
+        char* c = nullptr;
+        b = c; // expected-error {{incompatible type}}
+        B::b = c; // expected-error {{incompatible type}}
+        A<T,I>::B::b = c; // expected-error {{incompatible type}}
+        A<T*,I>::B::b = c; // not current instantiation
+      }
+    };
+  };
+
+  template <class T> class A<T*,0> {
+    void f(A<T*,0>* a1, A<T,0>* a2) {
+      a1->i = 1; // FIXME {{incompatible type}}
+      a2->i = 1; // not current instantiation
+    }
+  };
+}
Index: test/CXX/drs/dr3xx.cpp
===================================================================
--- test/CXX/drs/dr3xx.cpp
+++ test/CXX/drs/dr3xx.cpp
@@ -1167,8 +1167,8 @@
 namespace dr390 { // dr390: yes
   template<typename T>
   struct A {
-    A() { f(); } // expected-warning {{call to pure virt}}
-    virtual void f() = 0; // expected-note {{here}}
+    A() { f(); } // expected-warning {{call to pure virt}} expected-warning {{call to pure virt}}
+    virtual void f() = 0; // expected-note {{here}} expected-note {{here}}
     virtual ~A() = 0;
   };
   template<typename T> A<T>::~A() { T::error; } // expected-error {{cannot be used prior to}}
Index: test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
===================================================================
--- test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
+++ test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
@@ -29,7 +29,10 @@
   };
 }
 
-struct Opaque0 {};
+struct Opaque0 {}; // expected-note {{no known conversion}}
+#if __cplusplus >= 201103L
+//  expected-note@-2 {{no known conversion}}
+#endif
 
 namespace test1 {
   struct A {
@@ -112,7 +115,7 @@
     }
 
     void test5() {
-      Opaque0 _ = hiding;
+      Opaque0 _ = hiding; // expected-error {{no viable conversion from 'int' to 'Opaque0'}}
     }
   };
 }
Index: test/CXX/class.access/class.access.dcl/p1.cpp
===================================================================
--- test/CXX/class.access/class.access.dcl/p1.cpp
+++ test/CXX/class.access/class.access.dcl/p1.cpp
@@ -56,7 +56,10 @@
   };
 }
 
-struct Opaque0 {};
+struct Opaque0 {}; // expected-note {{candidate constructor}}
+#if __cplusplus >= 201103L
+// expected-note@-2 {{candidate constructor}}
+#endif
 
 namespace test1 {
   struct A {
@@ -196,7 +199,7 @@
     }
 
     void test5() {
-      Opaque0 _ = hiding;
+      Opaque0 _ = hiding; // expected-error {{no viable conversion from 'int' to 'Opaque0'}}
     }
   };
 }
Index: test/Analysis/stack-addr-ps.cpp
===================================================================
--- test/Analysis/stack-addr-ps.cpp
+++ test/Analysis/stack-addr-ps.cpp
@@ -84,8 +84,8 @@
 struct TS {
   int *get();
   int *m() {
-    int *&x = get();
-    return x;
+    int * const &x = get(); // expected-note {{binding reference variable 'x' here}}
+    return x; // expected-warning {{returning address of local temporary object}}
   }
 };
 
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -4879,7 +4879,7 @@
     assert(FromClassification.isLValue());
   }
 
-  assert(FromType->isRecordType());
+  assert(FromType->isRecordType() || FromType->getTypeClass() == Type::InjectedClassName);
 
   // C++0x [over.match.funcs]p4:
   //   For non-static member functions, the type of the implicit object
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -1398,6 +1398,37 @@
   }
 }
 
+static bool IsMemberOfCurrentInstantiation(Expr *Base, ValueDecl *MemberDecl) {
+  const auto *BaseType = Base->getType().getTypePtr();
+  if (BaseType->isPointerType())
+    BaseType = BaseType->getPointeeType().getTypePtr();
+
+  const auto *BaseClass = BaseType->getAsCXXRecordDecl();
+
+  if (!BaseClass)
+    return false;
+
+  if (auto *Method = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+    for (auto *EnableIf : Method->specific_attrs<EnableIfAttr>()) {
+      if (EnableIf->getCond()->isTypeDependent())
+        return false;
+    }
+
+    const auto *Parent = Method->getParent();
+    if (BaseClass != Parent && !BaseClass->isDerivedFrom(Parent))
+      return false;
+
+  } else if (auto *Field = dyn_cast<FieldDecl>(MemberDecl)) {
+    const auto *Parent = dyn_cast<CXXRecordDecl>(Field->getParent());
+    if (!Parent || (BaseClass != Parent && !BaseClass->isDerivedFrom(Parent)))
+      return false;
+
+  } else {
+    return false;
+  }
+  return true;
+}
+
 MemberExpr *MemberExpr::Create(
     const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc,
     NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
@@ -1420,17 +1451,16 @@
   MemberExpr *E = new (Mem)
       MemberExpr(base, isarrow, OperatorLoc, memberdecl, nameinfo, ty, vk, ok);
 
+  // A member of the current instantiation is only type dependent if
+  // the field is type dependent. (14.6.2.1 [temp.dep.type])
+  if (E->isTypeDependent()
+   && IsMemberOfCurrentInstantiation(base, memberdecl)
+   && !memberdecl->getType()->isDependentType()) {
+    assert(!ty->isDependentType());
+    E->setTypeDependent(false);
+  }
+
   if (hasQualOrFound) {
-    // FIXME: Wrong. We should be looking at the member declaration we found.
-    if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) {
-      E->setValueDependent(true);
-      E->setTypeDependent(true);
-      E->setInstantiationDependent(true);
-    } 
-    else if (QualifierLoc && 
-             QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) 
-      E->setInstantiationDependent(true);
-    
     E->HasQualifierOrFoundDecl = true;
 
     MemberExprNameQualifier *NQ =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to