<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>