mirror of https://github.com/microsoft/clang.git
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:
parent
1fafd1d964
commit
647c8b32c2
|
@ -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);
|
||||
|
|
|
@ -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>'}}
|
||||
}
|
Loading…
Reference in New Issue