I reverted this temporarily in r354097. > On Feb 14, 2019, at 6:35 PM, Francis Visoiu Mistrih <franci...@yahoo.com> > wrote: > > Hi Richard, > > This seems to now emit an error when building the sanitizer tests: > http://green.lab.llvm.org/green/job/clang-stage1-configure-RA/53965/consoleFull > > <http://green.lab.llvm.org/green/job/clang-stage1-configure-RA/53965/consoleFull>. > > I managed to reproduce it locally and when reverting your commit the error > goes away. > > I am not sure if the error is in the sanitizer test’s code or actually a > compiler error. Can you please take a look? > > Thanks, > > -- > Francis > >> On Feb 14, 2019, at 4:29 PM, Richard Smith via cfe-commits >> <cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>> wrote: >> >> Author: rsmith >> Date: Thu Feb 14 16:29:04 2019 >> New Revision: 354091 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=354091&view=rev >> <http://llvm.org/viewvc/llvm-project?rev=354091&view=rev> >> Log: >> Fix implementation of [temp.local]p4. >> >> When a template-name is looked up, we need to give injected-class-name >> declarations of class templates special treatment, as they denote a >> template rather than a type. >> >> Previously we achieved this by applying a filter to the lookup results >> after completing name lookup, but that is incorrect in various ways, not >> least of which is that it lost all information about access and how >> members were named, and the filtering caused us to generally lose >> all ambiguity errors between templates and non-templates. >> >> We now preserve the lookup results exactly, and the few places that need >> to map from a declaration found by name lookup into a declaration of a >> template do so explicitly. Deduplication of repeated lookup results of >> the same injected-class-name declaration is done by name lookup instead >> of after the fact. >> >> Modified: >> cfe/trunk/include/clang/Sema/Lookup.h >> cfe/trunk/include/clang/Sema/Sema.h >> cfe/trunk/lib/Sema/SemaDecl.cpp >> cfe/trunk/lib/Sema/SemaDeclCXX.cpp >> cfe/trunk/lib/Sema/SemaLookup.cpp >> cfe/trunk/lib/Sema/SemaTemplate.cpp >> cfe/trunk/test/CXX/class.access/p4.cpp >> cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp >> cfe/trunk/test/SemaTemplate/temp.cpp >> >> Modified: cfe/trunk/include/clang/Sema/Lookup.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Lookup.h?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Lookup.h?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/include/clang/Sema/Lookup.h (original) >> +++ cfe/trunk/include/clang/Sema/Lookup.h Thu Feb 14 16:29:04 2019 >> @@ -172,7 +172,8 @@ public: >> : SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo), >> LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl), >> ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags), >> - AllowHidden(Other.AllowHidden) {} >> + AllowHidden(Other.AllowHidden), >> + TemplateNameLookup(Other.TemplateNameLookup) {} >> >> // FIXME: Remove these deleted methods once the default build includes >> // -Wdeprecated. >> @@ -193,7 +194,8 @@ public: >> HideTags(std::move(Other.HideTags)), >> Diagnose(std::move(Other.Diagnose)), >> AllowHidden(std::move(Other.AllowHidden)), >> - Shadowed(std::move(Other.Shadowed)) { >> + Shadowed(std::move(Other.Shadowed)), >> + TemplateNameLookup(std::move(Other.TemplateNameLookup)) { >> Other.Paths = nullptr; >> Other.Diagnose = false; >> } >> @@ -216,6 +218,7 @@ public: >> Diagnose = std::move(Other.Diagnose); >> AllowHidden = std::move(Other.AllowHidden); >> Shadowed = std::move(Other.Shadowed); >> + TemplateNameLookup = std::move(Other.TemplateNameLookup); >> Other.Paths = nullptr; >> Other.Diagnose = false; >> return *this; >> @@ -286,6 +289,15 @@ public: >> HideTags = Hide; >> } >> >> + /// Sets whether this is a template-name lookup. For template-name >> lookups, >> + /// injected-class-names are treated as naming a template rather than a >> + /// template specialization. >> + void setTemplateNameLookup(bool TemplateName) { >> + TemplateNameLookup = TemplateName; >> + } >> + >> + bool isTemplateNameLookup() const { return TemplateNameLookup; } >> + >> bool isAmbiguous() const { >> return getResultKind() == Ambiguous; >> } >> @@ -739,6 +751,9 @@ private: >> /// declaration that we skipped. This only happens when \c LookupKind >> /// is \c LookupRedeclarationWithLinkage. >> bool Shadowed = false; >> + >> + /// True if we're looking up a template-name. >> + bool TemplateNameLookup = false; >> }; >> >> /// Consumes visible declarations found when searching for >> >> Modified: cfe/trunk/include/clang/Sema/Sema.h >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/include/clang/Sema/Sema.h (original) >> +++ cfe/trunk/include/clang/Sema/Sema.h Thu Feb 14 16:29:04 2019 >> @@ -6212,9 +6212,21 @@ public: >> // C++ Templates [C++ 14] >> // >> void FilterAcceptableTemplateNames(LookupResult &R, >> - bool AllowFunctionTemplates = true); >> + bool AllowFunctionTemplates = true, >> + bool AllowDependent = true); >> bool hasAnyAcceptableTemplateNames(LookupResult &R, >> - bool AllowFunctionTemplates = true); >> + bool AllowFunctionTemplates = true, >> + bool AllowDependent = true); >> + /// Try to interpret the lookup result D as a template-name. >> + /// >> + /// \param D A declaration found by name lookup. >> + /// \param AllowFunctionTemplates Whether function templates should be >> + /// considered valid results. >> + /// \param AllowDependent Whether unresolved using declarations (that >> might >> + /// name templates) should be considered valid results. >> + NamedDecl *getAsTemplateNameDecl(NamedDecl *D, >> + bool AllowFunctionTemplates = true, >> + bool AllowDependent = true); >> >> bool LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, >> QualType ObjectType, bool EnteringContext, >> >> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Feb 14 16:29:04 2019 >> @@ -1017,7 +1017,8 @@ Corrected: >> >> case LookupResult::Ambiguous: >> if (getLangOpts().CPlusPlus && NextToken.is >> <http://nexttoken.is/>(tok::less) && >> - hasAnyAcceptableTemplateNames(Result)) { >> + hasAnyAcceptableTemplateNames(Result, >> /*AllowFunctionTemplates=*/true, >> + /*AllowDependent=*/false)) { >> // C++ [temp.local]p3: >> // A lookup that finds an injected-class-name (10.2) can result in an >> // ambiguity in certain cases (for example, if it is found in more >> than >> @@ -1041,7 +1042,9 @@ Corrected: >> } >> >> if (getLangOpts().CPlusPlus && NextToken.is >> <http://nexttoken.is/>(tok::less) && >> - (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { >> + (IsFilteredTemplateName || >> + hasAnyAcceptableTemplateNames(Result, >> /*AllowFunctionTemplates=*/true, >> + /*AllowDependent=*/false))) { >> // C++ [temp.names]p3: >> // After name lookup (3.4) finds that a name is a template-name or that >> // an operator-function-id or a literal- operator-id refers to a set of >> @@ -1060,15 +1063,16 @@ Corrected: >> Template = Context.getOverloadedTemplateName(Result.begin(), >> Result.end()); >> } else { >> - TemplateDecl *TD >> - = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl()); >> + auto *TD = cast<TemplateDecl>(getAsTemplateNameDecl( >> + *Result.begin(), /*AllowFunctionTemplates=*/true, >> + /*AllowDependent=*/false)); >> IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); >> IsVarTemplate = isa<VarTemplateDecl>(TD); >> >> if (SS.isSet() && !SS.isInvalid()) >> - Template = Context.getQualifiedTemplateName(SS.getScopeRep(), >> - >> /*TemplateKeyword=*/false, >> - TD); >> + Template = >> + Context.getQualifiedTemplateName(SS.getScopeRep(), >> + /*TemplateKeyword=*/false, >> TD); >> else >> Template = TemplateName(TD); >> } >> >> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Feb 14 16:29:04 2019 >> @@ -1128,7 +1128,6 @@ static bool checkTupleLikeDecomposition( >> } >> } >> } >> - S.FilterAcceptableTemplateNames(MemberGet); >> } >> >> unsigned I = 0; >> >> Modified: cfe/trunk/lib/Sema/SemaLookup.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Feb 14 16:29:04 2019 >> @@ -2172,11 +2172,27 @@ bool Sema::LookupQualifiedName(LookupRes >> DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin(); >> DeclContext::lookup_iterator CurrentD = Path->Decls.begin(); >> >> + // Get the decl that we should use for deduplicating this lookup. >> + auto GetRepresentativeDecl = [&](NamedDecl *D) -> Decl * { >> + // C++ [temp.local]p3: >> + // A lookup that finds an injected-class-name (10.2) can result >> in >> + // an ambiguity in certain cases (for example, if it is found in >> + // more than one base class). If all of the injected-class-names >> + // that are found refer to specializations of the same class >> + // template, and if the name is used as a template-name, the >> + // reference refers to the class template itself and not a >> + // specialization thereof, and is not ambiguous. >> + if (R.isTemplateNameLookup()) >> + if (auto *TD = getAsTemplateNameDecl(D)) >> + D = TD; >> + return D->getUnderlyingDecl()->getCanonicalDecl(); >> + }; >> + >> while (FirstD != FirstPath->Decls.end() && >> CurrentD != Path->Decls.end()) { >> - if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() != >> - (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl()) >> - break; >> + if (GetRepresentativeDecl(*FirstD) != >> + GetRepresentativeDecl(*CurrentD)) >> + break; >> >> ++FirstD; >> ++CurrentD; >> >> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Feb 14 16:29:04 2019 >> @@ -66,17 +66,20 @@ static Expr *clang::formAssociatedConstr >> >> /// Determine whether the declaration found is acceptable as the name >> /// of a template and, if so, return that template declaration. Otherwise, >> -/// returns NULL. >> -static NamedDecl *isAcceptableTemplateName(ASTContext &Context, >> - NamedDecl *Orig, >> - bool AllowFunctionTemplates) { >> - NamedDecl *D = Orig->getUnderlyingDecl(); >> +/// returns null. >> +/// >> +/// Note that this may return an UnresolvedUsingValueDecl if AllowDependent >> +/// is true. In all other cases it will return a TemplateDecl (or null). >> +NamedDecl *Sema::getAsTemplateNameDecl(NamedDecl *D, >> + bool AllowFunctionTemplates, >> + bool AllowDependent) { >> + D = D->getUnderlyingDecl(); >> >> if (isa<TemplateDecl>(D)) { >> if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D)) >> return nullptr; >> >> - return Orig; >> + return D; >> } >> >> if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { >> @@ -107,54 +110,29 @@ static NamedDecl *isAcceptableTemplateNa >> // 'using Dependent::foo;' can resolve to a template name. >> // 'using typename Dependent::foo;' cannot (not even if 'foo' is an >> // injected-class-name). >> - if (isa<UnresolvedUsingValueDecl>(D)) >> + if (AllowDependent && isa<UnresolvedUsingValueDecl>(D)) >> return D; >> >> return nullptr; >> } >> >> void Sema::FilterAcceptableTemplateNames(LookupResult &R, >> - bool AllowFunctionTemplates) { >> - // The set of class templates we've already seen. >> - llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates; >> + bool AllowFunctionTemplates, >> + bool AllowDependent) { >> LookupResult::Filter filter = R.makeFilter(); >> while (filter.hasNext()) { >> NamedDecl *Orig = filter.next(); >> - NamedDecl *Repl = isAcceptableTemplateName(Context, Orig, >> - AllowFunctionTemplates); >> - if (!Repl) >> + if (!getAsTemplateNameDecl(Orig, AllowFunctionTemplates, >> AllowDependent)) >> filter.erase(); >> - else if (Repl != Orig) { >> - >> - // C++ [temp.local]p3: >> - // A lookup that finds an injected-class-name (10.2) can result in >> an >> - // ambiguity in certain cases (for example, if it is found in more >> than >> - // one base class). If all of the injected-class-names that are >> found >> - // refer to specializations of the same class template, and if the >> name >> - // is used as a template-name, the reference refers to the class >> - // template itself and not a specialization thereof, and is not >> - // ambiguous. >> - if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl)) >> - if (!ClassTemplates.insert(ClassTmpl).second) { >> - filter.erase(); >> - continue; >> - } >> - >> - // FIXME: we promote access to public here as a workaround to >> - // the fact that LookupResult doesn't let us remember that we >> - // found this template through a particular injected class name, >> - // which means we end up doing nasty things to the invariants. >> - // Pretending that access is public is *much* safer. >> - filter.replace(Repl, AS_public); >> - } >> } >> filter.done(); >> } >> >> bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R, >> - bool AllowFunctionTemplates) { >> + bool AllowFunctionTemplates, >> + bool AllowDependent) { >> for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) >> - if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates)) >> + if (getAsTemplateNameDecl(*I, AllowFunctionTemplates, AllowDependent)) >> return true; >> >> return false; >> @@ -198,20 +176,45 @@ TemplateNameKind Sema::isTemplateName(Sc >> MemberOfUnknownSpecialization)) >> return TNK_Non_template; >> if (R.empty()) return TNK_Non_template; >> + >> + NamedDecl *D = nullptr; >> if (R.isAmbiguous()) { >> - // Suppress diagnostics; we'll redo this lookup later. >> - R.suppressDiagnostics(); >> + // If we got an ambiguity involving a non-function template, treat this >> + // as a template name, and pick an arbitrary template for error >> recovery. >> + bool AnyFunctionTemplates = false; >> + for (NamedDecl *FoundD : R) { >> + if (NamedDecl *FoundTemplate = getAsTemplateNameDecl(FoundD)) { >> + if (isa<FunctionTemplateDecl>(FoundTemplate)) >> + AnyFunctionTemplates = true; >> + else { >> + D = FoundTemplate; >> + break; >> + } >> + } >> + } >> >> - // FIXME: we might have ambiguous templates, in which case we >> - // should at least parse them properly! >> - return TNK_Non_template; >> + // If we didn't find any templates at all, this isn't a template name. >> + // Leave the ambiguity for a later lookup to diagnose. >> + if (!D && !AnyFunctionTemplates) { >> + R.suppressDiagnostics(); >> + return TNK_Non_template; >> + } >> + >> + // If the only templates were function templates, filter out the rest. >> + // We'll diagnose the ambiguity later. >> + if (!D) >> + FilterAcceptableTemplateNames(R); >> } >> >> + // At this point, we have either picked a single template name >> declaration D >> + // or we have a non-empty set of results R containing either one template >> name >> + // declaration or a set of function templates. >> + >> TemplateName Template; >> TemplateNameKind TemplateKind; >> >> unsigned ResultCount = R.end() - R.begin(); >> - if (ResultCount > 1) { >> + if (!D && ResultCount > 1) { >> // We assume that we'll preserve the qualifier from a function >> // template name in other ways. >> Template = Context.getOverloadedTemplateName(R.begin(), R.end()); >> @@ -219,12 +222,19 @@ TemplateNameKind Sema::isTemplateName(Sc >> >> // We'll do this lookup again later. >> R.suppressDiagnostics(); >> - } else if >> (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) { >> - // We don't yet know whether this is a template-name or not. >> - MemberOfUnknownSpecialization = true; >> - return TNK_Non_template; >> } else { >> - TemplateDecl *TD = >> cast<TemplateDecl>((*R.begin())->getUnderlyingDecl()); >> + if (!D) { >> + D = getAsTemplateNameDecl(*R.begin()); >> + assert(D && "unambiguous result is not a template name"); >> + } >> + >> + if (isa<UnresolvedUsingValueDecl>(D)) { >> + // We don't yet know whether this is a template-name or not. >> + MemberOfUnknownSpecialization = true; >> + return TNK_Non_template; >> + } >> + >> + TemplateDecl *TD = cast<TemplateDecl>(D); >> >> if (SS.isSet() && !SS.isInvalid()) { >> NestedNameSpecifier *Qualifier = SS.getScopeRep(); >> @@ -316,6 +326,8 @@ bool Sema::LookupTemplateName(LookupResu >> bool EnteringContext, >> bool &MemberOfUnknownSpecialization, >> SourceLocation TemplateKWLoc) { >> + Found.setTemplateNameLookup(true); >> + >> // Determine where to perform name lookup >> MemberOfUnknownSpecialization = false; >> DeclContext *LookupCtx = nullptr; >> @@ -390,6 +402,9 @@ bool Sema::LookupTemplateName(LookupResu >> IsDependent |= Found.wasNotFoundInCurrentInstantiation(); >> } >> >> + if (Found.isAmbiguous()) >> + return false; >> + >> if (Found.empty() && !IsDependent) { >> // If we did not find any names, attempt to correct any typos. >> DeclarationName Name = Found.getLookupName(); >> @@ -407,7 +422,9 @@ bool Sema::LookupTemplateName(LookupResu >> if (auto *ND = Corrected.getFoundDecl()) >> Found.addDecl(ND); >> FilterAcceptableTemplateNames(Found); >> - if (!Found.empty()) { >> + if (Found.isAmbiguous()) { >> + Found.clear(); >> + } else if (!Found.empty()) { >> if (LookupCtx) { >> std::string CorrectedStr(Corrected.getAsString(getLangOpts())); >> bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && >> @@ -457,14 +474,19 @@ bool Sema::LookupTemplateName(LookupResu >> // Note: C++11 does not perform this second lookup. >> LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), >> LookupOrdinaryName); >> + FoundOuter.setTemplateNameLookup(true); >> LookupName(FoundOuter, S); >> + // FIXME: We silently accept an ambiguous lookup here, in violation of >> + // [basic.lookup]/1. >> FilterAcceptableTemplateNames(FoundOuter, >> /*AllowFunctionTemplates=*/false); >> >> + NamedDecl *OuterTemplate; >> if (FoundOuter.empty()) { >> // - if the name is not found, the name found in the class of the >> // object expression is used, otherwise >> - } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>() || >> - FoundOuter.isAmbiguous()) { >> + } else if (FoundOuter.isAmbiguous() || !FoundOuter.isSingleResult() || >> + !(OuterTemplate = >> + getAsTemplateNameDecl(FoundOuter.getFoundDecl()))) { >> // - if the name is found in the context of the entire >> // postfix-expression and does not name a class template, the name >> // found in the class of the object expression is used, otherwise >> @@ -474,8 +496,8 @@ bool Sema::LookupTemplateName(LookupResu >> // entity as the one found in the class of the object expression, >> // otherwise the program is ill-formed. >> if (!Found.isSingleResult() || >> - Found.getFoundDecl()->getCanonicalDecl() >> - != FoundOuter.getFoundDecl()->getCanonicalDecl()) { >> + getAsTemplateNameDecl(Found.getFoundDecl())->getCanonicalDecl() != >> + OuterTemplate->getCanonicalDecl()) { >> Diag(Found.getNameLoc(), >> diag::ext_nested_name_member_ref_lookup_ambiguous) >> << Found.getLookupName() >> @@ -545,7 +567,8 @@ void Sema::diagnoseExprIntendedAsTemplat >> >> // Try to correct the name by looking for templates and C++ named casts. >> struct TemplateCandidateFilter : CorrectionCandidateCallback { >> - TemplateCandidateFilter() { >> + Sema &S; >> + TemplateCandidateFilter(Sema &S) : S(S) { >> WantTypeSpecifiers = false; >> WantExpressionKeywords = false; >> WantRemainingKeywords = false; >> @@ -553,7 +576,7 @@ void Sema::diagnoseExprIntendedAsTemplat >> }; >> bool ValidateCandidate(const TypoCorrection &Candidate) override { >> if (auto *ND = Candidate.getCorrectionDecl()) >> - return isAcceptableTemplateName(ND->getASTContext(), ND, true); >> + return S.getAsTemplateNameDecl(ND); >> return Candidate.isKeyword(); >> } >> }; >> @@ -561,12 +584,11 @@ void Sema::diagnoseExprIntendedAsTemplat >> DeclarationName Name = NameInfo.getName(); >> if (TypoCorrection Corrected = >> CorrectTypo(NameInfo, LookupKind, S, &SS, >> - llvm::make_unique<TemplateCandidateFilter>(), >> + llvm::make_unique<TemplateCandidateFilter>(*this), >> CTK_ErrorRecovery, LookupCtx)) { >> auto *ND = Corrected.getFoundDecl(); >> if (ND) >> - ND = isAcceptableTemplateName(Context, ND, >> - /*AllowFunctionTemplates*/ true); >> + ND = getAsTemplateNameDecl(ND); >> if (ND || Corrected.isKeyword()) { >> if (LookupCtx) { >> std::string CorrectedStr(Corrected.getAsString(getLangOpts())); >> @@ -4262,7 +4284,7 @@ TemplateNameKind Sema::ActOnDependentTem >> LookupOrdinaryName); >> bool MOUS; >> if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, >> - MOUS, TemplateKWLoc)) >> + MOUS, TemplateKWLoc) && !R.isAmbiguous()) >> Diag(Name.getBeginLoc(), diag::err_no_member) >> << DNI.getName() << LookupCtx << SS.getRange(); >> return TNK_Non_template; >> >> Modified: cfe/trunk/test/CXX/class.access/p4.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/test/CXX/class.access/p4.cpp (original) >> +++ cfe/trunk/test/CXX/class.access/p4.cpp Thu Feb 14 16:29:04 2019 >> @@ -514,16 +514,12 @@ namespace test17 { >> } >> >> namespace test18 { >> - template <class T> class A {}; >> - class B : A<int> { >> + template <class T> class A {}; // expected-note {{member is declared >> here}} >> + class B : A<int> { // expected-note {{constrained by implicitly private >> inheritance here}} >> A<int> member; >> }; >> - >> - // FIXME: this access to A should be forbidden (because C++ is dumb), >> - // but LookupResult can't express the necessary information to do >> - // the check, so we aggressively suppress access control. >> class C : B { >> - A<int> member; >> + A<int> member; // expected-error {{'A' is a private member of >> 'test18::A<int>'}} >> }; >> } >> >> >> Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp (original) >> +++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp Thu Feb 14 >> 16:29:04 2019 >> @@ -380,10 +380,10 @@ template <class T> struct A { >> namespace test18 { >> namespace ns1 { template <class T> struct foo {}; } // >> expected-note{{candidate ignored: not a function template}} >> namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a >> function template}} >> -using ns1::foo; >> -using ns2::foo; >> +using ns1::foo; // expected-note {{found by name lookup}} >> +using ns2::foo; // expected-note {{found by name lookup}} >> >> template <class T> class A { >> - friend void foo<T>() {} // expected-error{{no candidate function template >> was found for dependent friend function template specialization}} >> + friend void foo<T>() {} // expected-error {{ambiguous}} >> expected-error{{no candidate function template was found for dependent >> friend function template specialization}} >> }; >> } >> >> Modified: cfe/trunk/test/SemaTemplate/temp.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp.cpp?rev=354091&r1=354090&r2=354091&view=diff >> >> <http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp.cpp?rev=354091&r1=354090&r2=354091&view=diff> >> ============================================================================== >> --- cfe/trunk/test/SemaTemplate/temp.cpp (original) >> +++ cfe/trunk/test/SemaTemplate/temp.cpp Thu Feb 14 16:29:04 2019 >> @@ -8,12 +8,43 @@ namespace test0 { >> >> // PR7252 >> namespace test1 { >> - namespace A { template<typename T> struct Base { typedef T t; }; } // >> expected-note {{member found}} >> + namespace A { template<typename T> struct Base { typedef T t; }; } // >> expected-note 3{{member}} >> namespace B { template<typename T> struct Base { typedef T t; }; } // >> expected-note {{member found}} >> >> template<typename T> struct Derived : A::Base<char>, B::Base<int> { >> - // FIXME: the syntax error here is unfortunate >> - typename Derived::Base<float>::t x; // expected-error {{found in >> multiple base classes of different types}} \ >> - // expected-error {{expected member >> name or ';'}} >> + typename Derived::Base<float>::t x; // expected-error {{found in >> multiple base classes of different types}} >> }; >> + >> + class X : A::Base<int> {}; // expected-note 2{{private}} >> + class Y : A::Base<float> {}; >> + struct Z : A::Base<double> {}; >> + struct Use1 : X, Y { >> + Base<double> b1; // expected-error {{private}} >> + Use1::Base<double> b2; // expected-error {{private}} >> + }; >> + struct Use2 : Z, Y { >> + Base<double> b1; >> + Use2::Base<double> b2; >> + }; >> + struct Use3 : X, Z { >> + Base<double> b1; >> + Use3::Base<double> b2; >> + }; >> +} >> + >> +namespace test2 { >> + struct A { static int x; }; // expected-note 4{{member}} >> + struct B { template<typename T> static T x(); }; // expected-note >> 4{{member}} >> + struct C { template<typename T> struct x {}; }; // expected-note >> 3{{member}} >> + struct D { template<typename T> static T x(); }; // expected-note >> {{member}} >> + >> + template<typename ...T> struct X : T... {}; >> + >> + void f() { >> + X<A, B>::x<int>(); // expected-error {{found in multiple base classes >> of different types}} >> + X<A, C>::x<int>(); // expected-error {{found in multiple base classes >> of different types}} >> + X<B, C>::x<int>(); // expected-error {{found in multiple base classes >> of different types}} >> + X<A, B, C>::x<int>(); // expected-error {{found in multiple base >> classes of different types}} >> + X<A, B, D>::x<int>(); // expected-error {{found in multiple base >> classes of different types}} >> + } >> } >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org> >> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits