<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Richard,<div class=""><br class=""></div><div class="">It looks like this patch is causing clang to reject the following code, which used to compile fine:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 0, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">$ cat test.cpp</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 0, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">typedef __attribute__((__ext_vector_type__(2))) float vector_float2;</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 0, 0); min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 0, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">bool foo123(vector_float2 &A, vector_float2 &B)</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 0, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">{</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 0, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> return A.x < B.x && B.y > A.y;</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 0, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div><div><br class=""><blockquote type="cite" class=""><div class="">On May 8, 2019, at 8:31 PM, Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Author: rsmith<br class="">Date: Wed May 8 20:31:27 2019<br class="">New Revision: 360308<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=360308&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=360308&view=rev</a><br class="">Log:<br class="">[c++20] Implement P0846R0: allow (ADL-only) calls to template-ids whose<br class="">template name is not visible to unqualified lookup.<br class=""><br class="">In order to support this without a severe degradation in our ability to<br class="">diagnose typos in template names, this change significantly restructures<br class="">the way we handle template-id-shaped syntax for which lookup of the<br class="">template name finds nothing.<br class=""><br class="">Instead of eagerly diagnosing an undeclared template name, we now form a<br class="">placeholder template-name representing a name that is known to not find<br class="">any templates. When the parser sees such a name, it attempts to<br class="">disambiguate whether we have a less-than comparison or a template-id.<br class="">Any diagnostics or typo-correction for the name are delayed until its<br class="">point of use.<br class=""><br class="">The upshot should be a small improvement of our diagostic quality<br class="">overall: we now take more syntactic context into account when trying to<br class="">resolve an undeclared identifier on the left hand side of a '<'. In<br class="">fact, this works well enough that the backwards-compatible portion (for<br class="">an undeclared identifier rather than a lookup that finds functions but<br class="">no function templates) is enabled in all language modes.<br class=""><br class="">Added:<br class=""> cfe/trunk/test/SemaCXX/cxx2a-adl-only-template-id.cpp<br class="">Modified:<br class=""> cfe/trunk/include/clang/AST/ASTContext.h<br class=""> cfe/trunk/include/clang/AST/DeclarationName.h<br class=""> cfe/trunk/include/clang/AST/TemplateName.h<br class=""> cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br class=""> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br class=""> cfe/trunk/include/clang/Basic/TemplateKinds.h<br class=""> cfe/trunk/include/clang/Parse/Parser.h<br class=""> cfe/trunk/include/clang/Sema/Sema.h<br class=""> cfe/trunk/lib/AST/ASTContext.cpp<br class=""> cfe/trunk/lib/AST/ASTImporter.cpp<br class=""> cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp<br class=""> cfe/trunk/lib/AST/ItaniumMangle.cpp<br class=""> cfe/trunk/lib/AST/ODRHash.cpp<br class=""> cfe/trunk/lib/AST/TemplateName.cpp<br class=""> cfe/trunk/lib/Parse/ParseDecl.cpp<br class=""> cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br class=""> cfe/trunk/lib/Parse/ParseExprCXX.cpp<br class=""> cfe/trunk/lib/Parse/ParseTemplate.cpp<br class=""> cfe/trunk/lib/Parse/ParseTentative.cpp<br class=""> cfe/trunk/lib/Parse/Parser.cpp<br class=""> cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp<br class=""> cfe/trunk/lib/Sema/SemaDecl.cpp<br class=""> cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br class=""> cfe/trunk/lib/Sema/SemaExpr.cpp<br class=""> cfe/trunk/lib/Sema/SemaExprCXX.cpp<br class=""> cfe/trunk/lib/Sema/SemaOverload.cpp<br class=""> cfe/trunk/lib/Sema/SemaTemplate.cpp<br class=""> cfe/trunk/lib/Serialization/ASTReader.cpp<br class=""> cfe/trunk/lib/Serialization/ASTWriter.cpp<br class=""> cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp<br class=""> cfe/trunk/test/CXX/drs/dr2xx.cpp<br class=""> cfe/trunk/test/CXX/drs/dr6xx.cpp<br class=""> cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp<br class=""> cfe/trunk/test/FixIt/typo-crash.cpp<br class=""> cfe/trunk/test/Misc/diag-template-diffing.cpp<br class=""> cfe/trunk/test/Modules/module-private.cpp<br class=""> cfe/trunk/test/Modules/submodules-merge-defs.cpp<br class=""> cfe/trunk/test/Parser/cxx-ambig-init-templ.cpp<br class=""> cfe/trunk/test/Parser/cxx-template-argument.cpp<br class=""> cfe/trunk/test/Parser/cxx-template-decl.cpp<br class=""> cfe/trunk/test/SemaCXX/alias-template.cpp<br class=""> cfe/trunk/test/SemaCXX/class.cpp<br class=""> cfe/trunk/test/SemaCXX/destructor.cpp<br class=""> cfe/trunk/test/SemaCXX/invalid-member-expr.cpp<br class=""> cfe/trunk/test/SemaCXX/typo-correction.cpp<br class=""> cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp<br class=""> cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp<br class=""> cfe/trunk/test/SemaTemplate/rdar9173693.cpp<br class=""> cfe/trunk/test/SemaTemplate/recovery-crash.cpp<br class=""> cfe/trunk/tools/libclang/CIndex.cpp<br class=""> cfe/trunk/www/cxx_status.html<br class=""><br class="">Modified: cfe/trunk/include/clang/AST/ASTContext.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/AST/ASTContext.h (original)<br class="">+++ cfe/trunk/include/clang/AST/ASTContext.h Wed May 8 20:31:27 2019<br class="">@@ -1977,6 +1977,7 @@ public:<br class=""><br class=""> TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,<br class=""> UnresolvedSetIterator End) const;<br class="">+ TemplateName getAssumedTemplateName(DeclarationName Name) const;<br class=""><br class=""> TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,<br class=""> bool TemplateKeyword,<br class=""><br class="">Modified: cfe/trunk/include/clang/AST/DeclarationName.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclarationName.h?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclarationName.h?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/AST/DeclarationName.h (original)<br class="">+++ cfe/trunk/include/clang/AST/DeclarationName.h Wed May 8 20:31:27 2019<br class="">@@ -863,4 +863,24 @@ struct DenseMapInfo<clang::DeclarationNa<br class=""><br class=""> } // namespace llvm<br class=""><br class="">+// The definition of AssumedTemplateStorage is factored out of TemplateName to<br class="">+// resolve a cyclic dependency between it and DeclarationName (via Type).<br class="">+namespace clang {<br class="">+<br class="">+/// A structure for storing the information associated with a name that has<br class="">+/// been assumed to be a template name (despite finding no TemplateDecls).<br class="">+class AssumedTemplateStorage : public UncommonTemplateNameStorage {<br class="">+ friend class ASTContext;<br class="">+<br class="">+ AssumedTemplateStorage(DeclarationName Name)<br class="">+ : UncommonTemplateNameStorage(Assumed, 0), Name(Name) {}<br class="">+ DeclarationName Name;<br class="">+<br class="">+public:<br class="">+ /// Get the name of the template.<br class="">+ DeclarationName getDeclName() const { return Name; }<br class="">+};<br class="">+<br class="">+} // namespace clang<br class="">+<br class=""> #endif // LLVM_CLANG_AST_DECLARATIONNAME_H<br class=""><br class="">Modified: cfe/trunk/include/clang/AST/TemplateName.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateName.h?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateName.h?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/AST/TemplateName.h (original)<br class="">+++ cfe/trunk/include/clang/AST/TemplateName.h Wed May 8 20:31:27 2019<br class="">@@ -31,6 +31,7 @@ class NamedDecl;<br class=""> class NestedNameSpecifier;<br class=""> enum OverloadedOperatorKind : int;<br class=""> class OverloadedTemplateStorage;<br class="">+class AssumedTemplateStorage;<br class=""> class PartialDiagnostic;<br class=""> struct PrintingPolicy;<br class=""> class QualifiedTemplateName;<br class="">@@ -46,6 +47,7 @@ class UncommonTemplateNameStorage {<br class=""> protected:<br class=""> enum Kind {<br class=""> Overloaded,<br class="">+ Assumed, // defined in DeclarationName.h<br class=""> SubstTemplateTemplateParm,<br class=""> SubstTemplateTemplateParmPack<br class=""> };<br class="">@@ -78,6 +80,12 @@ public:<br class=""> : nullptr;<br class=""> }<br class=""><br class="">+ AssumedTemplateStorage *getAsAssumedTemplateName() {<br class="">+ return Bits.Kind == Assumed<br class="">+ ? reinterpret_cast<AssumedTemplateStorage *>(this)<br class="">+ : nullptr;<br class="">+ }<br class="">+<br class=""> SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {<br class=""> return Bits.Kind == SubstTemplateTemplateParm<br class=""> ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)<br class="">@@ -194,6 +202,10 @@ public:<br class=""> /// A set of overloaded template declarations.<br class=""> OverloadedTemplate,<br class=""><br class="">+ /// An unqualified-id that has been assumed to name a function template<br class="">+ /// that will be found by ADL.<br class="">+ AssumedTemplate,<br class="">+<br class=""> /// A qualified template name, where the qualification is kept<br class=""> /// to describe the source code as written.<br class=""> QualifiedTemplate,<br class="">@@ -215,6 +227,7 @@ public:<br class=""> TemplateName() = default;<br class=""> explicit TemplateName(TemplateDecl *Template);<br class=""> explicit TemplateName(OverloadedTemplateStorage *Storage);<br class="">+ explicit TemplateName(AssumedTemplateStorage *Storage);<br class=""> explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);<br class=""> explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);<br class=""> explicit TemplateName(QualifiedTemplateName *Qual);<br class="">@@ -236,7 +249,7 @@ public:<br class=""> TemplateDecl *getAsTemplateDecl() const;<br class=""><br class=""> /// Retrieve the underlying, overloaded function template<br class="">- // declarations that this template name refers to, if known.<br class="">+ /// declarations that this template name refers to, if known.<br class=""> ///<br class=""> /// \returns The set of overloaded function templates that this template<br class=""> /// name refers to, if known. If the template name does not refer to a<br class="">@@ -244,6 +257,10 @@ public:<br class=""> /// refers to a single template, returns NULL.<br class=""> OverloadedTemplateStorage *getAsOverloadedTemplate() const;<br class=""><br class="">+ /// Retrieve information on a name that has been assumed to be a<br class="">+ /// template-name in order to permit a call via ADL.<br class="">+ AssumedTemplateStorage *getAsAssumedTemplateName() const;<br class="">+<br class=""> /// Retrieve the substituted template template parameter, if<br class=""> /// known.<br class=""> ///<br class=""><br class="">Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)<br class="">+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed May 8 20:31:27 2019<br class="">@@ -744,7 +744,8 @@ def err_typename_refers_to_non_type_temp<br class=""> def err_expected_type_name_after_typename : Error<<br class=""> "expected an identifier or template-id after '::'">;<br class=""> def err_explicit_spec_non_template : Error<<br class="">- "explicit %select{specialization|instantiation}0 of non-template %1 %2">;<br class="">+ "explicit %select{specialization|instantiation}0 of "<br class="">+ "%select{non-|undeclared }3template %1 %2">;<br class=""><br class=""> def err_default_template_template_parameter_not_template : Error<<br class=""> "default template argument for a template template parameter must be a class "<br class=""><br class="">Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br class="">+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May 8 20:31:27 2019<br class="">@@ -3963,6 +3963,15 @@ def err_template_member_noparams : Error<br class=""> def err_template_tag_noparams : Error<<br class=""> "extraneous 'template<>' in declaration of %0 %1">;<br class=""><br class="">+def warn_cxx17_compat_adl_only_template_id : Warning<<br class="">+ "use of function template name with no prior function template "<br class="">+ "declaration in function call with explicit template arguments "<br class="">+ "is incompatible with C++ standards before C++2a">,<br class="">+ InGroup<CXXPre2aCompat>, DefaultIgnore;<br class="">+def ext_adl_only_template_id : ExtWarn<<br class="">+ "use of function template name with no prior declaration in function call "<br class="">+ "with explicit template arguments is a C++2a extension">, InGroup<CXX2a>;<br class="">+<br class=""> // C++ Template Argument Lists<br class=""> def err_template_missing_args : Error<<br class=""> "use of "<br class=""><br class="">Modified: cfe/trunk/include/clang/Basic/TemplateKinds.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TemplateKinds.h?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TemplateKinds.h?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Basic/TemplateKinds.h (original)<br class="">+++ cfe/trunk/include/clang/Basic/TemplateKinds.h Wed May 8 20:31:27 2019<br class="">@@ -21,7 +21,8 @@ enum TemplateNameKind {<br class=""> /// The name does not refer to a template.<br class=""> TNK_Non_template = 0,<br class=""> /// The name refers to a function template or a set of overloaded<br class="">- /// functions that includes at least one function template.<br class="">+ /// functions that includes at least one function template, or (in C++20)<br class="">+ /// refers to a set of non-template functions but is followed by a '<'.<br class=""> TNK_Function_template,<br class=""> /// The name refers to a template whose specialization produces a<br class=""> /// type. The template itself could be a class template, template<br class="">@@ -42,7 +43,11 @@ enum TemplateNameKind {<br class=""> /// whether the template name is assumed to refer to a type template or a<br class=""> /// function template depends on the context in which the template<br class=""> /// name occurs.<br class="">- TNK_Dependent_template_name<br class="">+ TNK_Dependent_template_name,<br class="">+ /// Lookup for the name failed, but we're assuming it was a template name<br class="">+ /// anyway. In C++20, this is mandatory in order to parse ADL-only function<br class="">+ /// template specialization calls.<br class="">+ TNK_Undeclared_template,<br class=""> };<br class=""><br class=""> }<br class=""><br class="">Modified: cfe/trunk/include/clang/Parse/Parser.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Parse/Parser.h (original)<br class="">+++ cfe/trunk/include/clang/Parse/Parser.h Wed May 8 20:31:27 2019<br class="">@@ -2303,13 +2303,18 @@ private:<br class=""> /// Doesn't consume tokens.<br class=""> TPResult<br class=""> isCXXDeclarationSpecifier(TPResult BracedCastResult = TPResult::False,<br class="">- bool *HasMissingTypename = nullptr);<br class="">+ bool *InvalidAsDeclSpec = nullptr);<br class=""><br class=""> /// Given that isCXXDeclarationSpecifier returns \c TPResult::True or<br class=""> /// \c TPResult::Ambiguous, determine whether the decl-specifier would be<br class=""> /// a type-specifier other than a cv-qualifier.<br class=""> bool isCXXDeclarationSpecifierAType();<br class=""><br class="">+ /// Determine whether the current token sequence might be<br class="">+ /// '<' template-argument-list '>'<br class="">+ /// rather than a less-than expression.<br class="">+ TPResult isTemplateArgumentList(unsigned TokensToSkip);<br class="">+<br class=""> /// Determine whether an identifier has been tentatively declared as a<br class=""> /// non-type. Such tentative declarations should not be found to name a type<br class=""> /// during a tentative parse, but also should not be annotated as a non-type.<br class="">@@ -2994,7 +2999,6 @@ private:<br class=""> UnqualifiedId &TemplateName,<br class=""> bool AllowTypeAnnotation = true);<br class=""> void AnnotateTemplateIdTokenAsType(bool IsClassName = false);<br class="">- bool IsTemplateArgumentList(unsigned Skip = 0);<br class=""> bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);<br class=""> ParsedTemplateArgument ParseTemplateTemplateArgument();<br class=""> ParsedTemplateArgument ParseTemplateArgument();<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=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Sema/Sema.h (original)<br class="">+++ cfe/trunk/include/clang/Sema/Sema.h Wed May 8 20:31:27 2019<br class="">@@ -1823,7 +1823,8 @@ public:<br class=""> NC_NestedNameSpecifier,<br class=""> NC_TypeTemplate,<br class=""> NC_VarTemplate,<br class="">- NC_FunctionTemplate<br class="">+ NC_FunctionTemplate,<br class="">+ NC_UndeclaredTemplate,<br class=""> };<br class=""><br class=""> class NameClassification {<br class="">@@ -1871,6 +1872,12 @@ public:<br class=""> return Result;<br class=""> }<br class=""><br class="">+ static NameClassification UndeclaredTemplate(TemplateName Name) {<br class="">+ NameClassification Result(NC_UndeclaredTemplate);<br class="">+ Result.Template = Name;<br class="">+ return Result;<br class="">+ }<br class="">+<br class=""> NameClassificationKind getKind() const { return Kind; }<br class=""><br class=""> ParsedType getType() const {<br class="">@@ -1885,7 +1892,7 @@ public:<br class=""><br class=""> TemplateName getTemplateName() const {<br class=""> assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate ||<br class="">- Kind == NC_VarTemplate);<br class="">+ Kind == NC_VarTemplate || Kind == NC_UndeclaredTemplate);<br class=""> return Template;<br class=""> }<br class=""><br class="">@@ -1897,6 +1904,8 @@ public:<br class=""> return TNK_Function_template;<br class=""> case NC_VarTemplate:<br class=""> return TNK_Var_template;<br class="">+ case NC_UndeclaredTemplate:<br class="">+ return TNK_Undeclared_template;<br class=""> default:<br class=""> llvm_unreachable("unsupported name classification.");<br class=""> }<br class="">@@ -6256,7 +6265,8 @@ public:<br class=""> bool AllowDependent = true);<br class=""> bool hasAnyAcceptableTemplateNames(LookupResult &R,<br class=""> bool AllowFunctionTemplates = true,<br class="">- bool AllowDependent = true);<br class="">+ bool AllowDependent = true,<br class="">+ bool AllowNonTemplateFunctions = false);<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="">@@ -6268,10 +6278,20 @@ public:<br class=""> bool AllowFunctionTemplates = true,<br class=""> bool AllowDependent = true);<br class=""><br class="">+ enum class AssumedTemplateKind {<br class="">+ /// This is not assumed to be a template name.<br class="">+ None,<br class="">+ /// This is assumed to be a template name because lookup found nothing.<br class="">+ FoundNothing,<br class="">+ /// This is assumed to be a template name because lookup found one or more<br class="">+ /// functions (but no function templates).<br class="">+ FoundFunctions,<br class="">+ };<br class=""> bool LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,<br class=""> QualType ObjectType, bool EnteringContext,<br class=""> bool &MemberOfUnknownSpecialization,<br class="">- SourceLocation TemplateKWLoc = SourceLocation());<br class="">+ SourceLocation TemplateKWLoc = SourceLocation(),<br class="">+ AssumedTemplateKind *ATK = nullptr);<br class=""><br class=""> TemplateNameKind isTemplateName(Scope *S,<br class=""> CXXScopeSpec &SS,<br class="">@@ -6282,6 +6302,20 @@ public:<br class=""> TemplateTy &Template,<br class=""> bool &MemberOfUnknownSpecialization);<br class=""><br class="">+ /// Try to resolve an undeclared template name as a type template.<br class="">+ ///<br class="">+ /// Sets II to the identifier corresponding to the template name, and updates<br class="">+ /// Name to a corresponding (typo-corrected) type template name and TNK to<br class="">+ /// the corresponding kind, if possible.<br class="">+ void ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &Name,<br class="">+ TemplateNameKind &TNK,<br class="">+ SourceLocation NameLoc,<br class="">+ IdentifierInfo *&II);<br class="">+<br class="">+ bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,<br class="">+ SourceLocation NameLoc,<br class="">+ bool Diagnose = true);<br class="">+<br class=""> /// Determine whether a particular identifier might be the name in a C++1z<br class=""> /// deduction-guide declaration.<br class=""> bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name,<br class="">@@ -6391,14 +6425,11 @@ public:<br class=""> TemplateArgumentListInfo &TemplateArgs);<br class=""><br class=""> TypeResult<br class="">- ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,<br class="">+ ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,<br class=""> TemplateTy Template, IdentifierInfo *TemplateII,<br class="">- SourceLocation TemplateIILoc,<br class="">- SourceLocation LAngleLoc,<br class="">- ASTTemplateArgsPtr TemplateArgs,<br class="">- SourceLocation RAngleLoc,<br class="">- bool IsCtorOrDtorName = false,<br class="">- bool IsClassName = false);<br class="">+ SourceLocation TemplateIILoc, SourceLocation LAngleLoc,<br class="">+ ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc,<br class="">+ bool IsCtorOrDtorName = false, bool IsClassName = false);<br class=""><br class=""> /// Parsed an elaborated-type-specifier that refers to a template-id,<br class=""> /// such as \c class T::template apply<U>.<br class=""><br class="">Modified: cfe/trunk/lib/AST/ASTContext.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/AST/ASTContext.cpp (original)<br class="">+++ cfe/trunk/lib/AST/ASTContext.cpp Wed May 8 20:31:27 2019<br class="">@@ -5226,6 +5226,11 @@ ASTContext::getNameForTemplate(TemplateN<br class=""> return DeclarationNameInfo((*Storage->begin())->getDeclName(), NameLoc);<br class=""> }<br class=""><br class="">+ case TemplateName::AssumedTemplate: {<br class="">+ AssumedTemplateStorage *Storage = Name.getAsAssumedTemplateName();<br class="">+ return DeclarationNameInfo(Storage->getDeclName(), NameLoc);<br class="">+ }<br class="">+<br class=""> case TemplateName::DependentTemplate: {<br class=""> DependentTemplateName *DTN = Name.getAsDependentTemplateName();<br class=""> DeclarationName DName;<br class="">@@ -5273,7 +5278,8 @@ TemplateName ASTContext::getCanonicalTem<br class=""> }<br class=""><br class=""> case TemplateName::OverloadedTemplate:<br class="">- llvm_unreachable("cannot canonicalize overloaded template");<br class="">+ case TemplateName::AssumedTemplate:<br class="">+ llvm_unreachable("cannot canonicalize unresolved template");<br class=""><br class=""> case TemplateName::DependentTemplate: {<br class=""> DependentTemplateName *DTN = Name.getAsDependentTemplateName();<br class="">@@ -7620,6 +7626,13 @@ ASTContext::getOverloadedTemplateName(Un<br class=""> return TemplateName(OT);<br class=""> }<br class=""><br class="">+/// Retrieve a template name representing an unqualified-id that has been<br class="">+/// assumed to name a template for ADL purposes.<br class="">+TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const {<br class="">+ auto *OT = new (*this) AssumedTemplateStorage(Name);<br class="">+ return TemplateName(OT);<br class="">+}<br class="">+<br class=""> /// Retrieve the template name that represents a qualified<br class=""> /// template name such as \c std::vector.<br class=""> TemplateName<br class=""><br class="">Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br class="">+++ cfe/trunk/lib/AST/ASTImporter.cpp Wed May 8 20:31:27 2019<br class="">@@ -8126,6 +8126,14 @@ Expected<TemplateName> ASTImporter::Impo<br class=""> ToTemplates.end());<br class=""> }<br class=""><br class="">+ case TemplateName::AssumedTemplate: {<br class="">+ AssumedTemplateStorage *FromStorage = From.getAsAssumedTemplateName();<br class="">+ auto DeclNameOrErr = Import_New(FromStorage->getDeclName());<br class="">+ if (!DeclNameOrErr)<br class="">+ return DeclNameOrErr.takeError();<br class="">+ return ToContext.getAssumedTemplateName(*DeclNameOrErr);<br class="">+ }<br class="">+<br class=""> case TemplateName::QualifiedTemplate: {<br class=""> QualifiedTemplateName *QTN = From.getAsQualifiedTemplateName();<br class=""> auto QualifierOrErr = Import_New(QTN->getQualifier());<br class=""><br class="">Modified: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp (original)<br class="">+++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp Wed May 8 20:31:27 2019<br class="">@@ -180,6 +180,12 @@ static bool IsStructurallyEquivalent(Str<br class=""> return I1 == E1 && I2 == E2;<br class=""> }<br class=""><br class="">+ case TemplateName::AssumedTemplate: {<br class="">+ AssumedTemplateStorage *TN1 = N1.getAsAssumedTemplateName(),<br class="">+ *TN2 = N1.getAsAssumedTemplateName();<br class="">+ return TN1->getDeclName() == TN2->getDeclName();<br class="">+ }<br class="">+<br class=""> case TemplateName::QualifiedTemplate: {<br class=""> QualifiedTemplateName *QN1 = N1.getAsQualifiedTemplateName(),<br class=""> *QN2 = N2.getAsQualifiedTemplateName();<br class=""><br class="">Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)<br class="">+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed May 8 20:31:27 2019<br class="">@@ -1891,6 +1891,7 @@ void CXXNameMangler::mangleType(Template<br class=""> break;<br class=""><br class=""> case TemplateName::OverloadedTemplate:<br class="">+ case TemplateName::AssumedTemplate:<br class=""> llvm_unreachable("can't mangle an overloaded template name as a <type>");<br class=""><br class=""> case TemplateName::DependentTemplate: {<br class="">@@ -2030,6 +2031,7 @@ bool CXXNameMangler::mangleUnresolvedTyp<br class=""> }<br class=""><br class=""> case TemplateName::OverloadedTemplate:<br class="">+ case TemplateName::AssumedTemplate:<br class=""> case TemplateName::DependentTemplate:<br class=""> llvm_unreachable("invalid base for a template specialization type");<br class=""><br class=""><br class="">Modified: cfe/trunk/lib/AST/ODRHash.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/AST/ODRHash.cpp (original)<br class="">+++ cfe/trunk/lib/AST/ODRHash.cpp Wed May 8 20:31:27 2019<br class="">@@ -140,6 +140,7 @@ void ODRHash::AddTemplateName(TemplateNa<br class=""> break;<br class=""> // TODO: Support these cases.<br class=""> case TemplateName::OverloadedTemplate:<br class="">+ case TemplateName::AssumedTemplate:<br class=""> case TemplateName::QualifiedTemplate:<br class=""> case TemplateName::DependentTemplate:<br class=""> case TemplateName::SubstTemplateTemplateParm:<br class=""><br class="">Modified: cfe/trunk/lib/AST/TemplateName.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateName.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateName.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/AST/TemplateName.cpp (original)<br class="">+++ cfe/trunk/lib/AST/TemplateName.cpp Wed May 8 20:31:27 2019<br class="">@@ -66,6 +66,8 @@ TemplateName::TemplateName(void *Ptr) {<br class=""> TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}<br class=""> TemplateName::TemplateName(OverloadedTemplateStorage *Storage)<br class=""> : Storage(Storage) {}<br class="">+TemplateName::TemplateName(AssumedTemplateStorage *Storage)<br class="">+ : Storage(Storage) {}<br class=""> TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)<br class=""> : Storage(Storage) {}<br class=""> TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)<br class="">@@ -87,6 +89,8 @@ TemplateName::NameKind TemplateName::get<br class=""> = Storage.get<UncommonTemplateNameStorage*>();<br class=""> if (uncommon->getAsOverloadedStorage())<br class=""> return OverloadedTemplate;<br class="">+ if (uncommon->getAsAssumedTemplateName())<br class="">+ return AssumedTemplate;<br class=""> if (uncommon->getAsSubstTemplateTemplateParm())<br class=""> return SubstTemplateTemplateParm;<br class=""> return SubstTemplateTemplateParmPack;<br class="">@@ -113,6 +117,14 @@ OverloadedTemplateStorage *TemplateName:<br class=""> return nullptr;<br class=""> }<br class=""><br class="">+AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {<br class="">+ if (UncommonTemplateNameStorage *Uncommon =<br class="">+ Storage.dyn_cast<UncommonTemplateNameStorage *>())<br class="">+ return Uncommon->getAsAssumedTemplateName();<br class="">+<br class="">+ return nullptr;<br class="">+}<br class="">+<br class=""> SubstTemplateTemplateParmStorage *<br class=""> TemplateName::getAsSubstTemplateTemplateParm() const {<br class=""> if (UncommonTemplateNameStorage *uncommon =<br class="">@@ -230,7 +242,9 @@ TemplateName::print(raw_ostream &OS, con<br class=""> } else if (SubstTemplateTemplateParmPackStorage *SubstPack<br class=""> = getAsSubstTemplateTemplateParmPack())<br class=""> OS << *SubstPack->getParameterPack();<br class="">- else {<br class="">+ else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {<br class="">+ Assumed->getDeclName().print(OS, Policy);<br class="">+ } else {<br class=""> OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();<br class=""> (*OTS->begin())->printName(OS);<br class=""> }<br class=""><br class="">Modified: cfe/trunk/lib/Parse/ParseDecl.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed May 8 20:31:27 2019<br class="">@@ -2916,6 +2916,7 @@ Parser::DiagnoseMissingSemiAfterTagDefin<br class=""> case Sema::NC_Expression:<br class=""> case Sema::NC_VarTemplate:<br class=""> case Sema::NC_FunctionTemplate:<br class="">+ case Sema::NC_UndeclaredTemplate:<br class=""> // Might be a redeclaration of a prior entity.<br class=""> break;<br class=""> }<br class="">@@ -3386,7 +3387,8 @@ void Parser::ParseDeclarationSpecifiers(<br class=""> // type-name<br class=""> case tok::annot_template_id: {<br class=""> TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);<br class="">- if (TemplateId->Kind != TNK_Type_template) {<br class="">+ if (TemplateId->Kind != TNK_Type_template &&<br class="">+ TemplateId->Kind != TNK_Undeclared_template) {<br class=""> // This template-id does not refer to a type name, so we're<br class=""> // done with the type-specifiers.<br class=""> goto DoneWithDeclSpec;<br class=""><br class="">Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed May 8 20:31:27 2019<br class="">@@ -597,10 +597,11 @@ bool Parser::ParseUsingDeclarator(Declar<br class=""><br class=""> // Parse nested-name-specifier.<br class=""> IdentifierInfo *LastII = nullptr;<br class="">- ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false,<br class="">- /*MayBePseudoDtor=*/nullptr,<br class="">- /*IsTypename=*/false,<br class="">- /*LastII=*/&LastII);<br class="">+ if (ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false,<br class="">+ /*MayBePseudoDtor=*/nullptr,<br class="">+ /*IsTypename=*/false,<br class="">+ /*LastII=*/&LastII))<br class="">+ return true;<br class=""> if (D.SS.isInvalid())<br class=""> return true;<br class=""><br class="">@@ -1111,7 +1112,8 @@ TypeResult Parser::ParseBaseTypeSpecifie<br class=""><br class=""> // Parse optional nested-name-specifier<br class=""> CXXScopeSpec SS;<br class="">- ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);<br class="">+ if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false))<br class="">+ return true;<br class=""><br class=""> BaseLoc = Tok.getLocation();<br class=""><br class="">@@ -1135,7 +1137,8 @@ TypeResult Parser::ParseBaseTypeSpecifie<br class=""> if (<a href="http://Tok.is" class="">Tok.is</a>(tok::annot_template_id)) {<br class=""> TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);<br class=""> if (TemplateId->Kind == TNK_Type_template ||<br class="">- TemplateId->Kind == TNK_Dependent_template_name) {<br class="">+ TemplateId->Kind == TNK_Dependent_template_name ||<br class="">+ TemplateId->Kind == TNK_Undeclared_template) {<br class=""> AnnotateTemplateIdTokenAsType(/*IsClassName*/true);<br class=""><br class=""> assert(<a href="http://Tok.is" class="">Tok.is</a>(tok::annot_typename) && "template-id -> type failed");<br class="">@@ -1554,6 +1557,36 @@ void Parser::ParseClassSpecifier(tok::To<br class=""><br class=""> TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;<br class=""><br class="">+ auto RecoverFromUndeclaredTemplateName = [&](IdentifierInfo *Name,<br class="">+ SourceLocation NameLoc,<br class="">+ SourceRange TemplateArgRange,<br class="">+ bool KnownUndeclared) {<br class="">+ Diag(NameLoc, diag::err_explicit_spec_non_template)<br class="">+ << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)<br class="">+ << TagTokKind << Name << TemplateArgRange << KnownUndeclared;<br class="">+<br class="">+ // Strip off the last template parameter list if it was empty, since<br class="">+ // we've removed its template argument list.<br class="">+ if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {<br class="">+ if (TemplateParams->size() > 1) {<br class="">+ TemplateParams->pop_back();<br class="">+ } else {<br class="">+ TemplateParams = nullptr;<br class="">+ const_cast<ParsedTemplateInfo &>(TemplateInfo).Kind =<br class="">+ ParsedTemplateInfo::NonTemplate;<br class="">+ }<br class="">+ } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {<br class="">+ // Pretend this is just a forward declaration.<br class="">+ TemplateParams = nullptr;<br class="">+ const_cast<ParsedTemplateInfo &>(TemplateInfo).Kind =<br class="">+ ParsedTemplateInfo::NonTemplate;<br class="">+ const_cast<ParsedTemplateInfo &>(TemplateInfo).TemplateLoc =<br class="">+ SourceLocation();<br class="">+ const_cast<ParsedTemplateInfo &>(TemplateInfo).ExternLoc =<br class="">+ SourceLocation();<br class="">+ }<br class="">+ };<br class="">+<br class=""> // Parse the (optional) class name or simple-template-id.<br class=""> IdentifierInfo *Name = nullptr;<br class=""> SourceLocation NameLoc;<br class="">@@ -1574,38 +1607,26 @@ void Parser::ParseClassSpecifier(tok::To<br class=""> // try to give any location information for the list.<br class=""> LAngleLoc = RAngleLoc = SourceLocation();<br class=""> }<br class="">-<br class="">- Diag(NameLoc, diag::err_explicit_spec_non_template)<br class="">- << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)<br class="">- << TagTokKind << Name << SourceRange(LAngleLoc, RAngleLoc);<br class="">-<br class="">- // Strip off the last template parameter list if it was empty, since<br class="">- // we've removed its template argument list.<br class="">- if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {<br class="">- if (TemplateParams->size() > 1) {<br class="">- TemplateParams->pop_back();<br class="">- } else {<br class="">- TemplateParams = nullptr;<br class="">- const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind<br class="">- = ParsedTemplateInfo::NonTemplate;<br class="">- }<br class="">- } else if (TemplateInfo.Kind<br class="">- == ParsedTemplateInfo::ExplicitInstantiation) {<br class="">- // Pretend this is just a forward declaration.<br class="">- TemplateParams = nullptr;<br class="">- const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind<br class="">- = ParsedTemplateInfo::NonTemplate;<br class="">- const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc<br class="">- = SourceLocation();<br class="">- const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc<br class="">- = SourceLocation();<br class="">- }<br class="">+ RecoverFromUndeclaredTemplateName(<br class="">+ Name, NameLoc, SourceRange(LAngleLoc, RAngleLoc), false);<br class=""> }<br class=""> } else if (<a href="http://Tok.is" class="">Tok.is</a>(tok::annot_template_id)) {<br class=""> TemplateId = takeTemplateIdAnnotation(Tok);<br class=""> NameLoc = ConsumeAnnotationToken();<br class=""><br class="">- if (TemplateId->Kind != TNK_Type_template &&<br class="">+ if (TemplateId->Kind == TNK_Undeclared_template) {<br class="">+ // Try to resolve the template name to a type template.<br class="">+ Actions.ActOnUndeclaredTypeTemplateName(getCurScope(), TemplateId->Template,<br class="">+ TemplateId->Kind, NameLoc, Name);<br class="">+ if (TemplateId->Kind == TNK_Undeclared_template) {<br class="">+ RecoverFromUndeclaredTemplateName(<br class="">+ Name, NameLoc,<br class="">+ SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc), true);<br class="">+ TemplateId = nullptr;<br class="">+ }<br class="">+ }<br class="">+<br class="">+ if (TemplateId && TemplateId->Kind != TNK_Type_template &&<br class=""> TemplateId->Kind != TNK_Dependent_template_name) {<br class=""> // The template-name in the simple-template-id refers to<br class=""> // something other than a class template. Give an appropriate<br class="">@@ -1616,7 +1637,7 @@ void Parser::ParseClassSpecifier(tok::To<br class=""><br class=""> // FIXME: Name may be null here.<br class=""> Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)<br class="">- << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;<br class="">+ << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;<br class=""><br class=""> DS.SetTypeSpecError();<br class=""> SkipUntil(tok::semi, StopBeforeMatch);<br class="">@@ -3451,7 +3472,8 @@ void Parser::ParseConstructorInitializer<br class=""> MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {<br class=""> // parse '::'[opt] nested-name-specifier[opt]<br class=""> CXXScopeSpec SS;<br class="">- ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);<br class="">+ if (ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false))<br class="">+ return true;<br class=""><br class=""> // : identifier<br class=""> IdentifierInfo *II = nullptr;<br class="">@@ -3477,11 +3499,14 @@ MemInitResult Parser::ParseMemInitialize<br class=""> ? takeTemplateIdAnnotation(Tok)<br class=""> : nullptr;<br class=""> if (TemplateId && (TemplateId->Kind == TNK_Type_template ||<br class="">- TemplateId->Kind == TNK_Dependent_template_name)) {<br class="">+ TemplateId->Kind == TNK_Dependent_template_name ||<br class="">+ TemplateId->Kind == TNK_Undeclared_template)) {<br class=""> AnnotateTemplateIdTokenAsType(/*IsClassName*/true);<br class=""> assert(<a href="http://Tok.is" class="">Tok.is</a>(tok::annot_typename) && "template-id -> type failed");<br class=""> TemplateTypeTy = getTypeAnnotation(Tok);<br class=""> ConsumeAnnotationToken();<br class="">+ if (!TemplateTypeTy)<br class="">+ return true;<br class=""> } else {<br class=""> Diag(Tok, diag::err_expected_member_or_base_name);<br class=""> return true;<br class=""><br class="">Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed May 8 20:31:27 2019<br class="">@@ -487,6 +487,14 @@ bool Parser::ParseOptionalCXXScopeSpecif<br class=""> EnteringContext,<br class=""> Template,<br class=""> MemberOfUnknownSpecialization)) {<br class="">+ // If lookup didn't find anything, we treat the name as a template-name<br class="">+ // anyway. C++20 requires this, and in prior language modes it improves<br class="">+ // error recovery. But before we commit to this, check that we actually<br class="">+ // have something that looks like a template-argument-list next.<br class="">+ if (!IsTypename && TNK == TNK_Undeclared_template &&<br class="">+ isTemplateArgumentList(1) == TPResult::False)<br class="">+ break;<br class="">+<br class=""> // We have found a template name, so annotate this token<br class=""> // with a template-id annotation. We do not permit the<br class=""> // template-id to be translated into a type annotation,<br class="">@@ -501,7 +509,7 @@ bool Parser::ParseOptionalCXXScopeSpecif<br class=""> }<br class=""><br class=""> if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) &&<br class="">- (IsTypename || IsTemplateArgumentList(1))) {<br class="">+ (IsTypename || isTemplateArgumentList(1) == TPResult::True)) {<br class=""> // We have something like t::getAs<T>, where getAs is a<br class=""> // member of an unknown specialization. However, this will only<br class=""> // parse correctly as a template, so suggest the keyword 'template'<br class="">@@ -2138,9 +2146,15 @@ bool Parser::ParseUnqualifiedIdTemplateI<br class=""> TemplateKWLoc.isValid(), Id,<br class=""> ObjectType, EnteringContext, Template,<br class=""> MemberOfUnknownSpecialization);<br class="">+ // If lookup found nothing but we're assuming that this is a template<br class="">+ // name, double-check that makes sense syntactically before committing<br class="">+ // to it.<br class="">+ if (TNK == TNK_Undeclared_template &&<br class="">+ isTemplateArgumentList(0) == TPResult::False)<br class="">+ return false;<br class=""><br class=""> if (TNK == TNK_Non_template && MemberOfUnknownSpecialization &&<br class="">- ObjectType && IsTemplateArgumentList()) {<br class="">+ ObjectType && isTemplateArgumentList(0) == TPResult::True) {<br class=""> // We have something like t->getAs<T>(), where getAs is a<br class=""> // member of an unknown specialization. However, this will only<br class=""> // parse correctly as a template, so suggest the keyword 'template'<br class="">@@ -2244,11 +2258,9 @@ bool Parser::ParseUnqualifiedIdTemplateI<br class=""> ASTTemplateArgsPtr TemplateArgsPtr(TemplateArgs);<br class=""><br class=""> // Constructor and destructor names.<br class="">- TypeResult Type<br class="">- = Actions.ActOnTemplateIdType(SS, TemplateKWLoc,<br class="">- Template, Name, NameLoc,<br class="">- LAngleLoc, TemplateArgsPtr, RAngleLoc,<br class="">- /*IsCtorOrDtorName=*/true);<br class="">+ TypeResult Type = Actions.ActOnTemplateIdType(<br class="">+ getCurScope(), SS, TemplateKWLoc, Template, Name, NameLoc, LAngleLoc,<br class="">+ TemplateArgsPtr, RAngleLoc, /*IsCtorOrDtorName=*/true);<br class=""> if (Type.isInvalid())<br class=""> return true;<br class=""><br class=""><br class="">Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Wed May 8 20:31:27 2019<br class="">@@ -1031,6 +1031,8 @@ bool Parser::AnnotateTemplateIdToken(Tem<br class=""> // If we failed to parse the template ID but skipped ahead to a >, we're not<br class=""> // going to be able to form a token annotation. Eat the '>' if present.<br class=""> TryConsumeToken(tok::greater);<br class="">+ // FIXME: Annotate the token stream so we don't produce the same errors<br class="">+ // again if we're doing this annotation as part of a tentative parse.<br class=""> return true;<br class=""> }<br class=""><br class="">@@ -1039,13 +1041,15 @@ bool Parser::AnnotateTemplateIdToken(Tem<br class=""> // Build the annotation token.<br class=""> if (TNK == TNK_Type_template && AllowTypeAnnotation) {<br class=""> TypeResult Type = Actions.ActOnTemplateIdType(<br class="">- SS, TemplateKWLoc, Template, TemplateName.Identifier,<br class="">+ getCurScope(), SS, TemplateKWLoc, Template, TemplateName.Identifier,<br class=""> TemplateNameLoc, LAngleLoc, TemplateArgsPtr, RAngleLoc);<br class=""> if (Type.isInvalid()) {<br class=""> // If we failed to parse the template ID but skipped ahead to a >, we're<br class=""> // not going to be able to form a token annotation. Eat the '>' if<br class=""> // present.<br class=""> TryConsumeToken(tok::greater);<br class="">+ // FIXME: Annotate the token stream so we don't produce the same errors<br class="">+ // again if we're doing this annotation as part of a tentative parse.<br class=""> return true;<br class=""> }<br class=""><br class="">@@ -1108,14 +1112,16 @@ void Parser::AnnotateTemplateIdTokenAsTy<br class=""><br class=""> TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);<br class=""> assert((TemplateId->Kind == TNK_Type_template ||<br class="">- TemplateId->Kind == TNK_Dependent_template_name) &&<br class="">+ TemplateId->Kind == TNK_Dependent_template_name ||<br class="">+ TemplateId->Kind == TNK_Undeclared_template) &&<br class=""> "Only works for type and dependent templates");<br class=""><br class=""> ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),<br class=""> TemplateId->NumArgs);<br class=""><br class=""> TypeResult Type<br class="">- = Actions.ActOnTemplateIdType(TemplateId->SS,<br class="">+ = Actions.ActOnTemplateIdType(getCurScope(),<br class="">+ TemplateId->SS,<br class=""> TemplateId->TemplateKWLoc,<br class=""> TemplateId->Template,<br class=""> TemplateId->Name,<br class="">@@ -1272,36 +1278,6 @@ ParsedTemplateArgument Parser::ParseTemp<br class=""> ExprArg.get(), Loc);<br class=""> }<br class=""><br class="">-/// Determine whether the current tokens can only be parsed as a<br class="">-/// template argument list (starting with the '<') and never as a '<'<br class="">-/// expression.<br class="">-bool Parser::IsTemplateArgumentList(unsigned Skip) {<br class="">- struct AlwaysRevertAction : TentativeParsingAction {<br class="">- AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { }<br class="">- ~AlwaysRevertAction() { Revert(); }<br class="">- } Tentative(*this);<br class="">-<br class="">- while (Skip) {<br class="">- ConsumeAnyToken();<br class="">- --Skip;<br class="">- }<br class="">-<br class="">- // '<'<br class="">- if (!TryConsumeToken(tok::less))<br class="">- return false;<br class="">-<br class="">- // An empty template argument list.<br class="">- if (<a href="http://Tok.is" class="">Tok.is</a>(tok::greater))<br class="">- return true;<br class="">-<br class="">- // See whether we have declaration specifiers, which indicate a type.<br class="">- while (isCXXDeclarationSpecifier() == TPResult::True)<br class="">- ConsumeAnyToken();<br class="">-<br class="">- // If we have a '>' or a ',' then this is a template argument list.<br class="">- return Tok.isOneOf(tok::greater, tok::comma);<br class="">-}<br class="">-<br class=""> /// ParseTemplateArgumentList - Parse a C++ template-argument-list<br class=""> /// (C++ [temp.names]). Returns true if there was an error.<br class=""> ///<br class=""><br class="">Modified: cfe/trunk/lib/Parse/ParseTentative.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/ParseTentative.cpp Wed May 8 20:31:27 2019<br class="">@@ -1178,12 +1178,17 @@ public:<br class=""> /// be either a decl-specifier or a function-style cast, and TPResult::Error<br class=""> /// if a parsing error was found and reported.<br class=""> ///<br class="">-/// If HasMissingTypename is provided, a name with a dependent scope specifier<br class="">-/// will be treated as ambiguous if the 'typename' keyword is missing. If this<br class="">-/// happens, *HasMissingTypename will be set to 'true'. This will also be used<br class="">-/// as an indicator that undeclared identifiers (which will trigger a later<br class="">-/// parse error) should be treated as types. Returns TPResult::Ambiguous in<br class="">-/// such cases.<br class="">+/// If InvalidAsDeclSpec is not null, some cases that would be ill-formed as<br class="">+/// declaration specifiers but possibly valid as some other kind of construct<br class="">+/// return TPResult::Ambiguous instead of TPResult::False. When this happens,<br class="">+/// the intent is to keep trying to disambiguate, on the basis that we might<br class="">+/// find a better reason to treat this construct as a declaration later on.<br class="">+/// When this happens and the name could possibly be valid in some other<br class="">+/// syntactic context, *InvalidAsDeclSpec is set to 'true'. The current cases<br class="">+/// that trigger this are:<br class="">+///<br class="">+/// * When parsing X::Y (with no 'typename') where X is dependent<br class="">+/// * When parsing X<Y> where X is undeclared<br class=""> ///<br class=""> /// decl-specifier:<br class=""> /// storage-class-specifier<br class="">@@ -1281,7 +1286,7 @@ public:<br class=""> ///<br class=""> Parser::TPResult<br class=""> Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,<br class="">- bool *HasMissingTypename) {<br class="">+ bool *InvalidAsDeclSpec) {<br class=""> switch (Tok.getKind()) {<br class=""> case tok::identifier: {<br class=""> // Check for need to substitute AltiVec __vector keyword<br class="">@@ -1321,7 +1326,7 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""> // argument is an error, and was probably intended to be a type.<br class=""> return GreaterThanIsOperator ? TPResult::True : TPResult::False;<br class=""> case ANK_Unresolved:<br class="">- return HasMissingTypename ? TPResult::Ambiguous : TPResult::False;<br class="">+ return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;<br class=""> case ANK_Success:<br class=""> break;<br class=""> }<br class="">@@ -1342,7 +1347,7 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""> }<br class=""><br class=""> // We annotated this token as something. Recurse to handle whatever we got.<br class="">- return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);<br class="">+ return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);<br class=""> }<br class=""><br class=""> case tok::kw_typename: // typename T::type<br class="">@@ -1350,7 +1355,7 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""> // recurse to handle whatever we get.<br class=""> if (TryAnnotateTypeOrScopeToken())<br class=""> return TPResult::Error;<br class="">- return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);<br class="">+ return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);<br class=""><br class=""> case tok::coloncolon: { // ::foo::bar<br class=""> const Token &Next = NextToken();<br class="">@@ -1365,7 +1370,7 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""> // recurse to handle whatever we get.<br class=""> if (TryAnnotateTypeOrScopeToken())<br class=""> return TPResult::Error;<br class="">- return isCXXDeclarationSpecifier(BracedCastResult, HasMissingTypename);<br class="">+ return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);<br class=""><br class=""> // decl-specifier:<br class=""> // storage-class-specifier<br class="">@@ -1471,6 +1476,16 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""><br class=""> case tok::annot_template_id: {<br class=""> TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);<br class="">+ // If lookup for the template-name found nothing, don't assume we have a<br class="">+ // definitive disambiguation result yet.<br class="">+ if (TemplateId->Kind == TNK_Undeclared_template && InvalidAsDeclSpec) {<br class="">+ // 'template-id(' can be a valid expression but not a valid decl spec if<br class="">+ // the template-name is not declared, but we don't consider this to be a<br class="">+ // definitive disambiguation. In any other context, it's an error either<br class="">+ // way.<br class="">+ *InvalidAsDeclSpec = NextToken().is(tok::l_paren);<br class="">+ return TPResult::Ambiguous;<br class="">+ }<br class=""> if (TemplateId->Kind != TNK_Type_template)<br class=""> return TPResult::False;<br class=""> CXXScopeSpec SS;<br class="">@@ -1499,19 +1514,19 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""> TPResult TPR = TPResult::False;<br class=""> if (!isIdentifier)<br class=""> TPR = isCXXDeclarationSpecifier(BracedCastResult,<br class="">- HasMissingTypename);<br class="">+ InvalidAsDeclSpec);<br class=""><br class=""> if (isIdentifier ||<br class=""> TPR == TPResult::True || TPR == TPResult::Error)<br class=""> return TPResult::Error;<br class=""><br class="">- if (HasMissingTypename) {<br class="">+ if (InvalidAsDeclSpec) {<br class=""> // We can't tell whether this is a missing 'typename' or a valid<br class=""> // expression.<br class="">- *HasMissingTypename = true;<br class="">+ *InvalidAsDeclSpec = true;<br class=""> return TPResult::Ambiguous;<br class=""> } else {<br class="">- // In MS mode, if HasMissingTypename is not provided, and the tokens<br class="">+ // In MS mode, if InvalidAsDeclSpec is not provided, and the tokens<br class=""> // are or the form *) or &) *> or &> &&>, this can't be an expression.<br class=""> // The typename must be missing.<br class=""> if (getLangOpts().MSVCCompat) {<br class="">@@ -1547,8 +1562,7 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""> ? TPResult::True<br class=""> : TPResult::False;<br class=""> case ANK_Unresolved:<br class="">- return HasMissingTypename ? TPResult::Ambiguous<br class="">- : TPResult::False;<br class="">+ return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;<br class=""> case ANK_Success:<br class=""> break;<br class=""> }<br class="">@@ -1556,8 +1570,7 @@ Parser::isCXXDeclarationSpecifier(Parser<br class=""> // Annotated it, check again.<br class=""> assert(Tok.isNot(tok::annot_cxxscope) ||<br class=""> NextToken().isNot(tok::identifier));<br class="">- return isCXXDeclarationSpecifier(BracedCastResult,<br class="">- HasMissingTypename);<br class="">+ return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);<br class=""> }<br class=""> }<br class=""> return TPResult::False;<br class="">@@ -2029,3 +2042,56 @@ Parser::TPResult Parser::TryParseBracket<br class=""><br class=""> return TPResult::Ambiguous;<br class=""> }<br class="">+<br class="">+/// Determine whether we might be looking at the '<' template-argument-list '>'<br class="">+/// of a template-id or simple-template-id, rather than a less-than comparison.<br class="">+/// This will often fail and produce an ambiguity, but should never be wrong<br class="">+/// if it returns True or False.<br class="">+Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip) {<br class="">+ if (!TokensToSkip) {<br class="">+ if (Tok.isNot(tok::less))<br class="">+ return TPResult::False;<br class="">+ if (NextToken().is(tok::greater))<br class="">+ return TPResult::True;<br class="">+ }<br class="">+<br class="">+ RevertingTentativeParsingAction PA(*this);<br class="">+<br class="">+ while (TokensToSkip) {<br class="">+ ConsumeAnyToken();<br class="">+ --TokensToSkip;<br class="">+ }<br class="">+<br class="">+ if (!TryConsumeToken(tok::less))<br class="">+ return TPResult::False;<br class="">+<br class="">+ bool InvalidAsTemplateArgumentList = false;<br class="">+ while (true) {<br class="">+ // We can't do much to tell an expression apart from a template-argument,<br class="">+ // but one good distinguishing factor is that a "decl-specifier" not<br class="">+ // followed by '(' or '{' can't appear in an expression.<br class="">+ if (isCXXDeclarationSpecifier(<br class="">+ TPResult::False, &InvalidAsTemplateArgumentList) == TPResult::True)<br class="">+ return TPResult::True;<br class="">+<br class="">+ // That didn't help, try the next template-argument.<br class="">+ SkipUntil({tok::comma, tok::greater, tok::greatergreater,<br class="">+ tok::greatergreatergreater},<br class="">+ StopAtSemi | StopBeforeMatch);<br class="">+ switch (Tok.getKind()) {<br class="">+ case tok::comma:<br class="">+ ConsumeToken();<br class="">+ break;<br class="">+<br class="">+ case tok::greater:<br class="">+ case tok::greatergreater:<br class="">+ case tok::greatergreatergreater:<br class="">+ if (InvalidAsTemplateArgumentList)<br class="">+ return TPResult::False;<br class="">+ return TPResult::Ambiguous;<br class="">+<br class="">+ default:<br class="">+ return TPResult::False;<br class="">+ }<br class="">+ }<br class="">+}<br class=""><br class="">Modified: cfe/trunk/lib/Parse/Parser.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Parse/Parser.cpp (original)<br class="">+++ cfe/trunk/lib/Parse/Parser.cpp Wed May 8 20:31:27 2019<br class="">@@ -315,6 +315,14 @@ bool Parser::SkipUntil(ArrayRef<tok::Tok<br class=""> else<br class=""> SkipUntil(tok::r_brace);<br class=""> break;<br class="">+ case tok::question:<br class="">+ // Recursively skip ? ... : pairs; these function as brackets. But<br class="">+ // still stop at a semicolon if requested.<br class="">+ ConsumeToken();<br class="">+ SkipUntil(tok::colon,<br class="">+ SkipUntilFlags(unsigned(Flags) &<br class="">+ unsigned(StopAtCodeCompletion | StopAtSemi)));<br class="">+ break;<br class=""><br class=""> // Okay, we found a ']' or '}' or ')', which we think should be balanced.<br class=""> // Since the user wasn't looking for this token (if they were, it would<br class="">@@ -1600,6 +1608,20 @@ Parser::TryAnnotateName(bool IsAddressOf<br class=""> Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next,<br class=""> IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr);<br class=""><br class="">+ // If name lookup found nothing and we guessed that this was a template name,<br class="">+ // double-check before committing to that interpretation. C++20 requires that<br class="">+ // we interpret this as a template-id if it can be, but if it can't be, then<br class="">+ // this is an error recovery case.<br class="">+ if (Classification.getKind() == Sema::NC_UndeclaredTemplate &&<br class="">+ isTemplateArgumentList(1) == TPResult::False) {<br class="">+ // It's not a template-id; re-classify without the '<' as a hint.<br class="">+ Token FakeNext = Next;<br class="">+ FakeNext.setKind(tok::unknown);<br class="">+ Classification =<br class="">+ Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, FakeNext,<br class="">+ IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr);<br class="">+ }<br class="">+<br class=""> switch (Classification.getKind()) {<br class=""> case Sema::NC_Error:<br class=""> return ANK_Error;<br class="">@@ -1668,7 +1690,8 @@ Parser::TryAnnotateName(bool IsAddressOf<br class=""> }<br class=""> LLVM_FALLTHROUGH;<br class=""> case Sema::NC_VarTemplate:<br class="">- case Sema::NC_FunctionTemplate: {<br class="">+ case Sema::NC_FunctionTemplate:<br class="">+ case Sema::NC_UndeclaredTemplate: {<br class=""> // We have a type, variable or function template followed by '<'.<br class=""> ConsumeToken();<br class=""> UnqualifiedId Id;<br class="">@@ -1791,7 +1814,8 @@ bool Parser::TryAnnotateTypeOrScopeToken<br class=""> } else if (<a href="http://Tok.is" class="">Tok.is</a>(tok::annot_template_id)) {<br class=""> TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);<br class=""> if (TemplateId->Kind != TNK_Type_template &&<br class="">- TemplateId->Kind != TNK_Dependent_template_name) {<br class="">+ TemplateId->Kind != TNK_Dependent_template_name &&<br class="">+ TemplateId->Kind != TNK_Undeclared_template) {<br class=""> Diag(Tok, diag::err_typename_refers_to_non_type_template)<br class=""> << Tok.getAnnotationRange();<br class=""> return true;<br class="">@@ -1890,6 +1914,8 @@ bool Parser::TryAnnotateTypeOrScopeToken<br class=""> }<br class=""><br class=""> // If this is a template-id, annotate with a template-id or type token.<br class="">+ // FIXME: This appears to be dead code. We already have formed template-id<br class="">+ // tokens when parsing the scope specifier; this can never form a new one.<br class=""> if (NextToken().is(tok::less)) {<br class=""> TemplateTy Template;<br class=""> UnqualifiedId TemplateName;<br class="">@@ -1900,14 +1926,19 @@ bool Parser::TryAnnotateTypeOrScopeToken<br class=""> /*hasTemplateKeyword=*/false, TemplateName,<br class=""> /*ObjectType=*/nullptr, /*EnteringContext*/false, Template,<br class=""> MemberOfUnknownSpecialization)) {<br class="">- // Consume the identifier.<br class="">- ConsumeToken();<br class="">- if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),<br class="">- TemplateName)) {<br class="">- // If an unrecoverable error occurred, we need to return true here,<br class="">- // because the token stream is in a damaged state. We may not return<br class="">- // a valid identifier.<br class="">- return true;<br class="">+ // Only annotate an undeclared template name as a template-id if the<br class="">+ // following tokens have the form of a template argument list.<br class="">+ if (TNK != TNK_Undeclared_template ||<br class="">+ isTemplateArgumentList(1) != TPResult::False) {<br class="">+ // Consume the identifier.<br class="">+ ConsumeToken();<br class="">+ if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),<br class="">+ TemplateName)) {<br class="">+ // If an unrecoverable error occurred, we need to return true here,<br class="">+ // because the token stream is in a damaged state. We may not<br class="">+ // return a valid identifier.<br class="">+ return true;<br class="">+ }<br class=""> }<br class=""> }<br class=""> }<br class=""><br class="">Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)<br class="">+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Wed May 8 20:31:27 2019<br class="">@@ -888,7 +888,7 @@ bool Sema::IsInvalidUnlessNestedName(Sco<br class=""> bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,<br class=""> CXXScopeSpec &SS,<br class=""> SourceLocation TemplateKWLoc,<br class="">- TemplateTy Template,<br class="">+ TemplateTy OpaqueTemplate,<br class=""> SourceLocation TemplateNameLoc,<br class=""> SourceLocation LAngleLoc,<br class=""> ASTTemplateArgsPtr TemplateArgsIn,<br class="">@@ -898,11 +898,13 @@ bool Sema::ActOnCXXNestedNameSpecifier(S<br class=""> if (SS.isInvalid())<br class=""> return true;<br class=""><br class="">+ TemplateName Template = OpaqueTemplate.get();<br class="">+<br class=""> // Translate the parser's template argument list in our AST format.<br class=""> TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);<br class=""> translateTemplateArguments(TemplateArgsIn, TemplateArgs);<br class=""><br class="">- DependentTemplateName *DTN = Template.get().getAsDependentTemplateName();<br class="">+ DependentTemplateName *DTN = Template.getAsDependentTemplateName();<br class=""> if (DTN && DTN->isIdentifier()) {<br class=""> // Handle a dependent template specialization for which we cannot resolve<br class=""> // the template name.<br class="">@@ -930,23 +932,28 @@ bool Sema::ActOnCXXNestedNameSpecifier(S<br class=""> return false;<br class=""> }<br class=""><br class="">- TemplateDecl *TD = Template.get().getAsTemplateDecl();<br class="">- if (Template.get().getAsOverloadedTemplate() || DTN ||<br class="">+ // If we assumed an undeclared identifier was a template name, try to<br class="">+ // typo-correct it now.<br class="">+ if (Template.getAsAssumedTemplateName() &&<br class="">+ resolveAssumedTemplateNameAsType(S, Template, TemplateNameLoc))<br class="">+ return true;<br class="">+<br class="">+ TemplateDecl *TD = Template.getAsTemplateDecl();<br class="">+ if (Template.getAsOverloadedTemplate() || DTN ||<br class=""> isa<FunctionTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)) {<br class=""> SourceRange R(TemplateNameLoc, RAngleLoc);<br class=""> if (SS.getRange().isValid())<br class=""> R.setBegin(SS.getRange().getBegin());<br class=""><br class=""> Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)<br class="">- << (TD && isa<VarTemplateDecl>(TD)) << Template.get() << R;<br class="">- NoteAllFoundTemplates(Template.get());<br class="">+ << (TD && isa<VarTemplateDecl>(TD)) << Template << R;<br class="">+ NoteAllFoundTemplates(Template);<br class=""> return true;<br class=""> }<br class=""><br class=""> // We were able to resolve the template name to an actual template.<br class=""> // Build an appropriate nested-name-specifier.<br class="">- QualType T =<br class="">- CheckTemplateIdType(Template.get(), TemplateNameLoc, TemplateArgs);<br class="">+ QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);<br class=""> if (T.isNull())<br class=""> return true;<br class=""><br class="">@@ -954,7 +961,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(S<br class=""> // nested name specifiers.<br class=""> if (!T->isDependentType() && !T->getAs<TagType>()) {<br class=""> Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T;<br class="">- NoteAllFoundTemplates(Template.get());<br class="">+ NoteAllFoundTemplates(Template);<br class=""> return true;<br class=""> }<br class=""><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=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br class="">+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed May 8 20:31:27 2019<br class="">@@ -917,6 +917,16 @@ Corrected:<br class=""> }<br class=""> }<br class=""><br class="">+ if (getLangOpts().CPlusPlus2a && !SS.isSet() && <a href="http://NextToken.is" class="">NextToken.is</a>(tok::less)) {<br class="">+ // In C++20 onwards, this could be an ADL-only call to a function<br class="">+ // template, and we're required to assume that this is a template name.<br class="">+ //<br class="">+ // FIXME: Find a way to still do typo correction in this case.<br class="">+ TemplateName Template =<br class="">+ Context.getAssumedTemplateName(NameInfo.getName());<br class="">+ return NameClassification::UndeclaredTemplate(Template);<br class="">+ }<br class="">+<br class=""> // In C, we first see whether there is a tag type by the same name, in<br class=""> // which case it's likely that the user just forgot to write "enum",<br class=""> // "struct", or "union".<br class="">@@ -1045,52 +1055,62 @@ Corrected:<br class=""><br class=""> if (getLangOpts().CPlusPlus && <a href="http://NextToken.is" class="">NextToken.is</a>(tok::less) &&<br class=""> (IsFilteredTemplateName ||<br class="">- hasAnyAcceptableTemplateNames(Result, /*AllowFunctionTemplates=*/true,<br class="">- /*AllowDependent=*/false))) {<br class="">+ hasAnyAcceptableTemplateNames(<br class="">+ Result, /*AllowFunctionTemplates=*/true,<br class="">+ /*AllowDependent=*/false,<br class="">+ /*AllowNonTemplateFunctions*/ !SS.isSet() &&<br class="">+ getLangOpts().CPlusPlus2a))) {<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=""> // overloaded functions any member of which is a function template if<br class=""> // this is followed by a <, the < is always taken as the delimiter of a<br class=""> // template-argument-list and never as the less-than operator.<br class="">+ // C++2a [temp.names]p2:<br class="">+ // A name is also considered to refer to a template if it is an<br class="">+ // unqualified-id followed by a < and name lookup finds either one<br class="">+ // or more functions or finds nothing.<br class=""> if (!IsFilteredTemplateName)<br class=""> FilterAcceptableTemplateNames(Result);<br class=""><br class="">- if (!Result.empty()) {<br class="">- bool IsFunctionTemplate;<br class="">- bool IsVarTemplate;<br class="">- TemplateName Template;<br class="">- if (Result.end() - Result.begin() > 1) {<br class="">- IsFunctionTemplate = true;<br class="">- Template = Context.getOverloadedTemplateName(Result.begin(),<br class="">- Result.end());<br class="">- } else {<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 =<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="">- if (IsFunctionTemplate) {<br class="">- // Function templates always go through overload resolution, at which<br class="">- // point we'll perform the various checks (e.g., accessibility) we need<br class="">- // to based on which function we selected.<br class="">- Result.suppressDiagnostics();<br class="">+ bool IsFunctionTemplate;<br class="">+ bool IsVarTemplate;<br class="">+ TemplateName Template;<br class="">+ if (Result.end() - Result.begin() > 1) {<br class="">+ IsFunctionTemplate = true;<br class="">+ Template = Context.getOverloadedTemplateName(Result.begin(),<br class="">+ Result.end());<br class="">+ } else if (!Result.empty()) {<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 =<br class="">+ Context.getQualifiedTemplateName(SS.getScopeRep(),<br class="">+ /*TemplateKeyword=*/false, TD);<br class="">+ else<br class="">+ Template = TemplateName(TD);<br class="">+ } else {<br class="">+ // All results were non-template functions. This is a function template<br class="">+ // name.<br class="">+ IsFunctionTemplate = true;<br class="">+ Template = Context.getAssumedTemplateName(NameInfo.getName());<br class="">+ }<br class=""><br class="">- return NameClassification::FunctionTemplate(Template);<br class="">- }<br class="">+ if (IsFunctionTemplate) {<br class="">+ // Function templates always go through overload resolution, at which<br class="">+ // point we'll perform the various checks (e.g., accessibility) we need<br class="">+ // to based on which function we selected.<br class="">+ Result.suppressDiagnostics();<br class=""><br class="">- return IsVarTemplate ? NameClassification::VarTemplate(Template)<br class="">- : NameClassification::TypeTemplate(Template);<br class="">+ return NameClassification::FunctionTemplate(Template);<br class=""> }<br class="">+<br class="">+ return IsVarTemplate ? NameClassification::VarTemplate(Template)<br class="">+ : NameClassification::TypeTemplate(Template);<br class=""> }<br class=""><br class=""> NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();<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=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br class="">+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed May 8 20:31:27 2019<br class="">@@ -3881,6 +3881,8 @@ Sema::BuildMemInitializer(Decl *Construc<br class=""><br class=""> if (TemplateTypeTy) {<br class=""> BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);<br class="">+ if (BaseType.isNull())<br class="">+ return true;<br class=""> } else if (DS.getTypeSpecType() == TST_decltype) {<br class=""> BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());<br class=""> } else if (DS.getTypeSpecType() == TST_decltype_auto) {<br class=""><br class="">Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br class="">+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed May 8 20:31:27 2019<br class="">@@ -2065,11 +2065,12 @@ bool Sema::DiagnoseEmptyLookup(Scope *S,<br class=""> // is in the wrong place to recover. Suggest the typo<br class=""> // correction, but don't make it a fix-it since we're not going<br class=""> // to recover well anyway.<br class="">- AcceptableWithoutRecovery =<br class="">- isa<TypeDecl>(UnderlyingND) || isa<ObjCInterfaceDecl>(UnderlyingND);<br class="">+ AcceptableWithoutRecovery = isa<TypeDecl>(UnderlyingND) ||<br class="">+ getAsTypeTemplateDecl(UnderlyingND) ||<br class="">+ isa<ObjCInterfaceDecl>(UnderlyingND);<br class=""> } else {<br class="">- // FIXME: We found a keyword or a type. Suggest it, but don't provide a<br class="">- // fix-it because we aren't able to recover.<br class="">+ // FIXME: We found a keyword. Suggest it, but don't provide a fix-it<br class="">+ // because we aren't able to recover.<br class=""> AcceptableWithoutRecovery = true;<br class=""> }<br class=""><br class="">@@ -2221,8 +2222,10 @@ Sema::ActOnIdExpression(Scope *S, CXXSco<br class=""> // this becomes a performance hit, we can work harder to preserve those<br class=""> // results until we get here but it's likely not worth it.<br class=""> bool MemberOfUnknownSpecialization;<br class="">+ AssumedTemplateKind AssumedTemplate;<br class=""> if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,<br class="">- MemberOfUnknownSpecialization, TemplateKWLoc))<br class="">+ MemberOfUnknownSpecialization, TemplateKWLoc,<br class="">+ &AssumedTemplate))<br class=""> return ExprError();<br class=""><br class=""> if (MemberOfUnknownSpecialization ||<br class="">@@ -5518,7 +5521,24 @@ tryImplicitlyCaptureThisIfImplicitMember<br class=""> ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,<br class=""> MultiExprArg ArgExprs, SourceLocation RParenLoc,<br class=""> Expr *ExecConfig) {<br class="">- return BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig);<br class="">+ ExprResult Call =<br class="">+ BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig);<br class="">+ if (Call.isInvalid())<br class="">+ return Call;<br class="">+<br class="">+ // Diagnose uses of the C++20 "ADL-only template-id call" feature in earlier<br class="">+ // language modes.<br class="">+ if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(Fn)) {<br class="">+ if (ULE->hasExplicitTemplateArgs() &&<br class="">+ ULE->decls_begin() == ULE->decls_end()) {<br class="">+ Diag(Fn->getExprLoc(), getLangOpts().CPlusPlus2a<br class="">+ ? diag::warn_cxx17_compat_adl_only_template_id<br class="">+ : diag::ext_adl_only_template_id)<br class="">+ << ULE->getName();<br class="">+ }<br class="">+ }<br class="">+<br class="">+ return Call;<br class=""> }<br class=""><br class=""> /// BuildCallExpr - Handle a call to Fn with the specified array of arguments.<br class=""><br class="">Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br class="">+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed May 8 20:31:27 2019<br class="">@@ -7074,7 +7074,8 @@ ExprResult Sema::ActOnPseudoDestructorEx<br class=""> TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;<br class=""> ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),<br class=""> TemplateId->NumArgs);<br class="">- TypeResult T = ActOnTemplateIdType(TemplateId->SS,<br class="">+ TypeResult T = ActOnTemplateIdType(S,<br class="">+ TemplateId->SS,<br class=""> TemplateId->TemplateKWLoc,<br class=""> TemplateId->Template,<br class=""> TemplateId->Name,<br class="">@@ -7126,7 +7127,8 @@ ExprResult Sema::ActOnPseudoDestructorEx<br class=""> TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;<br class=""> ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),<br class=""> TemplateId->NumArgs);<br class="">- TypeResult T = ActOnTemplateIdType(TemplateId->SS,<br class="">+ TypeResult T = ActOnTemplateIdType(S,<br class="">+ TemplateId->SS,<br class=""> TemplateId->TemplateKWLoc,<br class=""> TemplateId->Template,<br class=""> TemplateId->Name,<br class=""><br class="">Modified: cfe/trunk/lib/Sema/SemaOverload.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)<br class="">+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed May 8 20:31:27 2019<br class="">@@ -12017,7 +12017,8 @@ bool Sema::buildOverloadedCallSet(Scope<br class=""> // We don't perform ADL for implicit declarations of builtins.<br class=""> // Verify that this was correctly set up.<br class=""> FunctionDecl *F;<br class="">- if (ULE->decls_begin() + 1 == ULE->decls_end() &&<br class="">+ if (ULE->decls_begin() != ULE->decls_end() &&<br class="">+ ULE->decls_begin() + 1 == ULE->decls_end() &&<br class=""> (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&<br class=""> F->getBuiltinID() && F->isImplicit())<br class=""> llvm_unreachable("performing ADL for builtin");<br class="">@@ -12201,10 +12202,9 @@ ExprResult Sema::BuildOverloadedCallExpr<br class=""> OverloadingResult OverloadResult =<br class=""> CandidateSet.BestViableFunction(*this, Fn->getBeginLoc(), Best);<br class=""><br class="">- return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args,<br class="">- RParenLoc, ExecConfig, &CandidateSet,<br class="">- &Best, OverloadResult,<br class="">- AllowTypoCorrection);<br class="">+ return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, RParenLoc,<br class="">+ ExecConfig, &CandidateSet, &Best,<br class="">+ OverloadResult, AllowTypoCorrection);<br class=""> }<br class=""><br class=""> static bool IsOverloaded(const UnresolvedSetImpl &Functions) {<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=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)<br class="">+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed May 8 20:31:27 2019<br class="">@@ -130,10 +130,15 @@ void Sema::FilterAcceptableTemplateNames<br class=""><br class=""> bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,<br class=""> bool AllowFunctionTemplates,<br class="">- bool AllowDependent) {<br class="">- for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)<br class="">+ bool AllowDependent,<br class="">+ bool AllowNonTemplateFunctions) {<br class="">+ for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) {<br class=""> if (getAsTemplateNameDecl(*I, AllowFunctionTemplates, AllowDependent))<br class=""> return true;<br class="">+ if (AllowNonTemplateFunctions &&<br class="">+ isa<FunctionDecl>((*I)->getUnderlyingDecl()))<br class="">+ return true;<br class="">+ }<br class=""><br class=""> return false;<br class=""> }<br class="">@@ -171,11 +176,25 @@ TemplateNameKind Sema::isTemplateName(Sc<br class=""><br class=""> QualType ObjectType = ObjectTypePtr.get();<br class=""><br class="">+ AssumedTemplateKind AssumedTemplate;<br class=""> LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName);<br class=""> if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,<br class="">- MemberOfUnknownSpecialization))<br class="">+ MemberOfUnknownSpecialization, SourceLocation(),<br class="">+ &AssumedTemplate))<br class="">+ return TNK_Non_template;<br class="">+<br class="">+ if (AssumedTemplate != AssumedTemplateKind::None) {<br class="">+ TemplateResult = TemplateTy::make(Context.getAssumedTemplateName(TName));<br class="">+ // Let the parser know whether we found nothing or found functions; if we<br class="">+ // found nothing, we want to more carefully check whether this is actually<br class="">+ // a function template name versus some other kind of undeclared identifier.<br class="">+ return AssumedTemplate == AssumedTemplateKind::FoundNothing<br class="">+ ? TNK_Undeclared_template<br class="">+ : TNK_Function_template;<br class="">+ }<br class="">+<br class="">+ if (R.empty())<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="">@@ -325,7 +344,11 @@ bool Sema::LookupTemplateName(LookupResu<br class=""> QualType ObjectType,<br class=""> bool EnteringContext,<br class=""> bool &MemberOfUnknownSpecialization,<br class="">- SourceLocation TemplateKWLoc) {<br class="">+ SourceLocation TemplateKWLoc,<br class="">+ AssumedTemplateKind *ATK) {<br class="">+ if (ATK)<br class="">+ *ATK = AssumedTemplateKind::None;<br class="">+<br class=""> Found.setTemplateNameLookup(true);<br class=""><br class=""> // Determine where to perform name lookup<br class="">@@ -405,6 +428,32 @@ bool Sema::LookupTemplateName(LookupResu<br class=""> if (Found.isAmbiguous())<br class=""> return false;<br class=""><br class="">+ if (ATK && !SS.isSet() && ObjectType.isNull() && TemplateKWLoc.isInvalid()) {<br class="">+ // C++2a [temp.names]p2:<br class="">+ // A name is also considered to refer to a template if it is an<br class="">+ // unqualified-id followed by a < and name lookup finds either one or more<br class="">+ // functions or finds nothing.<br class="">+ //<br class="">+ // To keep our behavior consistent, we apply the "finds nothing" part in<br class="">+ // all language modes, and diagnose the empty lookup in ActOnCallExpr if we<br class="">+ // successfully form a call to an undeclared template-id.<br class="">+ bool AllFunctions =<br class="">+ getLangOpts().CPlusPlus2a &&<br class="">+ std::all_of(Found.begin(), Found.end(), [](NamedDecl *ND) {<br class="">+ return isa<FunctionDecl>(ND->getUnderlyingDecl());<br class="">+ });<br class="">+ if (AllFunctions || (Found.empty() && !IsDependent)) {<br class="">+ // If lookup found any functions, or if this is a name that can only be<br class="">+ // used for a function, then strongly assume this is a function<br class="">+ // template-id.<br class="">+ *ATK = (Found.empty() && Found.getLookupName().isIdentifier())<br class="">+ ? AssumedTemplateKind::FoundNothing<br class="">+ : AssumedTemplateKind::FoundFunctions;<br class="">+ Found.clear();<br class="">+ return false;<br class="">+ }<br class="">+ }<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="">@@ -418,13 +467,13 @@ bool Sema::LookupTemplateName(LookupResu<br class=""> if (TypoCorrection Corrected =<br class=""> CorrectTypo(Found.getLookupNameInfo(), Found.getLookupKind(), S,<br class=""> &SS, FilterCCC, CTK_ErrorRecovery, LookupCtx)) {<br class="">- Found.setLookupName(Corrected.getCorrection());<br class=""> if (auto *ND = Corrected.getFoundDecl())<br class=""> Found.addDecl(ND);<br class=""> FilterAcceptableTemplateNames(Found);<br class=""> if (Found.isAmbiguous()) {<br class=""> Found.clear();<br class=""> } else if (!Found.empty()) {<br class="">+ Found.setLookupName(Corrected.getCorrection());<br class=""> if (LookupCtx) {<br class=""> std::string CorrectedStr(Corrected.getAsString(getLangOpts()));<br class=""> bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&<br class="">@@ -436,8 +485,6 @@ bool Sema::LookupTemplateName(LookupResu<br class=""> diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) << Name);<br class=""> }<br class=""> }<br class="">- } else {<br class="">- Found.setLookupName(Name);<br class=""> }<br class=""> }<br class=""><br class="">@@ -3348,14 +3395,65 @@ QualType Sema::CheckTemplateIdType(Templ<br class=""> return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);<br class=""> }<br class=""><br class="">-TypeResult<br class="">-Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,<br class="">- TemplateTy TemplateD, IdentifierInfo *TemplateII,<br class="">- SourceLocation TemplateIILoc,<br class="">- SourceLocation LAngleLoc,<br class="">- ASTTemplateArgsPtr TemplateArgsIn,<br class="">- SourceLocation RAngleLoc,<br class="">- bool IsCtorOrDtorName, bool IsClassName) {<br class="">+void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName,<br class="">+ TemplateNameKind &TNK,<br class="">+ SourceLocation NameLoc,<br class="">+ IdentifierInfo *&II) {<br class="">+ assert(TNK == TNK_Undeclared_template && "not an undeclared template name");<br class="">+<br class="">+ TemplateName Name = ParsedName.get();<br class="">+ auto *ATN = Name.getAsAssumedTemplateName();<br class="">+ assert(ATN && "not an assumed template name");<br class="">+ II = ATN->getDeclName().getAsIdentifierInfo();<br class="">+<br class="">+ if (!resolveAssumedTemplateNameAsType(S, Name, NameLoc, /*Diagnose*/false)) {<br class="">+ // Resolved to a type template name.<br class="">+ ParsedName = TemplateTy::make(Name);<br class="">+ TNK = TNK_Type_template;<br class="">+ }<br class="">+}<br class="">+<br class="">+bool Sema::resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,<br class="">+ SourceLocation NameLoc,<br class="">+ bool Diagnose) {<br class="">+ // We assumed this undeclared identifier to be an (ADL-only) function<br class="">+ // template name, but it was used in a context where a type was required.<br class="">+ // Try to typo-correct it now.<br class="">+ AssumedTemplateStorage *ATN = Name.getAsAssumedTemplateName();<br class="">+ assert(ATN && "not an assumed template name");<br class="">+<br class="">+ LookupResult R(*this, ATN->getDeclName(), NameLoc, LookupOrdinaryName);<br class="">+ struct CandidateCallback : CorrectionCandidateCallback {<br class="">+ bool ValidateCandidate(const TypoCorrection &TC) override {<br class="">+ return TC.getCorrectionDecl() &&<br class="">+ getAsTypeTemplateDecl(TC.getCorrectionDecl());<br class="">+ }<br class="">+ std::unique_ptr<CorrectionCandidateCallback> clone() override {<br class="">+ return llvm::make_unique<CandidateCallback>(*this);<br class="">+ }<br class="">+ } FilterCCC;<br class="">+<br class="">+ TypoCorrection Corrected =<br class="">+ CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, nullptr,<br class="">+ FilterCCC, CTK_ErrorRecovery);<br class="">+ if (Corrected && Corrected.getFoundDecl()) {<br class="">+ diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest)<br class="">+ << ATN->getDeclName());<br class="">+ Name = TemplateName(Corrected.getCorrectionDeclAs<TemplateDecl>());<br class="">+ return false;<br class="">+ }<br class="">+<br class="">+ if (Diagnose)<br class="">+ Diag(R.getNameLoc(), diag::err_no_template) << R.getLookupName();<br class="">+ return true;<br class="">+}<br class="">+<br class="">+TypeResult Sema::ActOnTemplateIdType(<br class="">+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,<br class="">+ TemplateTy TemplateD, IdentifierInfo *TemplateII,<br class="">+ SourceLocation TemplateIILoc, SourceLocation LAngleLoc,<br class="">+ ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc,<br class="">+ bool IsCtorOrDtorName, bool IsClassName) {<br class=""> if (SS.isInvalid())<br class=""> return true;<br class=""><br class="">@@ -3396,6 +3494,9 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &<br class=""> }<br class=""><br class=""> TemplateName Template = TemplateD.get();<br class="">+ if (Template.getAsAssumedTemplateName() &&<br class="">+ resolveAssumedTemplateNameAsType(S, Template, TemplateIILoc))<br class="">+ return true;<br class=""><br class=""> // Translate the parser's template argument list in our AST format.<br class=""> TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);<br class="">@@ -4141,7 +4242,6 @@ ExprResult Sema::BuildTemplateIdExpr(con<br class=""> // vs template<class T, class U> void f(U);<br class=""><br class=""> // These should be filtered out by our callers.<br class="">- assert(!R.empty() && "empty lookup results when building templateid");<br class=""> assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");<br class=""><br class=""> // Non-function templates require a template argument list.<br class=""><br class="">Modified: cfe/trunk/lib/Serialization/ASTReader.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)<br class="">+++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed May 8 20:31:27 2019<br class="">@@ -8745,6 +8745,11 @@ ASTReader::ReadTemplateName(ModuleFile &<br class=""> return Context.getOverloadedTemplateName(Decls.begin(), Decls.end());<br class=""> }<br class=""><br class="">+ case TemplateName::AssumedTemplate: {<br class="">+ DeclarationName Name = ReadDeclarationName(F, Record, Idx);<br class="">+ return Context.getAssumedTemplateName(Name);<br class="">+ }<br class="">+<br class=""> case TemplateName::QualifiedTemplate: {<br class=""> NestedNameSpecifier *NNS = ReadNestedNameSpecifier(F, Record, Idx);<br class=""> bool hasTemplKeyword = Record[Idx++];<br class=""><br class="">Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br class="">+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed May 8 20:31:27 2019<br class="">@@ -5877,6 +5877,12 @@ void ASTRecordWriter::AddTemplateName(Te<br class=""> break;<br class=""> }<br class=""><br class="">+ case TemplateName::AssumedTemplate: {<br class="">+ AssumedTemplateStorage *ADLT = Name.getAsAssumedTemplateName();<br class="">+ AddDeclarationName(ADLT->getDeclName());<br class="">+ break;<br class="">+ }<br class="">+<br class=""> case TemplateName::QualifiedTemplate: {<br class=""> QualifiedTemplateName *QualT = Name.getAsQualifiedTemplateName();<br class=""> AddNestedNameSpecifier(QualT->getQualifier());<br class=""><br class="">Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp (original)<br class="">+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp Wed May 8 20:31:27 2019<br class="">@@ -1,25 +1,67 @@<br class=""> // RUN: %clang_cc1 -fsyntax-only -verify %s<br class="">-// expected-no-diagnostics<br class="">+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s<br class="">+// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s<br class=""><br class="">-typedef int f; <br class="">+typedef int fn;<br class=""><br class=""> namespace N0 {<br class="">- struct A { <br class="">- friend void f(); <br class="">+ struct A {<br class="">+ friend void fn();<br class=""> void g() {<br class="">- int i = f(1);<br class="">+ int i = fn(1);<br class=""> }<br class=""> };<br class=""> }<br class=""><br class=""> namespace N1 {<br class="">- struct A { <br class="">- friend void f(A &);<br class="">+ struct A {<br class="">+ friend void fn(A &);<br class=""> operator int();<br class=""> void g(A a) {<br class="">- // ADL should not apply to the lookup of 'f', it refers to the typedef<br class="">+ // ADL should not apply to the lookup of 'fn', it refers to the typedef<br class=""> // above.<br class="">- int i = f(a);<br class="">+ int i = fn(a);<br class=""> }<br class=""> };<br class=""> }<br class="">+<br class="">+namespace std_example {<br class="">+ int h; // expected-note {{non-template declaration}}<br class="">+ void g();<br class="">+#if __cplusplus <= 201703L<br class="">+ // expected-note@-2 {{non-template declaration}}<br class="">+#endif<br class="">+ namespace N {<br class="">+ struct A {};<br class="">+ template<class T> int f(T);<br class="">+ template<class T> int g(T);<br class="">+#if __cplusplus <= 201703L<br class="">+ // expected-note@-2 {{here}}<br class="">+#endif<br class="">+ template<class T> int h(T); // expected-note {{here}}<br class="">+ }<br class="">+<br class="">+ int x = f<N::A>(N::A());<br class="">+#if __cplusplus <= 201703L<br class="">+ // expected-warning@-2 {{C++2a extension}}<br class="">+#endif<br class="">+ int y = g<N::A>(N::A());<br class="">+#if __cplusplus <= 201703L<br class="">+ // expected-error@-2 {{'g' does not name a template but is followed by template arguments; did you mean 'N::g'?}}<br class="">+#endif<br class="">+ int z = h<N::A>(N::A()); // expected-error {{'h' does not name a template but is followed by template arguments; did you mean 'N::h'?}}<br class="">+}<br class="">+<br class="">+namespace AnnexD_example {<br class="">+ struct A {};<br class="">+ void operator<(void (*fp)(), A);<br class="">+ void f() {}<br class="">+ int main() {<br class="">+ A a;<br class="">+ f < a;<br class="">+#if __cplusplus > 201703L<br class="">+ // expected-error@-2 {{expected '>'}}<br class="">+#endif<br class="">+ (f) < a;<br class="">+ }<br class="">+}<br class=""><br class="">Modified: cfe/trunk/test/CXX/drs/dr2xx.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr2xx.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr2xx.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/CXX/drs/dr2xx.cpp (original)<br class="">+++ cfe/trunk/test/CXX/drs/dr2xx.cpp Wed May 8 20:31:27 2019<br class="">@@ -2,6 +2,7 @@<br class=""> // RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors<br class=""> // RUN: %clang_cc1 -std=c++14 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors<br class=""> // RUN: %clang_cc1 -std=c++17 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors<br class="">+// RUN: %clang_cc1 -std=c++2a %s -verify -fexceptions -fcxx-exceptions -pedantic-errors<br class=""><br class=""> // PR13819 -- __SIZE_TYPE__ is incompatible.<br class=""> typedef __SIZE_TYPE__ size_t; // expected-error 0-1 {{extension}}<br class="">@@ -434,7 +435,7 @@ namespace dr239 { // dr239: yes<br class=""> namespace dr241 { // dr241: yes<br class=""> namespace A {<br class=""> struct B {};<br class="">- template <int X> void f(); // expected-note 2{{candidate}}<br class="">+ template <int X> void f(); // expected-note 3{{candidate}}<br class=""> template <int X> void g(B);<br class=""> }<br class=""> namespace C {<br class="">@@ -442,8 +443,8 @@ namespace dr241 { // dr241: yes<br class=""> template <class T> void g(T t); // expected-note {{candidate}}<br class=""> }<br class=""> void h(A::B b) {<br class="">- f<3>(b); // expected-error {{undeclared identifier}}<br class="">- g<3>(b); // expected-error {{undeclared identifier}}<br class="">+ f<3>(b); // expected-error 0-1{{C++2a extension}} expected-error {{no matching}}<br class="">+ g<3>(b); // expected-error 0-1{{C++2a extension}}<br class=""> A::f<3>(b); // expected-error {{no matching}}<br class=""> A::g<3>(b);<br class=""> C::f<3>(b); // expected-error {{no matching}}<br class=""><br class="">Modified: cfe/trunk/test/CXX/drs/dr6xx.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr6xx.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr6xx.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/CXX/drs/dr6xx.cpp (original)<br class="">+++ cfe/trunk/test/CXX/drs/dr6xx.cpp Wed May 8 20:31:27 2019<br class="">@@ -1048,10 +1048,13 @@ namespace dr686 { // dr686: yes<br class=""> template<struct R {} *> struct Y; // expected-error {{cannot be defined in a type specifier}}<br class=""> }<br class=""><br class="">-namespace dr687 { // dr687 still open<br class="">+namespace dr687 { // dr687 (9 c++20, but the issue is still considered open)<br class=""> template<typename T> void f(T a) {<br class="">- // FIXME: This is valid in C++20.<br class="">- g<int>(a); // expected-error {{undeclared}} expected-error {{'('}}<br class="">+ // This is valid in C++20.<br class="">+ g<int>(a);<br class="">+#if __cplusplus <= 201703L<br class="">+ // expected-error@-2 {{C++2a extension}}<br class="">+#endif<br class=""><br class=""> // This is not.<br class=""> template g<int>(a); // expected-error {{expected expression}}<br class=""><br class="">Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp (original)<br class="">+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p5.cpp Wed May 8 20:31:27 2019<br class="">@@ -8,7 +8,10 @@ namespace N {<br class=""> };<br class=""> }<br class=""><br class="">-template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}}<br class="">+template class Z<int>; // expected-error{{explicit instantiation of undeclared template class 'Z'}}<br class="">+<br class="">+struct Q;<br class="">+template class Q<int>; // expected-error{{explicit instantiation of non-template class 'Q'}}<br class=""><br class=""> // FIXME: This example from the standard is wrong; note posted to CWG reflector<br class=""> // on 10/27/2009<br class=""><br class="">Modified: cfe/trunk/test/FixIt/typo-crash.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo-crash.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo-crash.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/FixIt/typo-crash.cpp (original)<br class="">+++ cfe/trunk/test/FixIt/typo-crash.cpp Wed May 8 20:31:27 2019<br class="">@@ -1,14 +1,8 @@<br class=""> // RUN: %clang_cc1 -fsyntax-only -verify %s<br class=""><br class="">-// FIXME: The diagnostics and recovery here are very, very poor.<br class="">-<br class=""> // PR10355<br class="">-template<typename T> void template_id1() { // expected-note {{'template_id1' declared here}} \<br class="">- // expected-note {{possible target for call}}<br class="">- template_id2<> t; // expected-error {{no template named 'template_id2'; did you mean 'template_id1'?}} \<br class="">- // expected-error {{expected ';' after expression}} \<br class="">- // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} \<br class="">- // expected-error {{use of undeclared identifier 't'}}<br class="">+template<typename T> void template_id1() {<br class="">+ template_id2<> t; // expected-error-re {{no template named 'template_id2'{{$}}}}<br class=""> }<br class=""><br class=""> // FIXME: It would be nice if we could get this correction right.<br class=""><br class="">Modified: cfe/trunk/test/Misc/diag-template-diffing.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Misc/diag-template-diffing.cpp (original)<br class="">+++ cfe/trunk/test/Misc/diag-template-diffing.cpp Wed May 8 20:31:27 2019<br class="">@@ -394,7 +394,7 @@ template<double* ...A> class class_ptrs<br class=""> void set13(class_ptrs<&a13, &b13>) {}<br class=""> void test13() {<br class=""> set13(class_ptrs<&c13>());<br class="">- set13(class_ptrss<&a13, &b13, &d13>());<br class="">+ set13(class_ptrs<&a13, &b13, &d13>());<br class=""> }<br class=""> // CHECK-ELIDE-NOTREE: no matching function for call to 'set13'<br class=""> // CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ptrs<&c13, (no argument)>' to 'class_ptrs<&a13, &b13>' for 1st argument<br class=""><br class="">Modified: cfe/trunk/test/Modules/module-private.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/module-private.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/module-private.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Modules/module-private.cpp (original)<br class="">+++ cfe/trunk/test/Modules/module-private.cpp Wed May 8 20:31:27 2019<br class="">@@ -18,9 +18,7 @@ int test_broken() {<br class=""> int *ip = 0;<br class=""> f1(ip); // expected-error{{use of undeclared identifier 'f1'}}<br class=""><br class="">- vector<int> vec; // expected-error{{use of undeclared identifier 'vector'}} \<br class="">- // expected-error{{expected '(' for function-style cast or type construction}} \<br class="">- // expected-error{{use of undeclared identifier 'vec'}}<br class="">+ vector<int> vec; // expected-error{{no template named 'vector'}}<br class=""><br class=""> VisibleStruct vs;<br class=""> vs.field = 0; // expected-error{{no member named 'field' in 'VisibleStruct'}}<br class=""><br class="">Modified: cfe/trunk/test/Modules/submodules-merge-defs.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/submodules-merge-defs.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/submodules-merge-defs.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Modules/submodules-merge-defs.cpp (original)<br class="">+++ cfe/trunk/test/Modules/submodules-merge-defs.cpp Wed May 8 20:31:27 2019<br class="">@@ -29,7 +29,7 @@ B::Inner2 pre_bi; // expected-error +{{m<br class=""> // <a href="mailto:expected-note@defs.h" class="">expected-note@defs.h</a>:4 +{{here}}<br class=""> // <a href="mailto:expected-note@defs.h" class="">expected-note@defs.h</a>:17 +{{here}}<br class=""> void pre_bfi(B b) { // expected-error +{{must be imported}}<br class="">- b.f<int>(); // expected-error +{{}}<br class="">+ b.f<int>();<br class=""> }<br class=""><br class=""> C_Base<1> pre_cb1; // expected-error +{{must be imported}}<br class="">@@ -48,7 +48,7 @@ int pre_e = E(0); // expected-error {{mu<br class=""> // <a href="mailto:expected-note@defs.h" class="">expected-note@defs.h</a>:32 +{{here}}<br class=""><br class=""> int pre_ff = F<int>().f(); // expected-error +{{must be imported}}<br class="">-int pre_fg = F<int>().g<int>(); // expected-error +{{must be imported}} expected-error 2{{expected}}<br class="">+int pre_fg = F<int>().g<int>(); // expected-error +{{must be imported}}<br class=""> // <a href="mailto:expected-note@defs.h" class="">expected-note@defs.h</a>:34 +{{here}}<br class=""><br class=""> G::A pre_ga // expected-error +{{must be imported}}<br class=""><br class="">Modified: cfe/trunk/test/Parser/cxx-ambig-init-templ.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-ambig-init-templ.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-ambig-init-templ.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Parser/cxx-ambig-init-templ.cpp (original)<br class="">+++ cfe/trunk/test/Parser/cxx-ambig-init-templ.cpp Wed May 8 20:31:27 2019<br class="">@@ -31,7 +31,7 @@ struct S {<br class=""><br class=""> void f2a(<br class=""> // T3<int> here is a parameter type, so must be declared before it is used.<br class="">- int k1 = c < b, T3 < int > x = 0 // expected-error {{unexpected end of default argument expression}}<br class="">+ int k1 = c < b, T3 < int > x = 0 // expected-error {{no template named 'T3'}}<br class=""> );<br class=""><br class=""> template<typename, int=0> struct T3 { T3(int); operator int(); };<br class=""><br class="">Modified: cfe/trunk/test/Parser/cxx-template-argument.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-argument.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-argument.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Parser/cxx-template-argument.cpp (original)<br class="">+++ cfe/trunk/test/Parser/cxx-template-argument.cpp Wed May 8 20:31:27 2019<br class="">@@ -60,33 +60,32 @@ namespace pr16225add {<br class=""> template<int N1, int N2> struct ABC2 {};<br class=""><br class=""> template<class T1, typename T2> struct foo :<br class="">- UnknownBase<T1,T2> // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<T1,T2> // expected-error {{no template named 'UnknownBase'}}<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo2 :<br class="">- UnknownBase<T1,T2>, // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<T1,T2>, // expected-error {{no template named 'UnknownBase'}}<br class=""> Known<T1> // expected-error {{too few template arguments for class template 'Known'}}<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo3 :<br class="">- UnknownBase<T1,T2,ABC<T2,T1> > // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<T1,T2,ABC<T2,T1> > // expected-error {{no template named 'UnknownBase'}}<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo4 :<br class="">- UnknownBase<T1,ABC<T2> >, // expected-error {{unknown template name 'UnknownBase'}} \<br class="">- // expected-error {{too few template arguments for class template 'ABC'}}<br class="">+ UnknownBase<T1,ABC<T2> >, // expected-error {{too few template arguments for class template 'ABC'}}<br class=""> Known<T1> // expected-error {{too few template arguments for class template 'Known'}}<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo5 :<br class="">- UnknownBase<T1,T2,ABC<T2,T1>> // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<T1,T2,ABC<T2,T1>> // expected-error {{no template named 'UnknownBase'}}<br class=""> #if __cplusplus <= 199711L<br class=""> // expected-error@-2 {{use '> >'}}<br class=""> #endif<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo6 :<br class="">- UnknownBase<T1,ABC<T2,T1>>, // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<T1,ABC<T2,T1>>, // expected-error {{no template named 'UnknownBase'}}<br class=""> #if __cplusplus <= 199711L<br class=""> // expected-error@-2 {{use '> >'}}<br class=""> #endif<br class="">@@ -94,32 +93,32 @@ namespace pr16225add {<br class=""> { };<br class=""><br class=""> template<class T1, typename T2, int N> struct foo7 :<br class="">- UnknownBase<T1,T2,(N>1)> // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<T1,T2,(N>1)> // expected-error {{no template named 'UnknownBase'}}<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo8 :<br class="">- UnknownBase<X<int,int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<X<int,int>,X<int,int>> // expected-error {{no template named 'UnknownBase'}}<br class=""> #if __cplusplus <= 199711L<br class=""> // expected-error@-2 {{use '> >'}}<br class=""> #endif<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo9 :<br class="">- UnknownBase<Known<int,int>,X<int,int>> // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<Known<int,int>,X<int,int>> // expected-error {{no template named 'UnknownBase'}}<br class=""> #if __cplusplus <= 199711L<br class=""> // expected-error@-2 {{use '> >'}}<br class=""> #endif<br class=""> { };<br class=""><br class=""> template<class T1, typename T2> struct foo10 :<br class="">- UnknownBase<Known<int,int>,X<int,X<int,int>>> // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<Known<int,int>,X<int,X<int,int>>> // expected-error {{no template named 'UnknownBase'}}<br class=""> #if __cplusplus <= 199711L<br class=""> // expected-error@-2 {{use '> >'}}<br class=""> #endif<br class=""> { };<br class=""><br class=""> template<int N1, int N2> struct foo11 :<br class="">- UnknownBase<2<N1,N2<4> // expected-error {{unknown template name 'UnknownBase'}}<br class="">+ UnknownBase<2<N1,N2<4> // expected-error {{no template named 'UnknownBase'}}<br class=""> { };<br class=""><br class=""> }<br class=""><br class="">Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)<br class="">+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Wed May 8 20:31:27 2019<br class="">@@ -128,8 +128,13 @@ void f2() {<br class=""><br class=""><br class=""> // PR3844<br class="">-template <> struct S<int> { }; // expected-error{{explicit specialization of non-template struct 'S'}}<br class="">-template <> union U<int> { }; // expected-error{{explicit specialization of non-template union 'U'}}<br class="">+template <> struct S<int> { }; // expected-error{{explicit specialization of undeclared template struct 'S'}}<br class="">+template <> union U<int> { }; // expected-error{{explicit specialization of undeclared template union 'U'}}<br class="">+<br class="">+struct SS;<br class="">+union UU;<br class="">+template <> struct SS<int> { }; // expected-error{{explicit specialization of non-template struct 'SS'}}<br class="">+template <> union UU<int> { }; // expected-error{{explicit specialization of non-template union 'UU'}}<br class=""><br class=""> namespace PR6184 {<br class=""> namespace N {<br class="">@@ -230,11 +235,11 @@ struct base { };<br class=""><br class=""> struct t1 : base<int,<br class=""> public: // expected-error {{expected expression}}<br class="">-}; // expected-error {{expected class name}}<br class="">+};<br class=""> // expected-error@-1 {{expected '{' after base class list}}<br class=""> struct t2 : base<int,<br class=""> public // expected-error {{expected expression}}<br class="">-}; // expected-error {{expected class name}}<br class="">+};<br class=""> // expected-error@-1 {{expected '{' after base class list}}<br class=""><br class=""> }<br class=""><br class="">Modified: cfe/trunk/test/SemaCXX/alias-template.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alias-template.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alias-template.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaCXX/alias-template.cpp (original)<br class="">+++ cfe/trunk/test/SemaCXX/alias-template.cpp Wed May 8 20:31:27 2019<br class="">@@ -112,11 +112,8 @@ namespace StdExample {<br class=""> template<typename T> using handler_t = void (*)(T);<br class=""> extern handler_t<int> ignore;<br class=""> extern void (*ignore)(int);<br class="">- // FIXME: we recover as if cell is an undeclared variable. the diagnostics are terrible!<br class="">- template<typename T> using cell = pair<T*, cell<T>*>; // expected-error {{use of undeclared identifier 'cell'}} \<br class="">- expected-error {{'T' does not refer to a value}} \<br class="">- expected-note {{declared here}} \<br class="">- expected-error {{expected ';' after alias declaration}}<br class="">+ // FIXME: we recover as if cell is an undeclared variable template<br class="">+ template<typename T> using cell = pair<T*, cell<T>*>; // expected-error {{use of undeclared identifier 'cell'}} expected-error {{expected expression}}<br class=""> }<br class=""><br class=""> namespace Access {<br class=""><br class="">Modified: cfe/trunk/test/SemaCXX/class.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaCXX/class.cpp (original)<br class="">+++ cfe/trunk/test/SemaCXX/class.cpp Wed May 8 20:31:27 2019<br class="">@@ -138,7 +138,7 @@ struct S<br class=""> // Don't crash on this bogus code.<br class=""> namespace pr6629 {<br class=""> template<class T1, class T2> struct foo :<br class="">- bogus<foo<T1,T2> > // expected-error {{unknown template name 'bogus'}}<br class="">+ bogus<foo<T1,T2> > // expected-error {{no template named 'bogus'}}<br class=""> { };<br class=""><br class=""> template<> struct foo<unknown,unknown> { // expected-error {{undeclared identifier 'unknown'}}<br class=""><br class="">Added: cfe/trunk/test/SemaCXX/cxx2a-adl-only-template-id.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-adl-only-template-id.cpp?rev=360308&view=auto" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-adl-only-template-id.cpp?rev=360308&view=auto</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaCXX/cxx2a-adl-only-template-id.cpp (added)<br class="">+++ cfe/trunk/test/SemaCXX/cxx2a-adl-only-template-id.cpp Wed May 8 20:31:27 2019<br class="">@@ -0,0 +1,67 @@<br class="">+// RUN: %clang_cc1 -std=c++2a -verify %s<br class="">+<br class="">+namespace N {<br class="">+ struct Q {};<br class="">+ template<typename> int f(Q);<br class="">+ template<int> int f(Q);<br class="">+ template<typename> int g(Q);<br class="">+ template<int> int g(Q);<br class="">+<br class="">+ template<int> int some_long_name(Q); // expected-note {{here}}<br class="">+}<br class="">+N::Q q;<br class="">+int g();<br class="">+<br class="">+int h();<br class="">+template<int> int h(...);<br class="">+int h(int);<br class="">+<br class="">+// OK, these find the above functions by ADL.<br class="">+int a = f<int>(q);<br class="">+int b(f<int>(q));<br class="">+int c(f<0>(q));<br class="">+int d = g<int>(q);<br class="">+<br class="">+int e = h<0>(q); // ok, found by unqualified lookup<br class="">+<br class="">+void fn() {<br class="">+ f<0>(q);<br class="">+ int f;<br class="">+ f<0>(q); // expected-error {{invalid operands to binary expression}}<br class="">+}<br class="">+<br class="">+void disambig() {<br class="">+ // FIXME: It's unclear whether ending the template argument at the > inside the ?: is correct here (see DR579).<br class="">+ f<true ? 1 > 2 : 3>(q); // expected-error {{expected ':'}} expected-note {{to match}} expected-error {{expected expression}}<br class="">+<br class="">+ f < 1 + 3 > (q); // ok, function call<br class="">+}<br class="">+<br class="">+bool typo(int something) { // expected-note 4{{declared here}}<br class="">+ // FIXME: We shouldn't suggest the N:: for an ADL call if the candidate can be found by ADL.<br class="">+ some_logn_name<3>(q); // expected-error {{did you mean 'N::some_long_name'?}}<br class="">+ somethign < 3 ? h() > 4 : h(0); // expected-error {{did you mean 'something'}}<br class="">+ // This is parsed as a comparison on the left of a ?: expression.<br class="">+ somethign < 3 ? h() + 4 : h(0); // expected-error {{did you mean 'something'}}<br class="">+ // This is parsed as an ADL-only template-id call.<br class="">+ somethign < 3 ? h() + 4 : h(0) >(0); // expected-error {{undeclared identifier 'somethign'}}<br class="">+ bool k(somethign < 3); // expected-error {{did you mean 'something'}}<br class="">+ return somethign < 3; // expected-error {{did you mean 'something'}}<br class="">+}<br class="">+<br class="">+// Ensure that treating undeclared identifiers as template names doesn't cause<br class="">+// problems.<br class="">+struct W<int> {}; // expected-error {{undeclared template struct 'W'}}<br class="">+X<int>::Y xy; // expected-error {{no template named 'X'}}<br class="">+void xf(X<int> x); // expected-error {{no template named 'X'}}<br class="">+struct A : X<int> { // expected-error {{no template named 'X'}}<br class="">+ A() : X<int>() {} // expected-error {{no template named 'X'}}<br class="">+};<br class="">+<br class="">+// Similarly for treating overload sets of functions as template names.<br class="">+struct g<int> {}; // expected-error {{'g' refers to a function template}}<br class="">+g<int>::Y xy; // expected-error {{no template named 'g'}} FIXME lies<br class="">+void xf(g<int> x); // expected-error {{variable has incomplete type 'void'}} expected-error 1+{{}} expected-note {{}}<br class="">+struct B : g<int> { // expected-error {{expected class name}}<br class="">+ B() : g<int>() {} // expected-error {{expected class member or base class name}}<br class="">+};<br class=""><br class="">Modified: cfe/trunk/test/SemaCXX/destructor.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaCXX/destructor.cpp (original)<br class="">+++ cfe/trunk/test/SemaCXX/destructor.cpp Wed May 8 20:31:27 2019<br class="">@@ -99,7 +99,7 @@ struct Y {<br class=""> namespace PR6421 {<br class=""> class T; // expected-note{{forward declaration}}<br class=""><br class="">- class QGenericArgument // expected-note{{declared here}}<br class="">+ class QGenericArgument<br class=""> {<br class=""> template<typename U><br class=""> void foo(T t) // expected-error{{variable has incomplete type}}<br class="">@@ -108,8 +108,7 @@ namespace PR6421 {<br class=""> void disconnect()<br class=""> {<br class=""> T* t;<br class="">- bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \<br class="">- // expected-error{{does not refer to a value}}<br class="">+ bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}}<br class=""> }<br class=""> };<br class=""> }<br class=""><br class="">Modified: cfe/trunk/test/SemaCXX/invalid-member-expr.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/invalid-member-expr.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/invalid-member-expr.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaCXX/invalid-member-expr.cpp (original)<br class="">+++ cfe/trunk/test/SemaCXX/invalid-member-expr.cpp Wed May 8 20:31:27 2019<br class="">@@ -53,7 +53,10 @@ namespace test3 {<br class=""> namespace rdar11293995 {<br class=""><br class=""> struct Length {<br class="">- explicit Length(PassRefPtr<CalculationValue>); // expected-error {{no template named 'PassRefPtr}} expected-error {{undeclared identifier 'CalculationValue'}}<br class="">+ // FIXME: We try to annotate the template-id here during tentative parsing,<br class="">+ // and fail, then try again during the actual parse. This results in the same<br class="">+ // diagnostic being produced twice. :(<br class="">+ explicit Length(PassRefPtr<CalculationValue>); // expected-error 2{{undeclared identifier 'CalculationValue'}}<br class=""> };<br class=""><br class=""> struct LengthSize {<br class=""><br class="">Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaCXX/typo-correction.cpp (original)<br class="">+++ cfe/trunk/test/SemaCXX/typo-correction.cpp Wed May 8 20:31:27 2019<br class="">@@ -438,7 +438,7 @@ namespace PR17394 {<br class=""> long zzzzzzzzzz;<br class=""> };<br class=""> class B : private A {};<br class="">- B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{}<br class="">+ B zzzzzzzzzy<>; // expected-error {{template specialization requires 'template<>'}} expected-error {{no variable template matches specialization}}<br class=""> }<br class=""><br class=""> namespace correct_fields_in_member_funcs {<br class=""><br class="">Modified: cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp (original)<br class="">+++ cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp Wed May 8 20:31:27 2019<br class="">@@ -9,7 +9,7 @@ template<typename T, typename U><br class=""> struct X1 : T::apply<U> { }; // expected-error{{use 'template' keyword to treat 'apply' as a dependent template name}}<br class=""><br class=""> template<typename T><br class="">-struct X2 : vector<T> { }; // expected-error{{unknown template name 'vector'}}<br class="">+struct X2 : vector<T> { }; // expected-error{{no template named 'vector'}}<br class=""><br class=""> namespace PR6031 {<br class=""> template<typename T><br class=""><br class="">Modified: cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp (original)<br class="">+++ cfe/trunk/test/SemaTemplate/dependent-template-recover.cpp Wed May 8 20:31:27 2019<br class="">@@ -7,7 +7,7 @@ struct X {<br class=""><br class=""> t->operator+<U const, 1>(1); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}}<br class=""> t->f1<int const, 2>(1); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}}<br class="">- t->f1<3, int const>(1); // expected-error{{missing 'template' keyword prior to dependent template name 'f1'}}<br class="">+ t->f1<3, int const>(1); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}}<br class=""><br class=""> T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}}<br class=""> t->T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}}<br class="">@@ -15,7 +15,7 @@ struct X {<br class=""> (*t).f2<N>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}<br class=""> (*t).f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}<br class=""> T::f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}<br class="">- T::f2<0, int>(0); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}<br class="">+ T::f2<0, int>(0); // expected-error{{use 'template' keyword to treat 'f2' as a dependent template name}}<br class=""><br class=""> T::foo<N < 2 || N >= 4>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}<br class=""><br class="">@@ -24,7 +24,7 @@ struct X {<br class=""> T::foo<T::bar < 1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}<br class=""> T::foo < T::bar<1>(); // expected-error{{missing 'template' keyword prior to dependent template name 'bar'}}<br class=""><br class="">- // Prefer to diagonse a missing 'template' keyword rather than finding a non-template name.<br class="">+ // Prefer to diagnose a missing 'template' keyword rather than finding a non-template name.<br class=""> xyz < T::foo < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}<br class=""> T::foo < xyz < 1 > (); // expected-error{{missing 'template' keyword prior to dependent template name 'foo'}}<br class=""><br class="">@@ -83,12 +83,12 @@ template<int N, typename T> void f(T t)<br class=""> T::g<mb>(0);<br class=""><br class=""> // ... but this one must be a template-id.<br class="">- T::g<mb, int>(0); // expected-error {{missing 'template' keyword prior to dependent template name 'g'}}<br class="">+ T::g<mb, int>(0); // expected-error {{use 'template' keyword to treat 'g' as a dependent template name}} expected-error {{no matching function}}<br class=""> }<br class=""><br class=""> struct Y {<br class=""> template <int> void f(int);<br class="">- template <int = 0> static void g(int); // expected-warning 0-1{{extension}}<br class="">+ template <int = 0> static void g(int); // expected-warning 0-1{{extension}} expected-note {{candidate}}<br class=""> };<br class=""> void q() { void (*p)(int) = Y::g; }<br class=""> template void f<0>(Y); // expected-note {{in instantiation of}}<br class=""><br class="">Modified: cfe/trunk/test/SemaTemplate/rdar9173693.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/rdar9173693.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/rdar9173693.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaTemplate/rdar9173693.cpp (original)<br class="">+++ cfe/trunk/test/SemaTemplate/rdar9173693.cpp Wed May 8 20:31:27 2019<br class="">@@ -2,5 +2,8 @@<br class=""><br class=""> // <<a href="rdar://problem/9173693" class="">rdar://problem/9173693</a>><br class=""> template< bool C > struct assert { };<br class="">-template< bool > struct assert_arg_pred_impl { }; // expected-note 3 {{declared here}}<br class="">-template< typename Pred > assert<false> assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type ); // expected-error 5 {{}}<br class="">+// FIXME: We diagnose the same problem multiple times here because we have no<br class="">+// way to indicate in the token stream that we already tried to annotate a<br class="">+// template-id and we failed.<br class="">+template< bool > struct assert_arg_pred_impl { }; // expected-note 4 {{declared here}}<br class="">+template< typename Pred > assert<false> assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type ); // expected-error 6 {{}}<br class=""><br class="">Modified: cfe/trunk/test/SemaTemplate/recovery-crash.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/recovery-crash.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/recovery-crash.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/test/SemaTemplate/recovery-crash.cpp (original)<br class="">+++ cfe/trunk/test/SemaTemplate/recovery-crash.cpp Wed May 8 20:31:27 2019<br class="">@@ -28,12 +28,12 @@ namespace PR16134 {<br class=""> namespace PR16225 {<br class=""> template <typename T> void f();<br class=""> template <typename C> void g(C*) {<br class="">- struct LocalStruct : UnknownBase<Mumble, C> { }; // expected-error {{unknown template name 'UnknownBase'}} \<br class="">- // expected-error {{use of undeclared identifier 'Mumble'}}<br class="">+ struct LocalStruct : UnknownBase<Mumble, C> { }; // expected-error {{use of undeclared identifier 'Mumble'}}<br class=""> f<LocalStruct>();<br class=""> #if __cplusplus <= 199711L<br class=""> // expected-warning@-2 {{template argument uses local type 'LocalStruct'}}<br class=""> #endif<br class="">+ struct LocalStruct2 : UnknownBase<C> { }; // expected-error {{no template named 'UnknownBase'}}<br class=""> }<br class=""> struct S;<br class=""> void h() {<br class=""><br class="">Modified: cfe/trunk/tools/libclang/CIndex.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/tools/libclang/CIndex.cpp (original)<br class="">+++ cfe/trunk/tools/libclang/CIndex.cpp Wed May 8 20:31:27 2019<br class="">@@ -1430,6 +1430,10 @@ bool CursorVisitor::VisitTemplateName(Te<br class=""><br class=""> return false;<br class=""><br class="">+ case TemplateName::AssumedTemplate:<br class="">+ // FIXME: Visit DeclarationName?<br class="">+ return false;<br class="">+<br class=""> case TemplateName::DependentTemplate:<br class=""> // FIXME: Visit nested-name-specifier.<br class=""> return false;<br class=""><br class="">Modified: cfe/trunk/www/cxx_status.html<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=360308&r1=360307&r2=360308&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=360308&r1=360307&r2=360308&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/www/cxx_status.html (original)<br class="">+++ cfe/trunk/www/cxx_status.html Wed May 8 20:31:27 2019<br class="">@@ -893,7 +893,7 @@ as the draft C++2a standard evolves.<br class=""> <tr><br class=""> <td>ADL and function templates that are not visible</td><br class=""> <td><a href="<a href="http://wg21.link/p0846r0" class="">http://wg21.link/p0846r0</a>">P0846R0</a></td><br class="">- <td class="none" align="center">No</td><br class="">+ <td class="svn" align="center">SVN</td><br class=""> </tr><br class=""> <tr><br class=""> <td><tt>const</tt> mismatch with defaulted copy constructor</td><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=""></div></div></blockquote></div><br class=""></div></body></html>