From d27e50cd839760880a73cfaaa93f912c01cb2171 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 16 Jun 2010 16:54:04 +0000 Subject: [PATCH] Don't poke at an undefined class type of a field. Fixes PR7355. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106111 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 69 +++++++++++++------------ test/SemaTemplate/instantiate-field.cpp | 9 ++++ 2 files changed, 44 insertions(+), 34 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index f10927d18e..fbd4ff446a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5803,41 +5803,42 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (const RecordType *RT = EltTy->getAs()) { CXXRecordDecl* RDecl = cast(RT->getDecl()); - - if (!RDecl->hasTrivialConstructor()) - CXXRecord->setHasTrivialConstructor(false); - if (!RDecl->hasTrivialCopyConstructor()) - CXXRecord->setHasTrivialCopyConstructor(false); - if (!RDecl->hasTrivialCopyAssignment()) - CXXRecord->setHasTrivialCopyAssignment(false); - if (!RDecl->hasTrivialDestructor()) - CXXRecord->setHasTrivialDestructor(false); - - // C++ 9.5p1: An object of a class with a non-trivial - // constructor, a non-trivial copy constructor, a non-trivial - // destructor, or a non-trivial copy assignment operator - // cannot be a member of a union, nor can an array of such - // objects. - // TODO: C++0x alters this restriction significantly. - if (Record->isUnion()) { - // We check for copy constructors before constructors - // because otherwise we'll never get complaints about - // copy constructors. - - CXXSpecialMember member = CXXInvalid; + if (RDecl->getDefinition()) { + if (!RDecl->hasTrivialConstructor()) + CXXRecord->setHasTrivialConstructor(false); if (!RDecl->hasTrivialCopyConstructor()) - member = CXXCopyConstructor; - else if (!RDecl->hasTrivialConstructor()) - member = CXXConstructor; - else if (!RDecl->hasTrivialCopyAssignment()) - member = CXXCopyAssignment; - else if (!RDecl->hasTrivialDestructor()) - member = CXXDestructor; - - if (member != CXXInvalid) { - Diag(Loc, diag::err_illegal_union_member) << Name << member; - DiagnoseNontrivial(RT, member); - NewFD->setInvalidDecl(); + CXXRecord->setHasTrivialCopyConstructor(false); + if (!RDecl->hasTrivialCopyAssignment()) + CXXRecord->setHasTrivialCopyAssignment(false); + if (!RDecl->hasTrivialDestructor()) + CXXRecord->setHasTrivialDestructor(false); + + // C++ 9.5p1: An object of a class with a non-trivial + // constructor, a non-trivial copy constructor, a non-trivial + // destructor, or a non-trivial copy assignment operator + // cannot be a member of a union, nor can an array of such + // objects. + // TODO: C++0x alters this restriction significantly. + if (Record->isUnion()) { + // We check for copy constructors before constructors + // because otherwise we'll never get complaints about + // copy constructors. + + CXXSpecialMember member = CXXInvalid; + if (!RDecl->hasTrivialCopyConstructor()) + member = CXXCopyConstructor; + else if (!RDecl->hasTrivialConstructor()) + member = CXXConstructor; + else if (!RDecl->hasTrivialCopyAssignment()) + member = CXXCopyAssignment; + else if (!RDecl->hasTrivialDestructor()) + member = CXXDestructor; + + if (member != CXXInvalid) { + Diag(Loc, diag::err_illegal_union_member) << Name << member; + DiagnoseNontrivial(RT, member); + NewFD->setInvalidDecl(); + } } } } diff --git a/test/SemaTemplate/instantiate-field.cpp b/test/SemaTemplate/instantiate-field.cpp index a260635778..d825cd7cc6 100644 --- a/test/SemaTemplate/instantiate-field.cpp +++ b/test/SemaTemplate/instantiate-field.cpp @@ -81,3 +81,12 @@ namespace PR7123 { sort(x,x); } } + +namespace PR7355 { + template class A { + class D; // expected-note{{declared here}} + D d; //expected-error{{implicit instantiation of undefined member 'PR7355::A::D'}} + }; + + A ai; // expected-note{{in instantiation of}} +} -- 2.40.0