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