/// for which we are performing code completion.
bool isCodeCompletionFile(SourceLocation FileLoc) const;
+ /// \brief Determine if we are performing code completion.
+ bool isCodeCompletionEnabled() const { return CodeCompletionFile != 0; }
+
/// \brief Instruct the preprocessor to skip part of the main
/// the main source file.
///
/// If SkipUntil finds the specified token, it returns true, otherwise it
/// returns false.
bool SkipUntil(tok::TokenKind T, bool StopAtSemi = true,
- bool DontConsume = false) {
- return SkipUntil(&T, 1, StopAtSemi, DontConsume);
+ bool DontConsume = false, bool StopAtCodeCompletion = false) {
+ return SkipUntil(&T, 1, StopAtSemi, DontConsume, StopAtCodeCompletion);
}
bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true,
- bool DontConsume = false) {
+ bool DontConsume = false, bool StopAtCodeCompletion = false) {
tok::TokenKind TokArray[] = {T1, T2};
- return SkipUntil(TokArray, 2, StopAtSemi, DontConsume);
+ return SkipUntil(TokArray, 2, StopAtSemi, DontConsume,StopAtCodeCompletion);
}
bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
- bool StopAtSemi = true, bool DontConsume = false);
+ bool StopAtSemi = true, bool DontConsume = false,
+ bool StopAtCodeCompletion = false);
//===--------------------------------------------------------------------===//
// Lexing and parsing of C++ inline methods.
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();
+ // When in code-completion, skip parsing for all function bodies unless
+ // the body contains the code-completion point.
+ if (PP.isCodeCompletionEnabled()) {
+ TentativeParsingAction PA(*this);
+ ConsumeBrace();
+ if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false,
+ /*StopAtCodeCompletion=*/true)) {
+ PA.Commit();
+ return Actions.ActOnFinishFunctionBody(Decl, 0);
+ }
+ PA.Revert();
+ }
+
PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
"parsing function body");
/// If SkipUntil finds the specified token, it returns true, otherwise it
/// returns false.
bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
- bool StopAtSemi, bool DontConsume) {
+ bool StopAtSemi, bool DontConsume,
+ bool StopAtCodeCompletion) {
// We always want this function to skip at least one token if the first token
// isn't T and if not at EOF.
bool isFirstTokenSkipped = true;
return false;
case tok::code_completion:
- ConsumeToken();
+ if (!StopAtCodeCompletion)
+ ConsumeToken();
return false;
case tok::l_paren:
// Recursively skip properly-nested parens.
ConsumeParen();
- SkipUntil(tok::r_paren, false);
+ SkipUntil(tok::r_paren, false, false, StopAtCodeCompletion);
break;
case tok::l_square:
// Recursively skip properly-nested square brackets.
ConsumeBracket();
- SkipUntil(tok::r_square, false);
+ SkipUntil(tok::r_square, false, false, StopAtCodeCompletion);
break;
case tok::l_brace:
// Recursively skip properly-nested braces.
ConsumeBrace();
- SkipUntil(tok::r_brace, false);
+ SkipUntil(tok::r_brace, false, false, StopAtCodeCompletion);
break;
// Okay, we found a ']' or '}' or ')', which we think should be balanced.
+++ /dev/null
-_Complex cd; // CHECK: code-complete-errors.c:1:1: warning: plain '_Complex' requires a type specifier; assuming '_Complex double'
-// CHECK: FIX-IT: Insert " double" at 1:9
-struct s {
- int x, y;; // CHECK: code-complete-errors.c:4:12: warning: extra ';' inside a struct
-}; // CHECK: FIX-IT: Remove [4:12 - 4:13]
-
-struct s s0 = { y: 5 }; // CHECK: code-complete-errors.c:7:20: warning: use of GNU old-style field designator extension
-// CHECK: FIX-IT: Replace [7:17 - 7:19] with ".y = "
-int f(int *ptr1, float *ptr2) {
- return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15:{10:10-10:14}{10:18-10:22}: warning: comparison of distinct pointer types ('int *' and 'float *')
-}
-
-#define expand_to_binary_function(ret, name, parm1, parm2, code) ret name(parm1, parm2) code
-
-expand_to_binary_function(int, g, int *ip, float *fp, {
- // CHECK: code-complete-errors.c:17:12:{17:9-17:24}: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
- if (ip = (float*)fp) ;
-// CHECK: code-complete-errors.c:19:15:{19:12-19:14}{19:18-19:20}: warning: comparison of distinct pointer types ('int *' and 'float *')
- return ip == fp;
- })
-
-void g() { }
-
-// RUN: c-index-test -code-completion-at=%s:21:12 -pedantic %s 2> %t
-// RUN: FileCheck -check-prefix=CHECK %s < %t
-// RUN: c-index-test -code-completion-at=%s:6:2 -remap-file="%s;%S/Inputs/remap-complete-to.c" %s 2> %t.err | FileCheck %s
-// RUN: FileCheck -check-prefix=CHECK-DIAGS %s < %t.err
+// RUN: c-index-test -code-completion-at=%s:6:2 -remap-file="%s;%S/Inputs/remap-complete-to.c" %s | FileCheck %s
// CHECK: FunctionDecl:{ResultType int}{TypedText f0}{LeftParen (}
void f() { }
-
-// CHECK-DIAGS: remap-complete.c:2:19