forked from OSchip/llvm-project
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
This commit is contained in:
parent
d9bb152821
commit
528ad93924
|
@ -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_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
|
||||||
def err_no_member : Error<"no member named %0 in %1">;
|
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_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_name_of_class : Error<"member %0 has the same name as its class">;
|
||||||
def err_member_def_undefined_record : Error<
|
def err_member_def_undefined_record : Error<
|
||||||
|
|
|
@ -3001,11 +3001,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
||||||
|
|
||||||
// If our context used to be dependent, we may need to instantiate
|
// If our context used to be dependent, we may need to instantiate
|
||||||
// it before performing lookup into that context.
|
// it before performing lookup into that context.
|
||||||
|
bool IsBeingInstantiated = false;
|
||||||
if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
|
if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) {
|
||||||
if (!Spec->isDependentContext()) {
|
if (!Spec->isDependentContext()) {
|
||||||
QualType T = Context.getTypeDeclType(Spec);
|
QualType T = Context.getTypeDeclType(Spec);
|
||||||
const RecordType *Tag = T->getAs<RecordType>();
|
const RecordType *Tag = T->getAs<RecordType>();
|
||||||
assert(Tag && "type of non-dependent record is not a RecordType");
|
assert(Tag && "type of non-dependent record is not a RecordType");
|
||||||
|
if (Tag->isBeingDefined())
|
||||||
|
IsBeingInstantiated = true;
|
||||||
if (!Tag->isBeingDefined() &&
|
if (!Tag->isBeingDefined() &&
|
||||||
RequireCompleteType(Loc, T, diag::err_incomplete_type))
|
RequireCompleteType(Loc, T, diag::err_incomplete_type))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3032,13 +3035,29 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
|
||||||
ParentDC->decls_end());
|
ParentDC->decls_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// UsingShadowDecls can instantiate to nothing because of using hiding.
|
if (!Result) {
|
||||||
// Note: this assertion end up firing in invalid code even when none of the
|
if (isa<UsingShadowDecl>(D)) {
|
||||||
// AST invariants have been broken, so we explicitly check whether any
|
// UsingShadowDecls can instantiate to nothing because of using hiding.
|
||||||
// errors have been emitted
|
} else if (Diags.hasErrorOccurred()) {
|
||||||
assert((Result || isa<UsingShadowDecl>(D) || Diags.hasErrorOccurred()) &&
|
// We've already complained about something, so most likely this
|
||||||
"Unable to find instantiation of declaration!");
|
// 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;
|
D = Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,28 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
// 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>
|
template<typename T>
|
||||||
class X {
|
class X {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue