]> granicus.if.org Git - clang/commitdiff
Continue parsing more postfix expressions, even after semantic
authorDouglas Gregor <dgregor@apple.com>
Sat, 18 Sep 2010 01:28:11 +0000 (01:28 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 18 Sep 2010 01:28:11 +0000 (01:28 +0000)
errors. Improves code completion in yet another case.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114255 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Parse/ParseExpr.cpp
lib/Sema/SemaCodeComplete.cpp
test/Index/complete-recovery.m
test/SemaCXX/copy-assignment.cpp

index 4164f0e15aa8def57e0a21914e9685dac66c883a..1ef14a2284b999190bbb831238eea3f2e5b7d266 100644 (file)
@@ -4313,7 +4313,7 @@ public:
   void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
                                        SourceLocation OpLoc,
                                        bool IsArrow);
-  void CodeCompletePostfixExpression(Scope *S, Expr *LHS);
+  void CodeCompletePostfixExpression(Scope *S, ExprResult LHS);
   void CodeCompleteTag(Scope *S, unsigned TagSpec);
   void CodeCompleteTypeQualifiers(DeclSpec &DS);
   void CodeCompleteCase(Scope *S);
index ec2c5d6b9559c5f32a202709bb0f53a3513178da..e04e62bcb2c011e61168db748d00e298f07a3199 100644 (file)
@@ -242,8 +242,7 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
   ExprResult R
     = ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
                                      ReceiverType, ReceiverExpr);
-  if (R.isInvalid()) return move(R);
-  R = ParsePostfixExpressionSuffix(R.take());
+  R = ParsePostfixExpressionSuffix(R);
   return ParseRHSOfBinaryExpression(R, prec::Assignment);
 }
 
@@ -576,8 +575,6 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
 
       Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
                                  TypeOfCast, CastTy, RParenLoc);
-      if (Res.isInvalid()) 
-        return move(Res);
     }
 
     switch (ParenExprType) {
@@ -1012,8 +1009,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
   }
 
   // These can be followed by postfix-expr pieces.
-  if (Res.isInvalid()) return move(Res);
-  return ParsePostfixExpressionSuffix(Res.get());
+  return ParsePostfixExpressionSuffix(Res);
 }
 
 /// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression
@@ -1045,7 +1041,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
       if (InMessageExpression)
         return move(LHS);
         
-      Actions.CodeCompletePostfixExpression(getCurScope(), LHS.take());
+      Actions.CodeCompletePostfixExpression(getCurScope(), LHS);
       ConsumeCodeCompletionToken();
       LHS = ExprError();
       break;
@@ -1099,12 +1095,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
       CommaLocsTy CommaLocs;
 
       Loc = ConsumeParen();
-
-      if (LHS.isInvalid()) {
-        SkipUntil(tok::r_paren);
-        return ExprError();
-      }
-
+      
       if (Tok.is(tok::code_completion)) {
         Actions.CodeCompleteCall(getCurScope(), LHS.get(), 0, 0);
         ConsumeCodeCompletionToken();
@@ -1114,24 +1105,25 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
         if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
                                 LHS.get())) {
           SkipUntil(tok::r_paren);
-          return ExprError();
+          LHS = ExprError();
         }
       }
 
       // Match the ')'.
-      if (Tok.isNot(tok::r_paren)) {
+      if (LHS.isInvalid()) {
+        SkipUntil(tok::r_paren);
+      } else if (Tok.isNot(tok::r_paren)) {
         MatchRHSPunctuation(tok::r_paren, Loc);
-        return ExprError();
-      }
-
-      if (!LHS.isInvalid()) {
-        assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
+        LHS = ExprError();
+      } else {
+        assert((ArgExprs.size() == 0 || 
+                ArgExprs.size()-1 == CommaLocs.size())&&
                "Unexpected number of commas!");
         LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc,
                                     move_arg(ArgExprs), Tok.getLocation());
+        ConsumeParen();
       }
 
-      ConsumeParen();
       break;
     }
     case tok::arrow:
@@ -1183,7 +1175,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
                              /*AllowConstructorName=*/false, 
                              ObjectType,
                              Name))
-        return ExprError();
+        LHS = ExprError();
       
       if (!LHS.isInvalid())
         LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc, 
@@ -1363,21 +1355,18 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
   default: assert(0 && "Not a builtin primary expression!");
   case tok::kw___builtin_va_arg: {
     ExprResult Expr(ParseAssignmentExpression());
-    if (Expr.isInvalid()) {
-      SkipUntil(tok::r_paren);
-      return ExprError();
-    }
 
     if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
-      return ExprError();
+      Expr = ExprError();
 
     TypeResult Ty = ParseTypeName();
 
     if (Tok.isNot(tok::r_paren)) {
       Diag(Tok, diag::err_expected_rparen);
-      return ExprError();
+      Expr = ExprError();
     }
-    if (Ty.isInvalid())
+
+    if (Expr.isInvalid() || Ty.isInvalid())
       Res = ExprError();
     else
       Res = Actions.ActOnVAArg(StartLoc, Expr.take(), Ty.get(), ConsumeParen());
index e305172e5114abd6e777b8e2a9941085ba567270..371921ca11e47066d636f4097149d44a98308d2c 100644 (file)
@@ -2757,9 +2757,11 @@ void Sema::CodeCompleteExpression(Scope *S,
                             Results.data(),Results.size());
 }
 
-void Sema::CodeCompletePostfixExpression(Scope *S, Expr *E) {
-  if (getLangOptions().ObjC1)
-    CodeCompleteObjCInstanceMessage(S, E, 0, 0, false);
+void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
+  if (E.isInvalid())
+    CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
+  else if (getLangOptions().ObjC1)
+    CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
 }
 
 static void AddObjCProperties(ObjCContainerDecl *Container, 
index 5141a533aeaafdeb47161e72cf54a796651c29f7..0b558f81ab722e9bb8e88cf4354139042a6ec5a8 100644 (file)
@@ -11,6 +11,7 @@
   A *a2;
   z = [a2 method:1];
   blah ? blech : [a2 method:1];
+  (a * a2)([a2 method:1]);
 }
 @end
 
@@ -29,3 +30,4 @@
 // RUN: c-index-test -code-completion-at=%s:12:11 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
 // CHECK-CC3: ObjCInstanceMethodDecl:{ResultType void}{TypedText method:}{Placeholder (int)} (17)
 // RUN: c-index-test -code-completion-at=%s:13:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: c-index-test -code-completion-at=%s:14:16 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
index 5730b2af8f3f0811d53726c5af14eba34c08ac6f..f3dadc445040fbfd5622a073322fbf7100a8aae7 100644 (file)
@@ -99,13 +99,15 @@ void test() {
 
 // <rdar://problem/8315440>: Don't crash
 // FIXME: the recovery here is really bad.
-namespace test1 {
-  template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}}
-    A(UndeclaredType n) : X(n) {} // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{undeclared identifier 'n'}} expected-error {{expected ';' at end}} expected-error {{field has incomplete type}}
+namespace test1 { // expected-note{{to match this '{'}}
+  template<typename T> class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} \
+    // expected-note{{template parameter is declared here}}
+    A(UndeclaredType n) : X(n) {} // expected-error{{expected ')'}} expected-note{{to match this '('}} \
+    // expected-error{{use of undeclared identifier 'n'}}
   };
-  template<typename T> class B : public A<T>     {
+  template<typename T> class B : public A<T>     { // expected-error{{declaration of 'T' shadows template parameter}}
     virtual void foo() {}
   };
-  extern template class A<char>; // expected-note {{in instantiation}} expected-note {{not complete}}
-  extern template class B<char>;
-}
+  extern template class A<char>; // expected-error{{expected member name or ';' after declaration specifiers}}
+  extern template class B<char>; // expected-error{{expected member name or ';' after declaration specifiers}}
+} // expected-error{{expected ';' after class}} // expected-error{{expected '}'}}