aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/Action.h8
-rw-r--r--include/clang/Parse/Parser.h21
-rw-r--r--lib/Lex/Lexer.cpp3
-rw-r--r--lib/Parse/ParseDecl.cpp4
-rw-r--r--lib/Parse/ParseDeclCXX.cpp10
-rw-r--r--lib/Parse/ParseExpr.cpp10
-rw-r--r--lib/Parse/ParseExprCXX.cpp6
-rw-r--r--lib/Parse/ParseObjc.cpp48
-rw-r--r--lib/Parse/ParseStmt.cpp4
-rw-r--r--lib/Parse/Parser.cpp26
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp20
-rw-r--r--lib/Sema/SemaCodeComplete.cpp8
-rw-r--r--test/Index/complete-recovery.m21
13 files changed, 121 insertions, 68 deletions
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index f9aef9b0e9..c9bbceef54 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -2649,9 +2649,13 @@ public:
/// \brief Code completion occurs at the beginning of the
/// initialization statement (or expression) in a for loop.
CCC_ForInit,
- /// \brief Code completion ocurs within the condition of an if,
+ /// \brief Code completion occurs within the condition of an if,
/// while, switch, or for statement.
- CCC_Condition
+ CCC_Condition,
+ /// \brief Code completion occurs within the body of a function on a
+ /// recovery path, where we do not have a specific handle on our position
+ /// in the grammar.
+ CCC_RecoveryInFunction
};
/// \brief Code completion for an ordinary name that occurs within the given
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 646f84021d..2e722f7a38 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -234,6 +234,11 @@ private:
assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() &&
!isTokenBrace() &&
"Should consume special tokens with Consume*Token");
+ if (Tok.is(tok::code_completion)) {
+ CodeCompletionRecovery();
+ return ConsumeCodeCompletionToken();
+ }
+
PrevTokLocation = Tok.getLocation();
PP.Lex(Tok);
return PrevTokLocation;
@@ -308,6 +313,22 @@ private:
return PrevTokLocation;
}
+ /// \brief Consume the current code-completion token.
+ ///
+ /// This routine should be called to consume the code-completion token once
+ /// a code-completion action has already been invoked.
+ SourceLocation ConsumeCodeCompletionToken() {
+ assert(Tok.is(tok::code_completion));
+ PrevTokLocation = Tok.getLocation();
+ PP.Lex(Tok);
+ return PrevTokLocation;
+ }
+
+ ///\ brief When we are consuming a code-completion token within having
+ /// matched specific position in the grammar, provide code-completion results
+ /// based on context.
+ void CodeCompletionRecovery();
+
/// GetLookAheadToken - This peeks ahead N tokens and returns that token
/// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
/// returns the token after Tok, etc.
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 0925dd73fe..cd153e147b 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -1359,6 +1359,9 @@ bool Lexer::LexEndOfFile(Token &Result, const char *CurPtr) {
// Only do the eof -> code_completion translation once.
PP->SetCodeCompletionPoint(0, 0, 0);
+
+ // Silence any diagnostics that occur once we hit the code-completion point.
+ PP->getDiagnostics().setSuppressAllDiagnostics(true);
return true;
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index e7650eae84..3e7d4a13c5 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -839,7 +839,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
CCC = Action::CCC_ObjCImplementation;
Actions.CodeCompleteOrdinaryName(CurScope, CCC);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
DS.SetRangeStart(Tok.getLocation());
@@ -1870,7 +1870,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
if (Tok.is(tok::code_completion)) {
// Code completion for an enum name.
Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
llvm::OwningPtr<AttributeList> Attr;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index b276db6bee..479c04c37d 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -50,7 +50,7 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
SourceLocation IdentLoc;
@@ -136,7 +136,7 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteNamespaceAliasDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
CXXScopeSpec SS;
@@ -231,7 +231,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsing(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.is(tok::kw_namespace))
@@ -268,7 +268,7 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteUsingDirective(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
CXXScopeSpec SS;
@@ -610,7 +610,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.is(tok::code_completion)) {
// Code completion for a struct, class, or union name.
Actions.CodeCompleteTag(CurScope, TagType);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
AttributeList *AttrList = 0;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index ed27f3bccb..b036e568f8 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -222,7 +222,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
Parser::OwningExprResult Parser::ParseAssignmentExpression() {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.is(tok::kw_throw))
@@ -906,7 +906,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
case tok::code_completion:
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
NotCastExpr, TypeOfCast);
case tok::l_square:
@@ -975,7 +975,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::r_paren)) {
@@ -1029,7 +1029,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
Actions.CodeCompleteMemberReferenceExpr(CurScope, LHS.get(),
OpLoc, OpKind == tok::arrow);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (MayBePseudoDestructor) {
@@ -1562,7 +1562,7 @@ bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
if (Tok.is(tok::code_completion)) {
if (Completer)
(Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size());
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
OwningExprResult Expr(ParseAssignmentExpression());
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 0a909f626f..46f1d94cf2 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -110,7 +110,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// Code completion for a nested-name-specifier, where the code
// code completion token follows the '::'.
Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
}
@@ -729,7 +729,7 @@ bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
bool ConvertToBoolean) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (!isCXXConditionDeclaration()) {
@@ -1274,7 +1274,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
Actions.CodeCompleteOperatorName(CurScope);
// Consume the operator token.
- ConsumeToken();
+ ConsumeCodeCompletionToken();
// Don't try to parse any further.
return true;
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 9acb4fef80..9cfe73456a 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -32,7 +32,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, false);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
switch (Tok.getObjCKeywordID()) {
@@ -131,7 +131,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
// Code completion after '@interface'.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -149,7 +149,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
IdentifierInfo *categoryId = 0;
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId, nameLoc);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// For ObjC2, the category name is optional (not an error).
@@ -204,7 +204,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
// Code completion of superclass names.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCSuperclass(CurScope, nameId, nameLoc);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -350,7 +350,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
Actions.CodeCompleteOrdinaryName(CurScope,
ObjCImpDecl? Action::CCC_ObjCImplementation
: Action::CCC_ObjCInterface);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// If we don't have an @ directive, parse it as a function definition.
@@ -371,7 +371,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
SourceLocation AtLoc = ConsumeToken(); // the "@"
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
break;
}
@@ -438,7 +438,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// EOF. In the former case, eat the @end. In the later case, emit an error.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtDirective(CurScope, ObjCImpDecl, true);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
} else if (Tok.isObjCAtKeyword(tok::objc_end))
ConsumeToken(); // the "end" identifier
else
@@ -477,7 +477,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
while (1) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyFlags(CurScope, DS);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
const IdentifierInfo *II = Tok.getIdentifierInfo();
@@ -514,7 +514,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, DeclPtrTy ClassDecl,
else
Actions.CodeCompleteObjCPropertyGetter(CurScope, ClassDecl,
Methods, NumMethods);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -782,7 +782,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus,
/*ReturnType=*/0, IDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Parse the return type if present.
@@ -799,7 +799,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCMethodDecl(CurScope, mType == tok::minus,
ReturnType, IDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Now parse the selector.
@@ -945,7 +945,7 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(),
ProtocolIdents.size());
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1026,7 +1026,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtVisibility(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
switch (Tok.getObjCKeywordID()) {
@@ -1046,7 +1046,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteOrdinaryName(CurScope,
Action::CCC_ObjCInstanceVariableList);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
struct ObjCIvarCallback : FieldCallback {
@@ -1117,7 +1117,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCProtocolDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1203,7 +1203,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
// Code completion after '@implementation'.
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCImplementationDecl(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1222,7 +1222,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId, nameLoc);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.is(tok::identifier)) {
@@ -1342,7 +1342,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
while (true) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1361,7 +1361,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId,
ObjCImpDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1400,7 +1400,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
while (true) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCPropertyDefinition(CurScope, ObjCImpDecl);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
if (Tok.isNot(tok::identifier)) {
@@ -1654,7 +1654,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
Parser::OwningStmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteObjCAtStatement(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return StmtError();
}
@@ -1685,7 +1685,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
switch (Tok.getKind()) {
case tok::code_completion:
Actions.CodeCompleteObjCAtExpression(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return ExprError();
case tok::string_literal: // primary-expression: string-literal
@@ -1925,7 +1925,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
else
Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
0, 0);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Parse objc-selector
@@ -1979,7 +1979,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
Actions.CodeCompleteObjCInstanceMessage(CurScope, ReceiverExpr.get(),
KeyIdents.data(),
KeyIdents.size());
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Check for another keyword selector.
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index ea364ee2b6..98c005837e 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -283,7 +283,7 @@ Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
if (Tok.is(tok::code_completion)) {
Actions.CodeCompleteCase(CurScope);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
/// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
@@ -1000,7 +1000,7 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
Actions.CodeCompleteOrdinaryName(CurScope,
C99orCXXorObjC? Action::CCC_ForInit
: Action::CCC_Expression);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
}
// Parse the first part of the for specifier.
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 37475d23fe..8407db1916 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -134,7 +134,7 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
/// returned.
bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
const char *Msg, tok::TokenKind SkipToTok) {
- if (Tok.is(ExpectedTok)) {
+ if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) {
ConsumeAnyToken();
return false;
}
@@ -189,7 +189,11 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
case tok::eof:
// Ran out of tokens.
return false;
-
+
+ case tok::code_completion:
+ ConsumeToken();
+ return false;
+
case tok::l_paren:
// Recursively skip properly-nested parens.
ConsumeParen();
@@ -447,7 +451,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr)
Actions.CodeCompleteOrdinaryName(CurScope,
ObjCImpDecl? Action::CCC_ObjCImplementation
: Action::CCC_Namespace);
- ConsumeToken();
+ ConsumeCodeCompletionToken();
return ParseExternalDeclaration(Attr);
case tok::kw_using:
case tok::kw_namespace:
@@ -1072,6 +1076,22 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
return false;
}
+void Parser::CodeCompletionRecovery() {
+ for (Scope *S = CurScope; S; S = S->getParent()) {
+ if (S->getFlags() & Scope::FnScope) {
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_RecoveryInFunction);
+ return;
+ }
+
+ if (S->getFlags() & Scope::ClassScope) {
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Class);
+ return;
+ }
+ }
+
+ Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Namespace);
+}
+
// Anchor the Parser::FieldCallback vtable to this translation unit.
// We use a spurious method instead of the destructor because
// destroying FieldCallbacks can actually be slightly
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 0ef9a15faa..52562f6b44 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -459,11 +459,6 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
}
}
}
-
- // Once we've printed the code-completion results, suppress remaining
- // diagnostics.
- // FIXME: Move this somewhere else!
- SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
}
void
@@ -478,11 +473,6 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
delete CCS;
}
}
-
- // Once we've printed the code-completion results, suppress remaining
- // diagnostics.
- // FIXME: Move this somewhere else!
- SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
}
void
@@ -599,11 +589,6 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
CCS->Serialize(OS);
delete CCS;
}
-
- // Once we've printed the code-completion results, suppress remaining
- // diagnostics.
- // FIXME: Move this somewhere else!
- SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
}
void
@@ -619,9 +604,4 @@ CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
CCS->Serialize(OS);
delete CCS;
}
-
- // Once we've printed the code-completion results, suppress remaining
- // diagnostics.
- // FIXME: Move this somewhere else!
- SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
}
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 036ae7e869..1685cd572e 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -843,6 +843,7 @@ static void AddFunctionSpecifiers(Action::CodeCompletionContext CCC,
case Action::CCC_Statement:
case Action::CCC_ForInit:
case Action::CCC_Condition:
+ case Action::CCC_RecoveryInFunction:
break;
}
}
@@ -994,6 +995,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC,
AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
break;
+ case Action::CCC_RecoveryInFunction:
case Action::CCC_Statement: {
Results.AddResult(Result("typedef"));
@@ -1925,6 +1927,10 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
case CCC_Condition:
Results.setFilter(&ResultBuilder::IsOrdinaryName);
break;
+
+ case CCC_RecoveryInFunction:
+ // Unfiltered
+ break;
}
CodeCompletionDeclConsumer Consumer(Results, CurContext);
@@ -3079,8 +3085,6 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver,
}
Results.ExitScope();
-
- // This also suppresses remaining diagnostics.
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
diff --git a/test/Index/complete-recovery.m b/test/Index/complete-recovery.m
new file mode 100644
index 0000000000..2ea9fd9f77
--- /dev/null
+++ b/test/Index/complete-recovery.m
@@ -0,0 +1,21 @@
+/* Run lines are at the end, since line/column matter in this test. */
+
+@interface A
+- (void)method:(int)x;
+@end
+
+@implementation A
+- (void)method:(int)x {
+ A *a = [A method:1];
+ blarg * blah = wibble
+}
+@end
+
+// RUN: c-index-test -code-completion-at=%s:9:20 %s 2>%t | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: not grep error %t
+// CHECK-CC1: NotImplemented:{TypedText @encode}{LeftParen (}{Placeholder type-name}{RightParen )}
+// CHECK-CC1: NotImplemented:{TypedText _Bool}
+// CHECK-CC1: VarDecl:{ResultType A *}{TypedText a}
+// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )}
+
+// RUN: c-index-test -code-completion-at=%s:10:24 %s 2>%t | FileCheck -check-prefix=CHECK-CC1 %s