Skip to content

Commit 4974d75

Browse files
committed
[CodeComplete] Fill preferred type on binary expressions
Reviewers: kadircet Reviewed By: kadircet Subscribers: arphaman, cfe-commits Differential Revision: https://reviews.llvm.org/D55648 llvm-svn: 349053
1 parent b0b2f15 commit 4974d75

File tree

5 files changed

+300
-47
lines changed

5 files changed

+300
-47
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10350,7 +10350,7 @@ class Sema {
1035010350
void CodeCompleteInitializer(Scope *S, Decl *D);
1035110351
void CodeCompleteReturn(Scope *S);
1035210352
void CodeCompleteAfterIf(Scope *S);
10353-
void CodeCompleteAssignmentRHS(Scope *S, Expr *LHS);
10353+
void CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op);
1035410354

1035510355
void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
1035610356
bool EnteringContext, QualType BaseType);

clang/lib/Parse/ParseExpr.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
393393
}
394394
}
395395

396-
// Code completion for the right-hand side of an assignment expression
397-
// goes through a special hook that takes the left-hand side into account.
398-
if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) {
399-
Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get());
396+
// Code completion for the right-hand side of a binary expression goes
397+
// through a special hook that takes the left-hand side into account.
398+
if (Tok.is(tok::code_completion)) {
399+
Actions.CodeCompleteBinaryRHS(getCurScope(), LHS.get(),
400+
OpToken.getKind());
400401
cutOffParsing();
401402
return ExprError();
402403
}

clang/lib/Sema/SemaCodeComplete.cpp

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4878,9 +4878,86 @@ void Sema::CodeCompleteAfterIf(Scope *S) {
48784878
Results.data(), Results.size());
48794879
}
48804880

4881-
void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
4882-
if (LHS)
4883-
CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4881+
static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
4882+
tok::TokenKind Op) {
4883+
if (!LHS)
4884+
return QualType();
4885+
4886+
QualType LHSType = LHS->getType();
4887+
if (LHSType->isPointerType()) {
4888+
if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
4889+
return S.getASTContext().getPointerDiffType();
4890+
// Pointer difference is more common than subtracting an int from a pointer.
4891+
if (Op == tok::minus)
4892+
return LHSType;
4893+
}
4894+
4895+
switch (Op) {
4896+
// No way to infer the type of RHS from LHS.
4897+
case tok::comma:
4898+
return QualType();
4899+
// Prefer the type of the left operand for all of these.
4900+
// Arithmetic operations.
4901+
case tok::plus:
4902+
case tok::plusequal:
4903+
case tok::minus:
4904+
case tok::minusequal:
4905+
case tok::percent:
4906+
case tok::percentequal:
4907+
case tok::slash:
4908+
case tok::slashequal:
4909+
case tok::star:
4910+
case tok::starequal:
4911+
// Assignment.
4912+
case tok::equal:
4913+
// Comparison operators.
4914+
case tok::equalequal:
4915+
case tok::exclaimequal:
4916+
case tok::less:
4917+
case tok::lessequal:
4918+
case tok::greater:
4919+
case tok::greaterequal:
4920+
case tok::spaceship:
4921+
return LHS->getType();
4922+
// Binary shifts are often overloaded, so don't try to guess those.
4923+
case tok::greatergreater:
4924+
case tok::greatergreaterequal:
4925+
case tok::lessless:
4926+
case tok::lesslessequal:
4927+
if (LHSType->isIntegralOrEnumerationType())
4928+
return S.getASTContext().IntTy;
4929+
return QualType();
4930+
// Logical operators, assume we want bool.
4931+
case tok::ampamp:
4932+
case tok::pipepipe:
4933+
case tok::caretcaret:
4934+
return S.getASTContext().BoolTy;
4935+
// Operators often used for bit manipulation are typically used with the type
4936+
// of the left argument.
4937+
case tok::pipe:
4938+
case tok::pipeequal:
4939+
case tok::caret:
4940+
case tok::caretequal:
4941+
case tok::amp:
4942+
case tok::ampequal:
4943+
if (LHSType->isIntegralOrEnumerationType())
4944+
return LHSType;
4945+
return QualType();
4946+
// RHS should be a pointer to a member of the 'LHS' type, but we can't give
4947+
// any particular type here.
4948+
case tok::periodstar:
4949+
case tok::arrowstar:
4950+
return QualType();
4951+
default:
4952+
assert(false && "unhandled binary op");
4953+
return QualType();
4954+
}
4955+
}
4956+
4957+
void Sema::CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op) {
4958+
auto PreferredType = getPreferredTypeOfBinaryRHS(*this, LHS, Op);
4959+
if (!PreferredType.isNull())
4960+
CodeCompleteExpression(S, PreferredType);
48844961
else
48854962
CodeCompleteOrdinaryName(S, PCC_Expression);
48864963
}

clang/test/Index/complete-exprs.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,11 @@ void f5(float f) {
3333
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (8)
3434
// CHECK-CC1: NotImplemented:{ResultType size_t}{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (40)
3535
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
36-
// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
37-
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
38-
// CHECK-CC3: macro definition:{TypedText __VERSION__} (70)
39-
// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
40-
// CHECK-CC3-NOT: NotImplemented:{TypedText float}
41-
// CHECK-CC3: ParmDecl:{ResultType int}{TypedText j} (34)
42-
// CHECK-CC3: NotImplemented:{ResultType size_t}{TypedText sizeof}{LeftParen (}{Placeholder expressio
36+
// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
37+
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
4338

44-
// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
45-
// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
39+
// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
40+
// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
4641
// RUN: c-index-test -code-completion-at=%s:7:2 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s
4742
// CHECK-CC2: macro definition:{TypedText __VERSION__} (70)
4843
// CHECK-CC2: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)

0 commit comments

Comments
 (0)