mgehre updated this revision to Diff 90592.
mgehre added a comment.
Updated fix for the crash in SemaChecking::RefersToMemberWithReducedAlignment,
so it also works for C code.
https://reviews.llvm.org/D22476
Files:
lib/AST/Expr.cpp
lib/Sema/SemaChecking.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/instantiate-self.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/instantiate-self.cpp
===================================================================
--- test/SemaTemplate/instantiate-self.cpp
+++ test/SemaTemplate/instantiate-self.cpp
@@ -99,7 +99,7 @@
namespace test10 {
template<typename T> 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<int>().f()); // expected-note {{instantiation of}}
}
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,39 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+namespace CWG224 {
+template <class T, int I>
+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<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}}
+ }
+ 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
+ }
+};
+} // namespace CWG224
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,7 +84,7 @@
struct TS {
int *get();
int *m() {
- int *&x = get();
+ int *const &x = get();
return x;
}
};
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: 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<RecordType>()->getDecl();
+ RecordDecl *RD = dyn_cast<RecordDecl>(BaseType->getAsTagDecl());
ValueDecl *MD = ME->getMemberDecl();
auto *FD = dyn_cast<FieldDecl>(MD);
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<CXXMethodDecl>(MemberDecl)) {
+ for (auto *EnableIf : Method->specific_attrs<EnableIfAttr>()) {
+ 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<CXXMethodDecl>(MemberDecl)) {
+ Parent = Method->getParent();
+ } else if (auto *Field = dyn_cast<FieldDecl>(MemberDecl)) {
+ Parent = dyn_cast<CXXRecordDecl>(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 =
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits