clang: lib/Parse/ParseInit.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

23#include "llvm/ADT/STLExtras.h"

24#include "llvm/ADT/SmallString.h"

25using namespace clang;

26

27

28

29

30

31bool Parser::MayBeDesignationStart() {

33 default:

34 return false;

35

36 case tok::period:

37 return true;

38

39 case tok::l_square: {

41 return true;

42

43

44

45

47 case tok::equal:

48 case tok::ellipsis:

49 case tok::r_square:

50

51 return false;

52

53 case tok::amp:

54 case tok::kw_this:

55 case tok:⭐

56 case tok::identifier:

57

58

59 break;

60

61 default:

62

63

64 return true;

65 }

66

67

68 break;

69 }

70 case tok::identifier:

72 }

73

74

75

76 RevertingTentativeParsingAction Tentative(*this);

77

79 LambdaIntroducerTentativeParse ParseResult;

80 if (ParseLambdaIntroducer(Intro, &ParseResult)) {

81

82

83 return true;

84 }

85

86 switch (ParseResult) {

87 case LambdaIntroducerTentativeParse::Success:

88 case LambdaIntroducerTentativeParse::Incomplete:

89

90

91

92 break;

93

94 case LambdaIntroducerTentativeParse::MessageSend:

95 case LambdaIntroducerTentativeParse::Invalid:

96

97

98 return true;

99 }

100

101

102

103

104

105

106 return Tok.is(tok::equal);

107}

108

111

112

113

117 P.Diag(Loc, diag::ext_gnu_missing_equal_designator);

119 P.Diag(Loc, diag::err_expected_equal_designator);

120}

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164ExprResult Parser::ParseInitializerWithPotentialDesignator(

165 DesignatorCompletionInfo DesignatorCompletion) {

166

167

168

169

170 if (Tok.is(tok::identifier)) {

172

174 llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName()

175 << " = ";

176

178

179 assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");

181

182 Diag(NameLoc, diag::ext_gnu_old_style_field_designator)

184 NewSyntax);

185

190 Tok.getLocation(), DesignatorCompletion.PreferredBaseType, D);

192 ParseInitializer());

193 }

194

195

196

197

199

200

201 while (Tok.is(tok::period) || Tok.is(tok::l_square)) {

202 if (Tok.is(tok::period)) {

203

205

206 if (Tok.is(tok::code_completion)) {

207 cutOffParsing();

209 DesignatorCompletion.PreferredBaseType,

210 DesignatorCompletion.InitExprs, Desig);

212 }

213 if (Tok.isNot(tok::identifier)) {

214 Diag(Tok.getLocation(), diag::err_expected_field_designator);

216 }

217

221 continue;

222 }

223

224

225 assert(Tok.is(tok::l_square) && "Unexpected token!");

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

245

247 T.consumeOpen();

249

251

252

253

254

255

257

259 NextToken().isNot(tok::period) &&

262 return ParseAssignmentExprWithObjCMessageExprStart(

264 }

265

266

267 bool IsExpr;

268 void *TypeOrExpr;

269 if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {

272 }

273

274

275

276 if (!IsExpr) {

278 return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,

281 nullptr);

282 }

283

284

285

286

287

293

294

295

297 getCurScope(), II, IILoc, II == Ident_super,

298 NextToken().is(tok::period), ReceiverType)) {

301 return ParseAssignmentExprWithObjCMessageExprStart(

303

307 if (!ReceiverType) {

310 }

311

312

313 if (Tok.is(tok::less)) {

316 = parseObjCTypeArgsAndProtocolQualifiers(IILoc, ReceiverType,

317 true,

318 NewEndLoc);

319 if (!NewReceiverType.isUsable()) {

322 }

323

324 ReceiverType = NewReceiverType.get();

325 }

326

327 return ParseAssignmentExprWithObjCMessageExprStart(StartLoc,

329 ReceiverType,

330 nullptr);

331

333

334

335

336 break;

337 }

338 }

339

340

341

342

343

344

345

346

347 if (!Idx.get()) {

351 return Idx;

352 }

353 }

354

355

356

357

358

360 Tok.isNot(tok::r_square)) {

362 return ParseAssignmentExprWithObjCMessageExprStart(

364 }

365

366

367 if (Tok.isNot(tok::ellipsis)) {

369 StartLoc));

370 } else {

371

372 Diag(Tok, diag::ext_gnu_array_range);

374

376 if (RHS.isInvalid()) {

378 return RHS;

379 }

381 Idx.get(), RHS.get(), StartLoc, EllipsisLoc));

382 }

383

384 T.consumeClose();

386 T.getCloseLocation());

387 }

388

389

390

391

392

393 assert(!Desig.empty() && "Designator is empty?");

394

395

396 if (Tok.is(tok::equal)) {

399 Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);

