Implement a new identifier-classification scheme where Sema
performs name lookup for an identifier and resolves it to a
type/expression/template/etc. in the same step. This scheme is
intended to improve both performance (by reducing the number of
redundant name lookups for a given identifier token) and error
recovery (by giving Sema a chance to correct type names before the
parser has decided that the identifier isn't a type name). For
example, this allows us to properly typo-correct type names at the
beginning of a statement:

t.c:6:3: error: use of undeclared identifier 'integer'; did you mean
'Integer'?
  integer *i = 0;
  ^~~~~~~
  Integer
t.c:1:13: note: 'Integer' declared here
typedef int Integer;
            ^


Previously, we wouldn't give a Fix-It because the typo correction
occurred after the parser had checked whether "integer" was a type
name (via Sema::getTypeName(), which isn't allowed to typo-correct)
and therefore decided to parse "integer * i = 0" as an expression. By
typo-correcting earlier, we typo-correct to the type name Integer and
parse this as a declaration. 

Moreover, in this context, we can also typo-correct identifiers to
keywords, e.g.,

t.c:7:3: error: use of undeclared identifier 'vid'; did you mean
'void'?
  vid *p = i;
  ^~~
  void

and recover appropriately.

Note that this is very much a work-in-progress. The new
Sema::ClassifyName is only used for expression-or-declaration
disambiguation in C at the statement level. The next steps will be to
make this work for the same disambiguation in C++ (where
functional-style casts make some trouble), then push it
further into the parser to eliminate more redundant name lookups.

Fixes <rdar://problem/7963833> for C and starts us down the path of
<rdar://problem/8172000>.




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130082 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 08eb654..bc29a4c 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -76,13 +76,13 @@
   return 0;
 }
 
-static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) {
+void Sema::FilterAcceptableTemplateNames(LookupResult &R) {
   // The set of class templates we've already seen.
   llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
   LookupResult::Filter filter = R.makeFilter();
   while (filter.hasNext()) {
     NamedDecl *Orig = filter.next();
-    NamedDecl *Repl = isAcceptableTemplateName(C, Orig);
+    NamedDecl *Repl = isAcceptableTemplateName(Context, Orig);
     if (!Repl)
       filter.erase();
     else if (Repl != Orig) {
@@ -114,6 +114,14 @@
   filter.done();
 }
 
+bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) {
+  for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
+    if (isAcceptableTemplateName(Context, *I))
+      return true;
+  
+  return true;
+}
+
 TemplateNameKind Sema::isTemplateName(Scope *S,
                                       CXXScopeSpec &SS,
                                       bool hasTemplateKeyword,
@@ -289,7 +297,7 @@
     DeclarationName Name = Found.getLookupName();
     if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx,
                                                 false, CTC_CXXCasts)) {
-      FilterAcceptableTemplateNames(Context, Found);
+      FilterAcceptableTemplateNames(Found);
       if (!Found.empty()) {
         if (LookupCtx)
           Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
@@ -311,7 +319,7 @@
     }
   }
 
-  FilterAcceptableTemplateNames(Context, Found);
+  FilterAcceptableTemplateNames(Found);
   if (Found.empty()) {
     if (isDependent)
       MemberOfUnknownSpecialization = true;
@@ -327,7 +335,7 @@
     LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
                             LookupOrdinaryName);
     LookupName(FoundOuter, S);
-    FilterAcceptableTemplateNames(Context, FoundOuter);
+    FilterAcceptableTemplateNames(FoundOuter);
 
     if (FoundOuter.empty()) {
       //   - if the name is not found, the name found in the class of the