Improve code completion by introducing patterns for the various C and
C++ grammatical constructs that show up in top-level (namespace-level)
declarations, member declarations, template declarations, statements,
expressions, conditions, etc. For example, we now provide a pattern
for

  static_cast<type>(expr)

when we can have an expression, or

  using namespace identifier;

when we can have a using directive.

Also, improves the results of code completion at the beginning of a
top-level declaration. Previously, we would see value names (function
names, global variables, etc.); now we see types, namespace names,
etc., but no values.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93134 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index f429ac9..bc6dda8 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -814,7 +814,14 @@
                                         AccessSpecifier AS,
                                         DeclSpecContext DSContext) {
   if (Tok.is(tok::code_completion)) {
-    Actions.CodeCompleteOrdinaryName(CurScope);
+    Action::CodeCompletionContext CCC = Action::CCC_Namespace;
+    if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
+      CCC = DSContext == DSC_class? Action::CCC_MemberTemplate 
+                                  : Action::CCC_Template;
+    else if (DSContext == DSC_class)
+      CCC = Action::CCC_Class;
+
+    Actions.CodeCompleteOrdinaryName(CurScope, CCC);
     ConsumeToken();
   }
   
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 4d6988d..669575c 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -200,11 +200,6 @@
 ///         expression ',' assignment-expression
 ///
 Parser::OwningExprResult Parser::ParseExpression() {
-  if (Tok.is(tok::code_completion)) {
-    Actions.CodeCompleteOrdinaryName(CurScope);
-    ConsumeToken();
-  }
-
   OwningExprResult LHS(ParseAssignmentExpression());
   if (LHS.isInvalid()) return move(LHS);
 
@@ -248,6 +243,11 @@
 /// ParseAssignmentExpression - Parse an expr that doesn't include commas.
 ///
 Parser::OwningExprResult Parser::ParseAssignmentExpression() {
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
+    ConsumeToken();
+  }
+
   if (Tok.is(tok::kw_throw))
     return ParseThrowExpression();
 
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index abd26d7..3efa6f0 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -585,6 +585,11 @@
 /// \returns true if there was a parsing, false otherwise.
 bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
                                DeclPtrTy &DeclResult) {
+  if (Tok.is(tok::code_completion)) {
+    Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
+    ConsumeToken();
+  }
+
   if (!isCXXConditionDeclaration()) {
     ExprResult = ParseExpression(); // expression
     DeclResult = DeclPtrTy();
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 277cc91..21e960a 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -95,7 +95,7 @@
     }
 
   case tok::code_completion:
-    Actions.CodeCompleteOrdinaryName(CurScope);
+    Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Statement);
     ConsumeToken();
     return ParseStatementOrDeclaration(OnlyStatement);
       
@@ -955,7 +955,9 @@
   DeclPtrTy SecondVar;
   
   if (Tok.is(tok::code_completion)) {
-    Actions.CodeCompleteOrdinaryName(CurScope);
+    Actions.CodeCompleteOrdinaryName(CurScope, 
+                                     C99orCXXorObjC? Action::CCC_ForInit
+                                                   : Action::CCC_Expression);
     ConsumeToken();
   }
   
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 52c0153..bf0c7b2 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -455,7 +455,7 @@
     SingleDecl = ParseObjCMethodDefinition();
     break;
   case tok::code_completion:
-    Actions.CodeCompleteOrdinaryName(CurScope);
+    Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Namespace);
     ConsumeToken();
     return ParseExternalDeclaration(Attr);
   case tok::kw_using:
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index b9b85df..0a00b42 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -85,6 +85,26 @@
   case CK_Comma:
     this->Text = ", ";
     break;
+
+  case CK_Colon:
+    this->Text = ": ";
+    break;
+
+  case CK_SemiColon:
+    this->Text = ";";
+    break;
+
+  case CK_Equal:
+    this->Text = " = ";
+    break;
+
+  case CK_HorizontalSpace:
+    this->Text = " ";
+    break;
+
+  case CK_VerticalSpace:
+    this->Text = "\n";
+    break;
   }
 }
 
@@ -140,6 +160,11 @@
   case CK_LeftAngle:
   case CK_RightAngle:
   case CK_Comma:
+  case CK_Colon:
+  case CK_SemiColon:
+  case CK_Equal:
+  case CK_HorizontalSpace:
+  case CK_VerticalSpace:
     return Chunk(Kind, Text);
       
   case CK_Optional: {
@@ -177,6 +202,11 @@
   case CK_LeftAngle:
   case CK_RightAngle:
   case CK_Comma:
+  case CK_Colon:
+  case CK_SemiColon:
+  case CK_Equal:
+  case CK_HorizontalSpace:
+  case CK_VerticalSpace:
     break;
   }
 }
@@ -271,6 +301,11 @@
     case CK_LeftAngle:
     case CK_RightAngle:
     case CK_Comma:
+    case CK_Colon:
+    case CK_SemiColon:
+    case CK_Equal:
+    case CK_HorizontalSpace:
+    case CK_VerticalSpace:
       break;
     }
   }
@@ -326,6 +361,11 @@
     case CK_LeftAngle:
     case CK_RightAngle:
     case CK_Comma:
+    case CK_Colon:
+    case CK_SemiColon:
+    case CK_Equal:
+    case CK_HorizontalSpace:
+    case CK_VerticalSpace:
       Result->AddChunk(Chunk(Kind));
       break;      
     }
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index f487fbe..ec08658 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3806,7 +3806,8 @@
 
   /// \name Code completion
   //@{
-  virtual void CodeCompleteOrdinaryName(Scope *S);
+  virtual void CodeCompleteOrdinaryName(Scope *S, 
+                                     CodeCompletionContext CompletionContext);
   virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
                                                SourceLocation OpLoc,
                                                bool IsArrow);
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index ef82a94..582b369 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -158,6 +158,7 @@
     /// 
     //@{
     bool IsOrdinaryName(NamedDecl *ND) const;
+    bool IsOrdinaryNonValueName(NamedDecl *ND) const;
     bool IsNestedNameSpecifier(NamedDecl *ND) const;
     bool IsEnum(NamedDecl *ND) const;
     bool IsClassOrStruct(NamedDecl *ND) const;
@@ -517,6 +518,17 @@
   return ND->getIdentifierNamespace() & IDNS;
 }
 
+/// \brief Determines whether this given declaration will be found by
+/// ordinary name lookup.
+bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
+  unsigned IDNS = Decl::IDNS_Ordinary;
+  if (SemaRef.getLangOptions().CPlusPlus)
+    IDNS |= Decl::IDNS_Tag;
+  
+  return (ND->getIdentifierNamespace() & IDNS) && 
+    !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND);
+}
+
 /// \brief Determines whether the given declaration is suitable as the 
 /// start of a C++ nested-name-specifier, e.g., a class or namespace.
 bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
@@ -797,22 +809,32 @@
   Results.MaybeAddResult(Result("enum", Rank));
   Results.MaybeAddResult(Result("struct", Rank));
   Results.MaybeAddResult(Result("union", Rank));
-  
+  Results.MaybeAddResult(Result("const", Rank));
+  Results.MaybeAddResult(Result("volatile", Rank));
+
   if (LangOpts.C99) {
     // C99-specific
     Results.MaybeAddResult(Result("_Complex", Rank));
     Results.MaybeAddResult(Result("_Imaginary", Rank));
     Results.MaybeAddResult(Result("_Bool", Rank));
+    Results.MaybeAddResult(Result("restrict", Rank));
   }
   
   if (LangOpts.CPlusPlus) {
     // C++-specific
     Results.MaybeAddResult(Result("bool", Rank));
     Results.MaybeAddResult(Result("class", Rank));
-    Results.MaybeAddResult(Result("typename", Rank));
     Results.MaybeAddResult(Result("wchar_t", Rank));
     
+    // typename qualified-id
+    CodeCompletionString *Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("typename");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("qualified-id");
+    Results.MaybeAddResult(Result(Pattern, Rank));
+
     if (LangOpts.CPlusPlus0x) {
+      Results.MaybeAddResult(Result("auto", Rank));
       Results.MaybeAddResult(Result("char16_t", Rank));
       Results.MaybeAddResult(Result("char32_t", Rank));
       Results.MaybeAddResult(Result("decltype", Rank));
@@ -825,10 +847,487 @@
     //    Results.MaybeAddResult(Result("_Decimal32", Rank));
     //    Results.MaybeAddResult(Result("_Decimal64", Rank));
     //    Results.MaybeAddResult(Result("_Decimal128", Rank));
-    Results.MaybeAddResult(Result("typeof", Rank));
+    
+    CodeCompletionString *Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("typeof");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    Pattern->AddPlaceholderChunk("expression-or-type");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Results.MaybeAddResult(Result(Pattern, Rank));
   }
 }
 
+static void AddStorageSpecifiers(Action::CodeCompletionContext CCC,
+                                 const LangOptions &LangOpts, 
+                                 unsigned Rank, 
+                                 ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  // Note: we don't suggest either "auto" or "register", because both
+  // are pointless as storage specifiers. Elsewhere, we suggest "auto"
+  // in C++0x as a type specifier.
+  Results.MaybeAddResult(Result("extern", Rank));
+  Results.MaybeAddResult(Result("static", Rank));
+}
+
+static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC,
+                                  const LangOptions &LangOpts, 
+                                  unsigned Rank, 
+                                  ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  switch (CCC) {
+  case Action::CCC_Class:
+  case Action::CCC_MemberTemplate:
+    if (LangOpts.CPlusPlus) {
+      Results.MaybeAddResult(Result("explicit", Rank));
+      Results.MaybeAddResult(Result("friend", Rank));
+      Results.MaybeAddResult(Result("mutable", Rank));
+      Results.MaybeAddResult(Result("virtual", Rank));
+    }    
+    // Fall through
+
+  case Action::CCC_Namespace:
+  case Action::CCC_Template:
+    if (LangOpts.CPlusPlus || LangOpts.C99)
+      Results.MaybeAddResult(Result("inline", Rank));
+    break;
+
+  case Action::CCC_Expression:
+  case Action::CCC_Statement:
+  case Action::CCC_ForInit:
+  case Action::CCC_Condition:
+    break;
+  }
+}
+
+/// \brief Add language constructs that show up for "ordinary" names.
+static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
+                                   Scope *S,
+                                   Sema &SemaRef,
+                                   unsigned Rank, 
+                                   ResultBuilder &Results) {
+  typedef CodeCompleteConsumer::Result Result;
+  switch (CCC) {
+  case Action::CCC_Namespace:
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // namespace <identifier> { }
+      CodeCompletionString *Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("namespace");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+      Pattern->AddPlaceholderChunk("declarations");
+      Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+
+      // namespace identifier = identifier ;
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("namespace");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_Equal);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+
+      // Using directives
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("using");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddTextChunk("namespace");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("identifier");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+
+      // asm(string-literal)      
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("asm");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("string-literal");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+
+      // Explicit template instantiation
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("template");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("declaration");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+    }
+    // Fall through
+
+  case Action::CCC_Class:
+    Results.MaybeAddResult(Result("typedef", Rank));
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // Using declaration
+      CodeCompletionString *Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("using");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("qualified-id");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+      
+      // using typename qualified-id; (only in a dependent context)
+      if (SemaRef.CurContext->isDependentContext()) {
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("using");
+        Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Pattern->AddTextChunk("typename");
+        Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+        Pattern->AddPlaceholderChunk("qualified-id");
+        Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+        Results.MaybeAddResult(Result(Pattern, Rank));
+      }
+
+      if (CCC == Action::CCC_Class) {
+        // public:
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("public");
+        Pattern->AddChunk(CodeCompletionString::CK_Colon);
+        Results.MaybeAddResult(Result(Pattern, Rank));
+
+        // protected:
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("protected");
+        Pattern->AddChunk(CodeCompletionString::CK_Colon);
+        Results.MaybeAddResult(Result(Pattern, Rank));
+
+        // private:
+        Pattern = new CodeCompletionString;
+        Pattern->AddTypedTextChunk("private");
+        Pattern->AddChunk(CodeCompletionString::CK_Colon);
+        Results.MaybeAddResult(Result(Pattern, Rank));
+      }
+    }
+    // Fall through
+
+  case Action::CCC_Template:
+  case Action::CCC_MemberTemplate:
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // template < parameters >
+      CodeCompletionString *Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("template");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("parameters");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+    }
+
+    AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Rank, Results);
+    AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Rank, Results);
+    break;
+
+  case Action::CCC_Statement: {
+    Results.MaybeAddResult(Result("typedef", Rank));
+
+    CodeCompletionString *Pattern = 0;
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("try");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+      Pattern->AddPlaceholderChunk("statements");
+      Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+      Pattern->AddTextChunk("catch");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("declaration");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+      Pattern->AddPlaceholderChunk("statements");
+      Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+    }
+
+    // if (condition) { statements }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("if");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus)
+      Pattern->AddPlaceholderChunk("condition");
+    else
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+
+    // switch (condition) { }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("switch");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus)
+      Pattern->AddPlaceholderChunk("condition");
+    else
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+
+    // Switch-specific statements.
+    if (!SemaRef.getSwitchStack().empty()) {
+      // case expression:
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("case");
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_Colon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+
+      // default:
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("default");
+      Pattern->AddChunk(CodeCompletionString::CK_Colon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+    }
+
+    /// while (condition) { statements }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("while");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus)
+      Pattern->AddPlaceholderChunk("condition");
+    else
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+
+    // do { statements } while ( expression );
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("do");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Pattern->AddTextChunk("while");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+
+    // for ( for-init-statement ; condition ; expression ) { statements }
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("for");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
+      Pattern->AddPlaceholderChunk("init-statement");
+    else
+      Pattern->AddPlaceholderChunk("init-expression");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Pattern->AddPlaceholderChunk("condition");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Pattern->AddPlaceholderChunk("inc-expression");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Pattern->AddChunk(CodeCompletionString::CK_LeftBrace);
+    Pattern->AddPlaceholderChunk("statements");
+    Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace);
+    Pattern->AddChunk(CodeCompletionString::CK_RightBrace);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+    
+    if (S->getContinueParent()) {
+      // continue ;
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("continue");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+    }
+
+    if (S->getBreakParent()) {
+      // break ;
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("break");
+      Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+      Results.MaybeAddResult(Result(Pattern, Rank));
+    }
+
+    // "return expression ;" or "return ;", depending on whether we
+    // know the function is void or not.
+    bool isVoid = false;
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
+      isVoid = Function->getResultType()->isVoidType();
+    else if (ObjCMethodDecl *Method
+                                 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
+      isVoid = Method->getResultType()->isVoidType();
+    else if (SemaRef.CurBlock && !SemaRef.CurBlock->ReturnType.isNull())
+      isVoid = SemaRef.CurBlock->ReturnType->isVoidType();
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("return");
+    if (!isVoid)
+      Pattern->AddPlaceholderChunk("expression");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+
+    // goto identifier ;
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("goto");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("identifier");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.MaybeAddResult(Result(Pattern, Rank));    
+
+    // Using directives
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("using");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddTextChunk("namespace");
+    Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+    Pattern->AddPlaceholderChunk("identifier");
+    Pattern->AddChunk(CodeCompletionString::CK_SemiColon);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+  }
+
+  // Fall through (for statement expressions).
+  case Action::CCC_ForInit:
+  case Action::CCC_Condition:
+    AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Rank, Results);
+    // Fall through: conditions and statements can have expressions.
+
+  case Action::CCC_Expression: {
+    CodeCompletionString *Pattern = 0;
+    if (SemaRef.getLangOptions().CPlusPlus) {
+      // 'this', if we're in a non-static member function.
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext))
+        if (!Method->isStatic())
+          Results.MaybeAddResult(Result("this", Rank));
+      
+      // true, false
+      Results.MaybeAddResult(Result("true", Rank));
+      Results.MaybeAddResult(Result("false", Rank));
+
+      // dynamic_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("dynamic_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+      
+      // static_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("static_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+
+      // reinterpret_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("reinterpret_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+
+      // const_cast < type-id > ( expression )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("const_cast");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftAngle);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_RightAngle);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+
+      // typeid ( expression-or-type )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("typeid");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expression-or-type");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+
+      // new T ( ... )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("new");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expressions");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+
+      // new T [ ] ( ... )
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("new");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("type-id");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
+      Pattern->AddPlaceholderChunk("size");
+      Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
+      Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+      Pattern->AddPlaceholderChunk("expressions");
+      Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+
+      // delete expression
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("delete");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("expression");
+      Results.MaybeAddResult(Result(Pattern, Rank));      
+
+      // delete [] expression
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("delete");
+      Pattern->AddChunk(CodeCompletionString::CK_LeftBracket);
+      Pattern->AddChunk(CodeCompletionString::CK_RightBracket);
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("expression");
+      Results.MaybeAddResult(Result(Pattern, Rank));
+
+      // throw expression
+      Pattern = new CodeCompletionString;
+      Pattern->AddTypedTextChunk("throw");
+      Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+      Pattern->AddPlaceholderChunk("expression");
+      Results.MaybeAddResult(Result(Pattern, Rank));
+    }
+
+    if (SemaRef.getLangOptions().ObjC1) {
+      // Add "super", if we're in an Objective-C class with a superclass.
+      if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
+        if (Method->getClassInterface()->getSuperClass())
+          Results.MaybeAddResult(Result("super", Rank));
+    }
+
+    // sizeof expression
+    Pattern = new CodeCompletionString;
+    Pattern->AddTypedTextChunk("sizeof");
+    Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+    Pattern->AddPlaceholderChunk("expression-or-type");
+    Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+    Results.MaybeAddResult(Result(Pattern, Rank));
+    break;
+  }
+  }
+
+  AddTypeSpecifierResults(SemaRef.getLangOptions(), Rank, Results);
+
+  if (SemaRef.getLangOptions().CPlusPlus)
+    Results.MaybeAddResult(Result("operator", Rank));
+}
+
 /// \brief If the given declaration has an associated type, add it as a result 
 /// type chunk.
 static void AddResultTypeChunk(ASTContext &Context,
@@ -1422,22 +1921,35 @@
     Results[I].Destroy();
 }
 
