[cfe-commits] r127129 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-member-class.cpp
Douglas Gregor
dgregor at apple.com
Sun Mar 6 12:12:45 PST 2011
Author: dgregor
Date: Sun Mar 6 14:12:45 2011
New Revision: 127129
URL: http://llvm.org/viewvc/llvm-project?rev=127129&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/instantiate-member-class.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=127129&r1=127128&r2=127129&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Mar 6 14:12:45 2011
@@ -2439,6 +2439,11 @@
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<
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=127129&r1=127128&r2=127129&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Mar 6 14:12:45 2011
@@ -3001,11 +3001,14 @@
// 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 @@
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;
}
Modified: cfe/trunk/test/SemaTemplate/instantiate-member-class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-class.cpp?rev=127129&r1=127128&r2=127129&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-class.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-class.cpp Sun Mar 6 14:12:45 2011
@@ -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:
More information about the cfe-commits
mailing list