From: Douglas Gregor Date: Fri, 4 Feb 2011 13:35:07 +0000 (+0000) Subject: Improve our handling of the current instantiation for qualified X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2f9f89c6938a788a904c3be3ae7a64f4297c90a6;p=clang Improve our handling of the current instantiation for qualified id-expression, e.g., CurrentClass::member Previously, if CurrentClass was dependent and not complete, we would treat it as a dependent-scoped declaration reference expression, even if CurrentClass referred to the current instantiation. Fixes PR8966 and improves type checking of templates. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124867 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0d4950fd16..a464977779 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1035,28 +1035,6 @@ static void DecomposeUnqualifiedId(Sema &SemaRef, } } -/// Determines whether the given record is "fully-formed" at the given -/// location, i.e. whether a qualified lookup into it is assured of -/// getting consistent results already. -static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) { - if (!Record->hasDefinition()) - return false; - - for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), - E = Record->bases_end(); I != E; ++I) { - CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType()); - CanQual BaseRT = BaseT->getAs(); - if (!BaseRT) return false; - - CXXRecordDecl *BaseRecord = cast(BaseRT->getDecl()); - if (!BaseRecord->hasDefinition() || - !IsFullyFormedScope(SemaRef, BaseRecord)) - return false; - } - - return true; -} - /// Determines if the given class is provably not derived from all of /// the prospective base classes. static bool IsProvablyNotDerivedFrom(Sema &SemaRef, @@ -1489,9 +1467,6 @@ ExprResult Sema::ActOnIdExpression(Scope *S, if (DC) { if (RequireCompleteDeclContext(SS, DC)) return ExprError(); - // FIXME: We should be checking whether DC is the current instantiation. - if (CXXRecordDecl *RD = dyn_cast(DC)) - DependentID = !IsFullyFormedScope(*this, RD); } else { DependentID = true; } @@ -1513,10 +1488,21 @@ ExprResult Sema::ActOnIdExpression(Scope *S, bool MemberOfUnknownSpecialization; LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, MemberOfUnknownSpecialization); + + if (MemberOfUnknownSpecialization || + (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)) + return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand, + TemplateArgs); } else { IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl()); LookupParsedName(R, S, &SS, !IvarLookupFollowUp); + // If the result might be in a dependent base class, this is a dependent + // id-expression. + if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand, + TemplateArgs); + // If this reference is in an Objective-C method, then we need to do // some special Objective-C lookup, too. if (IvarLookupFollowUp) { diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp index 77961069c5..5776ddca2c 100644 --- a/test/SemaTemplate/dependent-names.cpp +++ b/test/SemaTemplate/dependent-names.cpp @@ -102,3 +102,30 @@ namespace test1 { template struct Derived; // expected-note {{requested here}} } + +namespace PR8966 { + template + class MyClassCore + { + }; + + template + class MyClass : public MyClassCore + { + public: + enum { + N + }; + + // static member declaration + static const char* array [N]; + + void f() { + MyClass::InBase = 17; + } + }; + + // static member definition + template + const char* MyClass::array [MyClass::N] = { "A", "B", "C" }; +}