diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-03-06 20:12:45 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-03-06 20:12:45 +0000 |
commit | 528ad93924b159b69b851732b6a6c2092f54e19f (patch) | |
tree | ed3b4133993eb3be811aaca78494291cf76b48c9 /clang | |
parent | d9bb15282150f6ff513e784a7512f2997523d518 (diff) | |
download | bcm5719-llvm-528ad93924b159b69b851732b6a6c2092f54e19f.tar.gz bcm5719-llvm-528ad93924b159b69b851732b6a6c2092f54e19f.zip |
We may fail to map a declaration in a template to its instantiated
declaration because of interesting ordering dependencies while
instantiating a class template or member class thereof. Complain,
rather than asserting (+Asserts) or silently rejecting the code
(-Asserts).
Fixes the crash-on-invalid in PR8965.
llvm-svn: 127129
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 33 | ||||
-rw-r--r-- | clang/test/SemaTemplate/instantiate-member-class.cpp | 23 |
3 files changed, 54 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index df43a7e9d01..d7a1c387ac8 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2439,6 +2439,11 @@ def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; +def err_member_not_yet_instantiated : Error< + "no member %0 in %1; it has not yet been instantiated">; +def note_non_instantiated_member_here : Note< + "not-yet-instantiated member is declared here">; + def err_member_redeclared : Error<"class member cannot be redeclared">; def err_member_name_of_class : Error<"member %0 has the same name as its class">; def err_member_def_undefined_record : Error< diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0b46642f871..102ef518089 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3001,11 +3001,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // If our context used to be dependent, we may need to instantiate // it before performing lookup into that context. + bool IsBeingInstantiated = false; if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) { if (!Spec->isDependentContext()) { QualType T = Context.getTypeDeclType(Spec); const RecordType *Tag = T->getAs<RecordType>(); assert(Tag && "type of non-dependent record is not a RecordType"); + if (Tag->isBeingDefined()) + IsBeingInstantiated = true; if (!Tag->isBeingDefined() && RequireCompleteType(Loc, T, diag::err_incomplete_type)) return 0; @@ -3032,13 +3035,29 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, ParentDC->decls_end()); } - // UsingShadowDecls can instantiate to nothing because of using hiding. - // Note: this assertion end up firing in invalid code even when none of the - // AST invariants have been broken, so we explicitly check whether any - // errors have been emitted - assert((Result || isa<UsingShadowDecl>(D) || Diags.hasErrorOccurred()) && - "Unable to find instantiation of declaration!"); - + if (!Result) { + if (isa<UsingShadowDecl>(D)) { + // UsingShadowDecls can instantiate to nothing because of using hiding. + } else if (Diags.hasErrorOccurred()) { + // We've already complained about something, so most likely this + // declaration failed to instantiate. There's no point in complaining + // further, since this is normal in invalid code. + } else if (IsBeingInstantiated) { + // The class in which this member exists is currently being + // instantiated, and we haven't gotten around to instantiating this + // member yet. This can happen when the code uses forward declarations + // of member classes, and introduces ordering dependencies via + // template instantiation. + Diag(Loc, diag::err_member_not_yet_instantiated) + << D->getDeclName() + << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC)); + Diag(D->getLocation(), diag::note_non_instantiated_member_here); + } else { + // We should have found something, but didn't. + llvm_unreachable("Unable to find instantiation of declaration!"); + } + } + D = Result; } diff --git a/clang/test/SemaTemplate/instantiate-member-class.cpp b/clang/test/SemaTemplate/instantiate-member-class.cpp index f1bdf3e1e6d..74c2609dcd0 100644 --- a/clang/test/SemaTemplate/instantiate-member-class.cpp +++ b/clang/test/SemaTemplate/instantiate-member-class.cpp @@ -1,5 +1,28 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s +namespace PR8965 { + template<typename T> + struct X { + typedef int type; + + T field; // expected-note{{in instantiation of member class}} + }; + + template<typename T> + struct Y { + struct Inner; + + typedef typename X<Inner>::type // expected-note{{in instantiation of template class}} + type; // expected-note{{not-yet-instantiated member is declared here}} + + struct Inner { + typedef type field; // expected-error{{no member 'type' in 'PR8965::Y<int>'; it has not yet been instantiated}} + }; + }; + + Y<int> y; // expected-note{{in instantiation of template class}} +} + template<typename T> class X { public: |