401 ParseInitializer());

402 }

403

404

405

406

409 Tok.getLocation(), DesignatorCompletion.PreferredBaseType, Desig);

411 ParseBraceInitializer());

412 }

413

414

415

416

417

421 Diag(Tok, diag::ext_gnu_missing_equal_designator)

424 true, ParseInitializer());

425 }

426

427 Diag(Tok, diag::err_expected_equal_designator);

429}

430

431ExprResult Parser::createEmbedExpr() {

432 assert(Tok.getKind() == tok::annot_embed);

438 if (Data->BinaryData.size() == 1) {

440 Context, llvm::APInt(CHAR_BIT, (unsigned char)Data->BinaryData.back()),

442 } else {

443 auto CreateStringLiteralFromStringRef = [&](StringRef Str, QualType Ty) {

444 llvm::APSInt ArraySize =

449 false, ArrayTy, StartLoc);

450 };

451

452 StringLiteral *BinaryDataArg = CreateStringLiteralFromStringRef(

454 Res = Actions.ActOnEmbedExpr(StartLoc, BinaryDataArg);

455 }

456 return Res;

457}

458

459

460

461

462

463

464

465

466

467

468

469

470

471ExprResult Parser::ParseBraceInitializer() {

473

475 T.consumeOpen();

477

478

479

480 ExprVector InitExprs;

481

482 if (Tok.is(tok::r_brace)) {

483

486 ? diag::warn_c23_compat_empty_initializer

487 : diag::ext_c_empty_initializer);

488 }

489

490 return Actions.ActOnInitList(LBraceLoc, {}, ConsumeBrace());

491 }

492

493

496

497 bool InitExprsOk = true;

498 QualType LikelyType = PreferredType.get(T.getOpenLocation());

499 DesignatorCompletionInfo DesignatorCompletion{InitExprs, LikelyType};

500 bool CalledSignatureHelp = false;

501 auto RunSignatureHelp = [&] {

503 if (!LikelyType.isNull())

506 InitExprs, T.getOpenLocation(), true);

507 CalledSignatureHelp = true;

508 return PreferredType;

509 };

510

511 while (true) {

512 PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);

513

514

515 if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) ||

516 Tok.is(tok::kw___if_not_exists))) {

517 if (ParseMicrosoftIfExistsBraceInitializer(InitExprs, InitExprsOk)) {

518 if (Tok.isNot(tok::comma)) break;

520 }

521 if (Tok.is(tok::r_brace)) break;

522 continue;

523 }

524

525

526

527

528

530 if (MayBeDesignationStart())

531 SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);

532 else if (Tok.getKind() == tok::annot_embed)

533 SubElt = createEmbedExpr();

534 else

535 SubElt = ParseInitializer();

536

537 if (Tok.is(tok::ellipsis))

539

541

542

544 InitExprs.push_back(SubElt.get());

545 } else {

546 InitExprsOk = false;

547

548

549

550

551

552

553

554

555

556 if (Tok.isNot(tok::comma)) {

558 break;

559 }

560 }

561

562

563 if (Tok.isNot(tok::comma)) break;

564

565

567

568

569 if (Tok.is(tok::r_brace)) break;

570 }

571

572 bool closed = T.consumeClose();

573

574 if (InitExprsOk && closed)

575 return Actions.ActOnInitList(LBraceLoc, InitExprs,

576 T.getCloseLocation());

577

578 return ExprError();

579}

580

581

582

583

584bool Parser::ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs,

585 bool &InitExprsOk) {

586 bool trailingComma = false;

587 IfExistsCondition Result;

588 if (ParseMicrosoftIfExistsCondition(Result))

589 return false;

590

592 if (Braces.consumeOpen()) {

593 Diag(Tok, diag::err_expected) << tok::l_brace;

594 return false;

595 }

596

597 switch (Result.Behavior) {

598 case IEB_Parse:

599

600 break;

601

602 case IEB_Dependent:

603 Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)

604 << Result.IsIfExists;

605

606 [[fallthrough]];

607

608 case IEB_Skip:

610 return false;

611 }

612

613 DesignatorCompletionInfo DesignatorCompletion{

614 InitExprs,

615 PreferredType.get(Braces.getOpenLocation()),

616 };

617 while (!isEofOrEom()) {

618 trailingComma = false;

619

620

622 if (MayBeDesignationStart())

623 SubElt = ParseInitializerWithPotentialDesignator(DesignatorCompletion);

624 else

625 SubElt = ParseInitializer();

626

627 if (Tok.is(tok::ellipsis))

629

630

632 InitExprs.push_back(SubElt.get());

633 else

634 InitExprsOk = false;

635

636 if (Tok.is(tok::comma)) {

638 trailingComma = true;

639 }

640

641 if (Tok.is(tok::r_brace))

642 break;

643 }

