[cfe-commits] r130288 - in /cfe/trunk: lib/Parse/ParseStmt.cpp lib/Parse/Parser.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp test/FixIt/typo.cpp test/SemaCXX/PR9459.cpp test/SemaTemplate/deduction-crash.cpp

Douglas Gregor dgregor at apple.com
Tue Apr 26 21:48:22 PDT 2011


Author: dgregor
Date: Tue Apr 26 23:48:22 2011
New Revision: 130288

URL: http://llvm.org/viewvc/llvm-project?rev=130288&view=rev
Log:
Extend Sema::ClassifyName() to support C++, ironing out a few issues
in the classification of template names and using declarations. We now
properly typo-correct the leading identifiers in statements to types,
templates, values, etc. As an added bonus, this reduces the number of
lookups required for disambiguation.


Modified:
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
    cfe/trunk/test/FixIt/typo.cpp
    cfe/trunk/test/SemaCXX/PR9459.cpp
    cfe/trunk/test/SemaTemplate/deduction-crash.cpp

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue Apr 26 23:48:22 2011
@@ -113,7 +113,7 @@
       return ParseLabeledStatement(attrs);
     }
     
-    if (!getLang().CPlusPlus) {
+    if (Next.isNot(tok::coloncolon)) {
       // FIXME: Temporarily enable this code only for C.
       CXXScopeSpec SS;
       IdentifierInfo *Name = Tok.getIdentifierInfo();
@@ -147,7 +147,7 @@
         // we're in a syntactic context we haven't handled yet. 
         break;     
           
-      case Sema::NC_Type:
+      case Sema::NC_Type: {
         // We have a type. In C, this means that we have a declaration.
         if (!getLang().CPlusPlus) {
           ParsedType Type = Classification.getType();
@@ -195,9 +195,15 @@
           return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
         }
           
-        // In C++, we might also have a functional-style cast.
-        // FIXME: Implement this!
+        // In C++, we might also have a functional-style cast. Just annotate
+        // this as a type token.
+        Tok.setKind(tok::annot_typename);
+        setTypeAnnotation(Tok, Classification.getType());
+        Tok.setAnnotationEndLoc(NameLoc);
+        Tok.setLocation(NameLoc);
+        PP.AnnotateCachedTokens(Tok);
         break;
+      }
           
       case Sema::NC_Expression:
         ConsumeToken(); // the identifier
@@ -211,7 +217,20 @@
         if (AnnotateTemplateIdToken(
                             TemplateTy::make(Classification.getTemplateName()), 
                                     Classification.getTemplateNameKind(),
-                                    SS, Id)) {
+                                    SS, Id, SourceLocation(),
+                                    /*AllowTypeAnnotation=*/false)) {
+          // Handle errors here by skipping up to the next semicolon or '}', and
+          // eat the semicolon if that's what stopped us.
+          SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);
+          if (Tok.is(tok::semi))
+            ConsumeToken();
+          return StmtError();        
+        }
+        
+        // If the next token is '::', jump right into parsing a 
+        // nested-name-specifier. We don't want to leave the template-id
+        // hanging.
+        if (NextToken().is(tok::coloncolon) && TryAnnotateCXXScopeToken(false)){
           // Handle errors here by skipping up to the next semicolon or '}', and
           // eat the semicolon if that's what stopped us.
           SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Apr 26 23:48:22 2011
@@ -1255,7 +1255,8 @@
 bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
   assert(getLang().CPlusPlus &&
          "Call sites of this function should be guarded by checking for C++");
-  assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
+  assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+          (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)))&&
          "Cannot be a type or scope token!");
 
   CXXScopeSpec SS;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Apr 26 23:48:22 2011
@@ -514,15 +514,16 @@
         unsigned QualifiedDiag = diag::err_no_member_suggest;
         
         NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin();
-
+        NamedDecl *UnderlyingFirstDecl
+          = FirstDecl? FirstDecl->getUnderlyingDecl() : 0;
         if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
-            FirstDecl && isa<TemplateDecl>(FirstDecl)) {
+            UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) {
           UnqualifiedDiag = diag::err_no_template_suggest;
           QualifiedDiag = diag::err_no_member_template_suggest;
-        } else if (FirstDecl && 
-                   (isa<TypeDecl>(FirstDecl) || 
-                    isa<ObjCInterfaceDecl>(FirstDecl) ||
-                    isa<ObjCCompatibleAliasDecl>(FirstDecl))) {
+        } else if (UnderlyingFirstDecl && 
+                   (isa<TypeDecl>(UnderlyingFirstDecl) || 
+                    isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) ||
+                    isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) {
            UnqualifiedDiag = diag::err_unknown_typename_suggest;
            QualifiedDiag = diag::err_unknown_nested_typename_suggest;
          }
@@ -588,7 +589,8 @@
     break;
       
   case LookupResult::Ambiguous:
