PR7837: For qualified id's, make sure the decl context is complete if not

dependent in ActOnIdExpression.  (This issue only shows up with member
operators because an operator is never a type.)



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110486 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2010-08-06 23:41:47 +00:00
parent 1fafd1d964
commit 647c8b32c2
2 changed files with 29 additions and 20 deletions

View File

@ -699,23 +699,6 @@ static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) {
return true;
}
/// Determines whether we can lookup this id-expression now or whether
/// we have to wait until template instantiation is complete.
static bool IsDependentIdExpression(Sema &SemaRef, const CXXScopeSpec &SS) {
DeclContext *DC = SemaRef.computeDeclContext(SS, false);
// If the qualifier scope isn't computable, it's definitely dependent.
if (!DC) return true;
// If the qualifier scope doesn't name a record, we can always look into it.
if (!isa<CXXRecordDecl>(DC)) return false;
// We can't look into record types unless they're fully-formed.
if (!IsFullyFormedScope(SemaRef, cast<CXXRecordDecl>(DC))) return true;
return false;
}
/// Determines if the given class is provably not derived from all of
/// the prospective base classes.
static bool IsProvablyNotDerivedFrom(Sema &SemaRef,
@ -1100,9 +1083,24 @@ Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S,
// names a dependent type.
// Determine whether this is a member of an unknown specialization;
// we need to handle these differently.
if ((Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
Name.getCXXNameType()->isDependentType()) ||
(SS.isSet() && IsDependentIdExpression(*this, SS))) {
bool DependentID = false;
if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
Name.getCXXNameType()->isDependentType()) {
DependentID = true;
} else if (SS.isSet()) {
DeclContext *DC = computeDeclContext(SS, false);
if (DC) {
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
// FIXME: We should be checking whether DC is the current instantiation.
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC))
DependentID = !IsFullyFormedScope(*this, RD);
} else {
DependentID = true;
}
}
if (DependentID) {
return ActOnDependentIdExpression(SS, Name, NameLoc,
isAddressOfOperand,
TemplateArgs);

View File

@ -0,0 +1,11 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// PR7837
template<class T> struct C1 { void operator()(T); };
template<class T> struct C2; // expected-note {{template is declared here}}
template<class T> void foo(T);
void wrap() {
foo(&C1<int>::operator());
foo(&C1<int>::operator+); // expected-error {{no member named 'operator+' in 'C1<int>'}}
foo(&C2<int>::operator+); // expected-error {{implicit instantiation of undefined template 'C2<int>'}}
}