@@ -229,12 +229,14 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
229
229
230
230
OS << " <Content>" << Content.str () << " </Content>\n " ;
231
231
232
- if (auto Ty = ExitInfo. getPointer ()) {
232
+ if (auto Ty = getType ()) {
233
233
OS << " <Type>" ;
234
234
Ty->print (OS);
235
235
OS << " </Type>" ;
236
- if (ExitInfo.getInt ()) {
237
- OS << " <Exit>true</Exit>" ;
236
+ switch (exit ()) {
237
+ case ExitState::Positive: OS << " <Exit>true</Exit>" ; break ;
238
+ case ExitState::Unsure: OS << " <Exit>unsure</Exit>" ; break ;
239
+ case ExitState::Negative: OS << " <Exit>false</Exit>" ; break ;
238
240
}
239
241
OS << " \n " ;
240
242
}
@@ -335,6 +337,23 @@ static bool hasUnhandledError(ArrayRef<ASTNode> Nodes) {
335
337
});
336
338
}
337
339
340
+ ReturnInfo::
341
+ ReturnInfo (ASTContext &Ctx, ArrayRef<ReturnInfo> Branches):
342
+ ReturnType(Ctx.TheErrorType.getPointer()), Exit(ExitState::Unsure) {
343
+ std::set<TypeBase*> AllTypes;
344
+ std::set<ExitState> AllExitStates;
345
+ for (auto I : Branches) {
346
+ AllTypes.insert (I.ReturnType );
347
+ AllExitStates.insert (I.Exit );
348
+ }
349
+ if (AllTypes.size () == 1 ) {
350
+ ReturnType = *AllTypes.begin ();
351
+ }
352
+ if (AllExitStates.size () == 1 ) {
353
+ Exit = *AllExitStates.begin ();
354
+ }
355
+ }
356
+
338
357
struct RangeResolver ::Implementation {
339
358
SourceFile &File;
340
359
ASTContext &Ctx;
@@ -394,10 +413,10 @@ struct RangeResolver::Implementation {
394
413
std::vector<ASTNode> ContainedASTNodes;
395
414
396
415
// / Collect the type that an ASTNode should be evaluated to.
397
- ReturnTyAndWhetherExit resolveNodeType (ASTNode N, RangeKind Kind) {
416
+ ReturnInfo resolveNodeType (ASTNode N, RangeKind Kind) {
398
417
auto *VoidTy = Ctx.getVoidDecl ()->getDeclaredInterfaceType ().getPointer ();
399
418
if (N.isNull ())
400
- return {VoidTy, false };
419
+ return {VoidTy, ExitState::Negative };
401
420
switch (Kind) {
402
421
case RangeKind::Invalid:
403
422
case RangeKind::SingleDecl:
@@ -406,7 +425,7 @@ struct RangeResolver::Implementation {
406
425
407
426
// For a single expression, its type is apparent.
408
427
case RangeKind::SingleExpression:
409
- return {N.get <Expr*>()->getType ().getPointer (), false };
428
+ return {N.get <Expr*>()->getType ().getPointer (), ExitState::Negative };
410
429
411
430
// For statements, we either resolve to the returning type or Void.
412
431
case RangeKind::SingleStatement:
@@ -415,9 +434,7 @@ struct RangeResolver::Implementation {
415
434
if (auto RS = dyn_cast<ReturnStmt>(N.get <Stmt*>())) {
416
435
return {
417
436
resolveNodeType (RS->hasResult () ? RS->getResult () : nullptr ,
418
- RangeKind::SingleExpression).getPointer (),
419
- true
420
- };
437
+ RangeKind::SingleExpression).ReturnType , ExitState::Positive };
421
438
}
422
439
423
440
// Unbox the brace statement to find its type.
@@ -430,22 +447,26 @@ struct RangeResolver::Implementation {
430
447
431
448
// Unbox the if statement to find its type.
432
449
if (auto *IS = dyn_cast<IfStmt>(N.get <Stmt*>())) {
433
- auto ThenTy = resolveNodeType (IS->getThenStmt (),
434
- RangeKind::SingleStatement);
435
- auto ElseTy = resolveNodeType (IS->getElseStmt (),
436
- RangeKind::SingleStatement);
437
-
438
- // If two branches agree on the return type, return that type.
439
- if (ThenTy.getPointer ()->isEqual (ElseTy.getPointer ()) &&
440
- ThenTy.getInt () == ElseTy.getInt ())
441
- return ThenTy;
442
-
443
- // Otherwise, return the error type.
444
- return {Ctx.TheErrorType .getPointer (), false };
450
+ llvm::SmallVector<ReturnInfo, 2 > Branches;
451
+ Branches.push_back (resolveNodeType (IS->getThenStmt (),
452
+ RangeKind::SingleStatement));
453
+ Branches.push_back (resolveNodeType (IS->getElseStmt (),
454
+ RangeKind::SingleStatement));
455
+ return {Ctx, Branches};
456
+ }
457
+
458
+ // Unbox switch statement to find return information.
459
+ if (auto *SWS = dyn_cast<SwitchStmt>(N.get <Stmt*>())) {
460
+ llvm::SmallVector<ReturnInfo, 4 > Branches;
461
+ for (auto *CS : SWS->getCases ()) {
462
+ Branches.push_back (resolveNodeType (CS->getBody (),
463
+ RangeKind::SingleStatement));
464
+ }
465
+ return {Ctx, Branches};
445
466
}
446
467
}
447
468
// For other statements, the type should be void.
448
- return {VoidTy, false };
469
+ return {VoidTy, ExitState::Negative };
449
470
}
450
471
}
451
472
}
@@ -480,7 +501,8 @@ struct RangeResolver::Implementation {
480
501
llvm::makeArrayRef (ReferencedDecls));
481
502
else {
482
503
assert (Node.is <Decl*>());
483
- return ResolvedRangeInfo (RangeKind::SingleDecl, {nullptr , false }, Content,
504
+ return ResolvedRangeInfo (RangeKind::SingleDecl,
505
+ ReturnInfo (), Content,
484
506
getImmediateContext (),
485
507
/* Common Parent Expr*/ nullptr ,
486
508
SingleEntry,
@@ -540,7 +562,7 @@ struct RangeResolver::Implementation {
540
562
if (!hasResult () && !Node.isImplicit () && nodeContainSelection (Node)) {
541
563
if (auto Parent = Node.is <Expr*>() ? Node.get <Expr*>() : nullptr ) {
542
564
Result = {
543
- RangeKind::PartOfExpression, { nullptr , false } , Content,
565
+ RangeKind::PartOfExpression, ReturnInfo () , Content,
544
566
getImmediateContext (),
545
567
Parent,
546
568
hasSingleEntryPoint (ContainedASTNodes),
0 commit comments