-void Sema::CodeCompleteOrdinaryName(Scope *S) {
+void Sema::CodeCompleteOrdinaryName(Scope *S, 
+                                    CodeCompletionContext CompletionContext) {
   typedef CodeCompleteConsumer::Result Result;
-  ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName);
+  ResultBuilder Results(*this);
+
+  // Determine how to filter results, e.g., so that the names of
+  // values (functions, enumerators, function templates, etc.) are
+  // only allowed where we can have an expression.
+  switch (CompletionContext) {
+  case CCC_Namespace:
+  case CCC_Class:
+  case CCC_Template:
+  case CCC_MemberTemplate:
+    Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
+    break;
+
+  case CCC_Expression:
+  case CCC_Statement:
+  case CCC_ForInit:
+  case CCC_Condition:
+    Results.setFilter(&ResultBuilder::IsOrdinaryName);
+    break;
+  }
+
   unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), 
                                            0, CurContext, Results);
 
   Results.EnterNewScope();
-  AddTypeSpecifierResults(getLangOptions(), NextRank, Results);
-  
-  if (getLangOptions().ObjC1) {
-    // Add the "super" keyword, if appropriate.
-    if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
-      if (Method->getClassInterface()->getSuperClass())
-        Results.MaybeAddResult(Result("super", NextRank));
-  }
-
+  AddOrdinaryNameResults(CompletionContext, S, *this, NextRank, Results);
   Results.ExitScope();
 
   if (CodeCompleter->includeMacros())
@@ -1561,9 +2073,6 @@
                                               E = ObjCPtr->qual_end();
          I != E; ++I)
       AddObjCProperties(*I, true, CurContext, Results);
-    
-    // FIXME: We could (should?) also look for "implicit" properties, identified
-    // only by the presence of nullary and unary selectors.
   } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
              (!IsArrow && BaseType->isObjCInterfaceType())) {
     // Objective-C instance variable access.
@@ -1746,7 +2255,7 @@
   // Ignore type-dependent call expressions entirely.
   if (Fn->isTypeDependent() || 
       Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
-    CodeCompleteOrdinaryName(S);
+    CodeCompleteOrdinaryName(S, CCC_Expression);
     return;
   }
 
@@ -1784,7 +2293,7 @@
   }
 
   if (Results.empty())
-    CodeCompleteOrdinaryName(S);
+    CodeCompleteOrdinaryName(S, CCC_Expression);
   else
     CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), 
                                              Results.size());
@@ -1968,7 +2477,7 @@
     // Since we have an interface or protocol, we can end it.
     Results.MaybeAddResult(Result("end", 0));
 
-    if (LangOpts.ObjC2) {
+    if (getLangOptions().ObjC2) {
       // @property
       Results.MaybeAddResult(Result("property", 0));
     }