644

645 Braces.consumeClose();

646

647 return !trailingComma;

648}

static void CheckArrayDesignatorSyntax(Parser &P, SourceLocation Loc, Designation &Desig)

This file declares facilities that support code completion.

This file declares semantic analysis for Objective-C.

Defines the clang::TokenKind enum and support functions.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const

Return the unique reference to the type for a constant array of the specified element type.

CanQualType getSizeType() const

Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.

CanQualType UnsignedCharTy

llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const

Make an APSInt of the appropriate width and signedness for the given Value and integer Type.

RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....

Designation - Represent a full designation, which is a sequence of designators.

const Designator & getDesignator(unsigned Idx) const

unsigned getNumDesignators() const

void AddDesignator(Designator D)

AddDesignator - Add a designator to the end of this list.

bool isArrayDesignator() const

static Designator CreateArrayRangeDesignator(Expr *Start, Expr *End, SourceLocation LBracketLoc, SourceLocation EllipsisLoc)

Creates a GNU array-range designator.

static Designator CreateArrayDesignator(Expr *Index, SourceLocation LBracketLoc)

Creates an array designator.

void setRBracketLoc(SourceLocation RBracketLoc) const

bool isArrayRangeDesignator() const

static Designator CreateFieldDesignator(const IdentifierInfo *FieldName, SourceLocation DotLoc, SourceLocation FieldLoc)

Creates a field designator.

RAII object that enters a new expression evaluation context.

This represents one expression.

static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)

Create a code modification hint that replaces the given source range with the given code string.

static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)

Create a code modification hint that inserts the given code string at a specific location.

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)

Returns a new integer literal with value 'V' and type 'type'.

static OpaquePtr getFromOpaquePtr(void *P)

Parser - This implements a parser for the C family of languages.

DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

SourceLocation ConsumeToken()

ConsumeToken - Consume the current 'peek token' and lex the next one.

ExprResult ParseConstantExpression()

Scope * getCurScope() const

bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))

SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...

ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)

Parse an expr that doesn't include (top-level) commas.

const LangOptions & getLangOpts() const

@ StopBeforeMatch

Stop skipping at specified token, but don't skip the token itself.

@ StopAtSemi

Stop skipping at semicolon.

const Token & NextToken()

NextToken - This peeks ahead one token and returns it without consuming it.

void enterDesignatedInitializer(SourceLocation Tok, QualType BaseType, const Designation &D)

Handles e.g. BaseType{ .D = Tok...

QualType get(SourceLocation Tok) const

Get the expected type associated with this location, if any.

const Token & LookAhead(unsigned N)

Peeks ahead N tokens and returns that token without consuming any tokens.

const LangOptions & getLangOpts() const

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, ArrayRef< Expr * > Args, SourceLocation OpenParLoc, bool Braced)

void CodeCompleteDesignator(const QualType BaseType, llvm::ArrayRef< Expr * > InitExprs, const Designation &D)

Trigger code completion for a record of BaseType.

ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name, SourceLocation NameLoc, bool IsSuper, bool HasTrailingDot, ParsedType &ReceiverType)

@ ObjCClassMessage

The message is a class message, and the identifier is a type name.

@ ObjCInstanceMessage

The message is an instance message.

@ ObjCSuperMessage

The message is sent to 'super'.

ExprResult ActOnDesignatedInitializer(Designation &Desig, SourceLocation EqualOrColonLoc, bool GNUSyntax, ExprResult Init)

ASTContext & getASTContext() const

SemaCodeCompletion & CodeCompletion()

ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg, SourceLocation EllipsisLoc)

Invoked when parsing a template argument followed by an ellipsis, which creates a pack expansion.

ExprResult ActOnEmbedExpr(SourceLocation EmbedKeywordLoc, StringLiteral *BinaryData)

ExprResult ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, SourceLocation RBraceLoc)

ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})

Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...

Encodes a location in the source.

A trivial tuple used to represent a source range.

StringLiteral - This represents a string literal expression, e.g.

static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumConcatenated)

This is the "fully general" constructor that allows representation of strings formed from multiple co...

IdentifierInfo * getIdentifierInfo() const

SourceLocation getLocation() const

Return a source location identifier for the specified offset in the current file.

bool is(tok::TokenKind K) const

is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....

void * getAnnotationValue() const

tok::TokenKind getKind() const

bool isNot(tok::TokenKind K) const

QualType getCanonicalTypeInternal() const

The JSON file list parser is used to communicate input to InstallAPI.

@ Result

The result type of a method or function.

ActionResult< Expr * > ExprResult

const FunctionProtoType * T

@ Braces

New-expression has a C++11 list-initializer.

Helper class to shuttle information about #embed directives from the preprocessor to the parser throu...

Represents a complete lambda introducer.