r354091 - Fix implementation of [temp.local]p4.
Francis Visoiu Mistrih via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 14 19:06:00 PST 2019
I reverted this temporarily in r354097.
> On Feb 14, 2019, at 6:35 PM, Francis Visoiu Mistrih <francisvm at 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 at lists.llvm.org <mailto:cfe-commits at 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 at lists.llvm.org <mailto:cfe-commits at lists.llvm.org>
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190214/dbbbd1df/attachment-0001.html>
More information about the cfe-commits
mailing list