Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -1434,6 +1434,49 @@ } } +static bool hasValueDependentEnableIfAttr(ValueDecl *MemberDecl) { + if (auto *Method = dyn_cast(MemberDecl)) { + for (auto *EnableIf : Method->specific_attrs()) { + if (EnableIf->getCond()->isValueDependent()) + return true; + } + } + return false; +} + +static bool IsMemberOfCurrentInstantiation(Expr *Base, ValueDecl *MemberDecl) { + + if (!Base->isTypeDependent()) + return false; + + const auto *BaseType = Base->getType().getTypePtr(); + if (BaseType->isPointerType()) + BaseType = BaseType->getPointeeType().getTypePtr(); + + const auto *BaseClass = BaseType->getAsCXXRecordDecl(); + + if (!BaseClass) + return false; // Cannot resolve base, thus it's an unknown specialization. + + const CXXRecordDecl *Parent = nullptr; + if (auto *Method = dyn_cast(MemberDecl)) { + Parent = Method->getParent(); + } else if (auto *Field = dyn_cast(MemberDecl)) { + Parent = dyn_cast(Field->getParent()); + } + + /* It can happen that the MemberDecl resolves to a member of an outer class, + * and later on Sema would print an error that it is not a member of the + * actual class. In this case, we keep it type-dependent, and the error will + * only appear if the class is specialised without inheriting from the outer + * class. + */ + if (!Parent || (BaseClass != Parent && !BaseClass->isDerivedFrom(Parent))) + return false; + + return true; +} + MemberExpr *MemberExpr::Create( const ASTContext &C, Expr *base, bool isarrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -1456,17 +1499,19 @@ 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]) + // We keep the expression type dependent if the member has an enable_if + // attribute, that is value dependent, because we cannot yet know if the + // member will be enabled. + if (IsMemberOfCurrentInstantiation(base, memberdecl) && + !memberdecl->getType()->isDependentType() && + !hasValueDependentEnableIfAttr(memberdecl)) { + 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 = Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -11854,7 +11854,7 @@ QualType BaseType = ME->getBase()->getType(); if (ME->isArrow()) BaseType = BaseType->getPointeeType(); - RecordDecl *RD = BaseType->getAs()->getDecl(); + RecordDecl *RD = dyn_cast(BaseType->getAsTagDecl()); ValueDecl *MD = ME->getMemberDecl(); auto *FD = dyn_cast(MD); Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -4992,7 +4992,8 @@ 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: test/Analysis/stack-addr-ps.cpp =================================================================== --- test/Analysis/stack-addr-ps.cpp +++ test/Analysis/stack-addr-ps.cpp @@ -84,7 +84,7 @@ struct TS { int *get(); int *m() { - int *&x = get(); + int *const &x = get(); return x; } }; 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/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/drs/dr3xx.cpp =================================================================== --- test/CXX/drs/dr3xx.cpp +++ test/CXX/drs/dr3xx.cpp @@ -1167,8 +1167,8 @@ namespace dr390 { // dr390: yes template 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 A::~A() { T::error; } // expected-error {{cannot be used prior to}} 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,39 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +namespace CWG224 { +template +struct A { + int *i; + typedef T newT; + 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::i = j; // expected-error {{incompatible type}} + A::i = j; // not current instantiation + A::i = j; // expected-error {{incompatible type}} + ::CWG224::A::i = j; // expected-error {{incompatible type}} + } + struct B { + int *b; + void f() { + char *c = nullptr; + b = c; // expected-error {{incompatible type}} + B::b = c; // expected-error {{incompatible type}} + A::B::b = c; // expected-error {{incompatible type}} + A::B::b = c; // not current instantiation + } + }; +}; + +template +class A { + void f(A *a1, A *a2) { + a1->i = 1; // FIXME {{incompatible type}} + a2->i = 1; // not current instantiation + } +}; +} // namespace CWG224 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().f(); // expected-note {{here}} + S().f(); } } 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/instantiate-self.cpp =================================================================== --- test/SemaTemplate/instantiate-self.cpp +++ test/SemaTemplate/instantiate-self.cpp @@ -99,7 +99,7 @@ namespace test10 { template struct A { - void f() noexcept(noexcept(f())); // expected-error {{exception specification of 'f' uses itself}} expected-note {{instantiation of}} + void f() noexcept(noexcept(f())); // / expected-error {{exception specification is not available until end of class definition}} expected-error {{exception specification of 'f' uses itself}} expected-note {{instantiation of}} }; bool b = noexcept(A().f()); // expected-note {{instantiation of}} } 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 Derived : public Base { 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 *'}} } }; }