typedef SmallVector<SourceLocation, 20> CommaLocsTy;
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
- bool ParseExpressionList(
- SmallVectorImpl<Expr *> &Exprs,
- SmallVectorImpl<SourceLocation> &CommaLocs,
- llvm::function_ref<void()> Completer = llvm::function_ref<void()>());
+ bool ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
+ SmallVectorImpl<SourceLocation> &CommaLocs,
+ llvm::function_ref<void()> ExpressionStarts =
+ llvm::function_ref<void()>());
/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
/// used for misc language extensions.
void enterCondition(Sema &S, SourceLocation Tok);
void enterReturn(Sema &S, SourceLocation Tok);
void enterVariableInit(SourceLocation Tok, Decl *D);
+ /// Computing a type for the function argument may require running
+ /// overloading, so we postpone its computation until it is actually needed.
+ ///
+ /// Clients should be very careful when using this funciton, as it stores a
+ /// function_ref, clients should make sure all calls to get() with the same
+ /// location happen while function_ref is alive.
+ void enterFunctionArgument(SourceLocation Tok,
+ llvm::function_ref<QualType()> ComputeType);
void enterParenExpr(SourceLocation Tok, SourceLocation LParLoc);
void enterUnary(Sema &S, SourceLocation Tok, tok::TokenKind OpKind,
void enterTypeCast(SourceLocation Tok, QualType CastType);
QualType get(SourceLocation Tok) const {
- if (Tok == ExpectedLoc)
+ if (Tok != ExpectedLoc)
+ return QualType();
+ if (!Type.isNull())
return Type;
+ if (ComputeType)
+ return ComputeType();
return QualType();
}
SourceLocation ExpectedLoc;
/// Expected type for a token starting at ExpectedLoc.
QualType Type;
+ /// A function to compute expected type at ExpectedLoc. It is only considered
+ /// if Type is null.
+ llvm::function_ref<QualType()> ComputeType;
};
/// Sema - This implements semantic analysis and AST building for C.
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
-
+
OMPClause *ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
SourceLocation StartLoc, SourceLocation LParenLoc,
/// Called on well-formed 'unified_address' clause.
OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
SourceLocation EndLoc);
-
+
/// Called on well-formed 'reverse_offload' clause.
OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
SourceLocation EndLoc);
InitializerScopeRAII InitScope(*this, D, ThisDecl);
- llvm::function_ref<void()> ExprListCompleter;
auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);
- auto ConstructorCompleter = [&, ThisVarDecl] {
+ auto RunSignatureHelp = [&]() {
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
ThisDecl->getLocation(), Exprs, T.getOpenLocation());
CalledSignatureHelp = true;
- Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ return PreferredType;
};
+ auto SetPreferredType = [&] {
+ PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);
+ };
+
+ llvm::function_ref<void()> ExpressionStarts;
if (ThisVarDecl) {
// ParseExpressionList can sometimes succeed even when ThisDecl is not
// VarDecl. This is an error and it is reported in a call to
// Actions.ActOnInitializerError(). However, we call
- // ProduceConstructorSignatureHelp only on VarDecls, falling back to
- // default completer in other cases.
- ExprListCompleter = ConstructorCompleter;
+ // ProduceConstructorSignatureHelp only on VarDecls.
+ ExpressionStarts = SetPreferredType;
}
-
- if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) {
+ if (ParseExpressionList(Exprs, CommaLocs, ExpressionStarts)) {
if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {
Actions.ProduceConstructorSignatureHelp(
getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(),
// Parse the optional expression-list.
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
+ auto RunSignatureHelp = [&] {
+ QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ T.getOpenLocation());
+ CalledSignatureHelp = true;
+ return PreferredType;
+ };
if (Tok.isNot(tok::r_paren) &&
ParseExpressionList(ArgExprs, CommaLocs, [&] {
- QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
- getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
- T.getOpenLocation());
- CalledSignatureHelp = true;
- Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ PreferredType.enterFunctionArgument(Tok.getLocation(),
+ RunSignatureHelp);
})) {
- if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
- Actions.ProduceCtorInitMemberSignatureHelp(
- getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
- T.getOpenLocation());
- CalledSignatureHelp = true;
- }
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+ RunSignatureHelp();
SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
-
- if (Tok.is(tok::code_completion)) {
+ auto RunSignatureHelp = [&]() -> QualType {
QualType PreferredType = Actions.ProduceCallSignatureHelp(
- getCurScope(), LHS.get(), None, PT.getOpenLocation());
+ getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation());
CalledSignatureHelp = true;
- Actions.CodeCompleteExpression(getCurScope(), PreferredType);
- cutOffParsing();
- return ExprError();
- }
-
+ return PreferredType;
+ };
if (OpKind == tok::l_paren || !LHS.isInvalid()) {
if (Tok.isNot(tok::r_paren)) {
if (ParseExpressionList(ArgExprs, CommaLocs, [&] {
- QualType PreferredType = Actions.ProduceCallSignatureHelp(
- getCurScope(), LHS.get(), ArgExprs, PT.getOpenLocation());
- CalledSignatureHelp = true;
- Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ PreferredType.enterFunctionArgument(Tok.getLocation(),
+ RunSignatureHelp);
})) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
// If we got an error when parsing expression list, we don't call
// the CodeCompleteCall handler inside the parser. So call it here
// to make sure we get overload suggestions even when we are in the
// middle of a parameter.
- if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
- Actions.ProduceCallSignatureHelp(getCurScope(), LHS.get(),
- ArgExprs, PT.getOpenLocation());
- CalledSignatureHelp = true;
- }
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+ RunSignatureHelp();
LHS = ExprError();
} else if (LHS.isInvalid()) {
for (auto &E : ArgExprs)
/// \endverbatim
bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
SmallVectorImpl<SourceLocation> &CommaLocs,
- llvm::function_ref<void()> Completer) {
+ llvm::function_ref<void()> ExpressionStarts) {
bool SawError = false;
while (1) {
- if (Tok.is(tok::code_completion)) {
- if (Completer)
- Completer();
- else
- Actions.CodeCompleteExpression(getCurScope(),
- PreferredType.get(Tok.getLocation()));
- cutOffParsing();
- return true;
- }
+ if (ExpressionStarts)
+ ExpressionStarts();
ExprResult Expr;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
ExprVector Exprs;
CommaLocsTy CommaLocs;
+ auto RunSignatureHelp = [&]() {
+ QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+ DS.getEndLoc(), Exprs, T.getOpenLocation());
+ CalledSignatureHelp = true;
+ return PreferredType;
+ };
+
if (Tok.isNot(tok::r_paren)) {
if (ParseExpressionList(Exprs, CommaLocs, [&] {
- QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
- getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
- DS.getEndLoc(), Exprs, T.getOpenLocation());
- CalledSignatureHelp = true;
- Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ PreferredType.enterFunctionArgument(Tok.getLocation(),
+ RunSignatureHelp);
})) {
- if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
- Actions.ProduceConstructorSignatureHelp(
- getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
- DS.getEndLoc(), Exprs, T.getOpenLocation());
- CalledSignatureHelp = true;
- }
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+ RunSignatureHelp();
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
ConstructorLParen = T.getOpenLocation();
if (Tok.isNot(tok::r_paren)) {
CommaLocsTy CommaLocs;
+ auto RunSignatureHelp = [&]() {
+ ParsedType TypeRep =
+ Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
+ QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
+ DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
+ CalledSignatureHelp = true;
+ return PreferredType;
+ };
if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] {
- ParsedType TypeRep =
- Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
- QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
- getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
- DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
- CalledSignatureHelp = true;
- Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ PreferredType.enterFunctionArgument(Tok.getLocation(),
+ RunSignatureHelp);
})) {
- if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
- ParsedType TypeRep =
- Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get();
- Actions.ProduceConstructorSignatureHelp(
- getCurScope(), TypeRep.get()->getCanonicalTypeInternal(),
- DeclaratorInfo.getEndLoc(), ConstructorArgs, ConstructorLParen);
- CalledSignatureHelp = true;
- }
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+ RunSignatureHelp();
SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch);
return ExprError();
}
CommaLocsTy CommaLocs;
SourceLocation LParLoc = T.getOpenLocation();
- if (ParseExpressionList(
- Exprs, CommaLocs, [this, OmpPrivParm, LParLoc, &Exprs] {
- QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
- getCurScope(),
- OmpPrivParm->getType()->getCanonicalTypeInternal(),
- OmpPrivParm->getLocation(), Exprs, LParLoc);
- CalledSignatureHelp = true;
- Actions.CodeCompleteExpression(getCurScope(), PreferredType);
- })) {
- if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
- Actions.ProduceConstructorSignatureHelp(
- getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
- OmpPrivParm->getLocation(), Exprs, LParLoc);
- CalledSignatureHelp = true;
- }
+ auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
+ QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
+ getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
+ OmpPrivParm->getLocation(), Exprs, LParLoc);
+ CalledSignatureHelp = true;
+ return PreferredType;
+ };
+ if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ PreferredType.enterFunctionArgument(Tok.getLocation(),
+ RunSignatureHelp);
+ })) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
+ RunSignatureHelp();
Actions.ActOnInitializerError(OmpPrivParm);
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
} else {
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
FirstClauses(OMPC_unknown + 1);
if (Tok.is(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::err_omp_expected_clause)
+ Diag(Tok, diag::err_omp_expected_clause)
<< getOpenMPDirectiveName(OMPD_requires);
break;
}
/// Parse map-type in map clause.
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
-/// where, map-type ::= to | from | tofrom | alloc | release | delete
+/// where, map-type ::= to | from | tofrom | alloc | release | delete
static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
Token Tok = P.getCurToken();
if (Tok.is(tok::colon)) {
void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
if (isa<BlockDecl>(S.CurContext)) {
if (sema::BlockScopeInfo *BSI = S.getCurBlock()) {
+ ComputeType = nullptr;
Type = BSI->ReturnType;
ExpectedLoc = Tok;
}
} else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) {
+ ComputeType = nullptr;
Type = Function->getReturnType();
ExpectedLoc = Tok;
} else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) {
+ ComputeType = nullptr;
Type = Method->getReturnType();
ExpectedLoc = Tok;
}
void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) {
auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D);
+ ComputeType = nullptr;
Type = VD ? VD->getType() : QualType();
ExpectedLoc = Tok;
}
+void PreferredTypeBuilder::enterFunctionArgument(
+ SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) {
+ this->ComputeType = ComputeType;
+ Type = QualType();
+ ExpectedLoc = Tok;
+}
+
void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok,
SourceLocation LParLoc) {
// expected type for parenthesized expression does not change.
case tok::kw___imag:
return QualType();
default:
- assert(false && "unhnalded unary op");
+ assert(false && "unhandled unary op");
return QualType();
}
}
void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS,
tok::TokenKind Op) {
+ ComputeType = nullptr;
Type = getPreferredTypeOfBinaryRHS(S, LHS, Op);
ExpectedLoc = Tok;
}
Expr *Base) {
if (!Base)
return;
- Type = this->get(Base->getBeginLoc());
+ // Do we have expected type for Base?
+ if (ExpectedLoc != Base->getBeginLoc())
+ return;
+ // Keep the expected type, only update the location.
ExpectedLoc = Tok;
+ return;
}
void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok,
tok::TokenKind OpKind,
SourceLocation OpLoc) {
+ ComputeType = nullptr;
Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind);
ExpectedLoc = Tok;
}
void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok,
Expr *LHS) {
+ ComputeType = nullptr;
Type = S.getASTContext().IntTy;
ExpectedLoc = Tok;
}
void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok,
QualType CastType) {
+ ComputeType = nullptr;
Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType();
ExpectedLoc = Tok;
}
void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) {
+ ComputeType = nullptr;
Type = S.getASTContext().BoolTy;
ExpectedLoc = Tok;
}
)cpp";
EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
}
+
+TEST(PreferredTypeTest, FunctionArguments) {
+ StringRef Code = R"cpp(
+ void foo(const int*);
+
+ void bar(const int*);
+ void bar(const int*, int b);
+
+ struct vector {
+ const int *data();
+ };
+ void test() {
+ foo(^(^(^(^vec^tor^().^da^ta^()))));
+ bar(^(^(^(^vec^tor^().^da^ta^()))));
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("const int *"));
+
+ Code = R"cpp(
+ void bar(int, volatile double *);
+ void bar(int, volatile double *, int, int);
+
+ struct vector {
+ double *data();
+ };
+
+ struct class_members {
+ void bar(int, volatile double *);
+ void bar(int, volatile double *, int, int);
+ };
+ void test() {
+ bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
+ class_members().bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
+ }
+ )cpp";
+ EXPECT_THAT(collectPreferredTypes(Code), Each("volatile double *"));
+}
} // namespace