-    if (getLangOptions().CPlusPlus && NextToken.is(tok::less)) {
+    if (getLangOptions().CPlusPlus && NextToken.is(tok::less) &&
+        hasAnyAcceptableTemplateNames(Result)) {
       // C++ [temp.local]p3:
       //   A lookup that finds an injected-class-name (10.2) can result in an
       //   ambiguity in certain cases (for example, if it is found in more than
@@ -622,37 +624,40 @@
     if (!IsFilteredTemplateName)
       FilterAcceptableTemplateNames(Result);
     
-    bool IsFunctionTemplate;
-    TemplateName Template;
-    if (Result.end() - Result.begin() > 1) {
-      IsFunctionTemplate = true;
-      Template = Context.getOverloadedTemplateName(Result.begin(), 
-                                                   Result.end());
-    } else {
-      TemplateDecl *TD = cast<TemplateDecl>(Result.getFoundDecl());
-      IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
-      
-      if (SS.isSet() && !SS.isInvalid())
-        Template = Context.getQualifiedTemplateName(SS.getScopeRep(), 
+    if (!Result.empty()) {
+      bool IsFunctionTemplate;
+      TemplateName Template;
+      if (Result.end() - Result.begin() > 1) {
+        IsFunctionTemplate = true;
+        Template = Context.getOverloadedTemplateName(Result.begin(), 
+                                                     Result.end());
+      } else {
+        TemplateDecl *TD
+          = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl());
+        IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
+        
+        if (SS.isSet() && !SS.isInvalid())
+          Template = Context.getQualifiedTemplateName(SS.getScopeRep(), 
                                                     /*TemplateKeyword=*/false,
-                                                    TD);
-      else
-        Template = TemplateName(TD);
-    }
-    
-    if (IsFunctionTemplate) {
-      // Function templates always go through overload resolution, at which
-      // point we'll perform the various checks (e.g., accessibility) we need
-      // to based on which function we selected.
-      Result.suppressDiagnostics();
+                                                      TD);
+        else
+          Template = TemplateName(TD);
+      }
+      
+      if (IsFunctionTemplate) {
+        // Function templates always go through overload resolution, at which
+        // point we'll perform the various checks (e.g., accessibility) we need
+        // to based on which function we selected.
+        Result.suppressDiagnostics();
+        
+        return NameClassification::FunctionTemplate(Template);
+      }
       
-      return NameClassification::FunctionTemplate(Template);
+      return NameClassification::TypeTemplate(Template);
     }
-    
-    return NameClassification::TypeTemplate(Template);
   }
   
-  NamedDecl *FirstDecl = *Result.begin();
+  NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl();
   if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) {
     DiagnoseUseOfDecl(Type, NameLoc);
     QualType T = Context.getTypeDeclType(Type);
@@ -681,6 +686,9 @@
     return ParsedType::make(T);
   }
   
+  if (!Result.empty() && (*Result.begin())->isCXXClassMember())
+    return BuildPossibleImplicitMemberExpr(SS, Result, 0);
+
   bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren));
   return BuildDeclarationNameExpr(SS, Result, ADL);
 }

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Apr 26 23:48:22 2011
@@ -119,7 +119,7 @@
     if (isAcceptableTemplateName(Context, *I))
       return true;
   
-  return true;
+  return false;
 }
 
 TemplateNameKind Sema::isTemplateName(Scope *S,

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp Tue Apr 26 23:48:22 2011
@@ -43,8 +43,7 @@
   (void)sizeof(auto); // expected-error{{'auto' not allowed here}}
   (void)__alignof(auto); // expected-error{{'auto' not allowed here}}
 
-  // FIXME: don't issue the second diagnostic for this error.
-  U<auto> v; // expected-error{{'auto' not allowed in template argument}} unexpected-error{{C++ requires a type specifier}}
+  U<auto> v; // expected-error{{'auto' not allowed in template argument}}
 
   int n;
   (void)dynamic_cast<auto&>(S()); // expected-error{{'auto' not allowed here}}

Modified: cfe/trunk/test/FixIt/typo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo.cpp (original)
+++ cfe/trunk/test/FixIt/typo.cpp Tue Apr 26 23:48:22 2011
@@ -65,3 +65,12 @@
 int &Derived::getMember() {
   return ember; // expected-error{{use of undeclared identifier 'ember'; did you mean 'member'?}}
 }
+
+typedef int Integer; // expected-note{{'Integer' declared here}}
+int global_value; // expected-note{{'global_value' declared here}}
+
+int foo() {
+  integer * i = 0; // expected-error{{unknown type name 'integer'; did you mean 'Integer'?}}
+  unsinged *ptr = 0; // expected-error{{use of undeclared identifier 'unsinged'; did you mean 'unsigned'?}}
+  return *i + *ptr + global_val; // expected-error{{use of undeclared identifier 'global_val'; did you mean 'global_value'?}}
+}

Modified: cfe/trunk/test/SemaCXX/PR9459.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR9459.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/PR9459.cpp (original)
+++ cfe/trunk/test/SemaCXX/PR9459.cpp Tue Apr 26 23:48:22 2011
@@ -2,8 +2,6 @@
 
 // Don't crash.
 
-template<typename>struct ae_same; // expected-note {{declared here}}
+template<typename>struct ae_same;
 template<typename>struct ts{}ap()
-{ts<a>::ap<ae_same<int>::&ae_same<>>::p(a); }; // expected-error 2 {{undeclared identifier}} \
-    // expected-error 2 {{expected}} expected-error {{a space is required}} \
-    // expected-error 2 {{global}} expected-error {{too few}}
+{ts<a>::ap<ae_same<int>::&ae_same<>>::p(a); }; // expected-error {{use of undeclared identifier 'a'}}

Modified: cfe/trunk/test/SemaTemplate/deduction-crash.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/deduction-crash.cpp?rev=130288&r1=130287&r2=130288&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/deduction-crash.cpp (original)
+++ cfe/trunk/test/SemaTemplate/deduction-crash.cpp Tue Apr 26 23:48:22 2011
@@ -4,7 +4,7 @@
 
 // Note that the error count below doesn't matter. We just want to
 // make sure that the parser doesn't crash.
-// CHECK: 14 errors
+// CHECK: 13 errors
 template<a>
 struct int_;
 





More information about the cfe-commits mailing list