[Sema] Validate calls to GetExprRange.

When a conditional expression has a throw expression it called
GetExprRange with a void expression, which caused an assertion failure.

This approach was suggested by Richard Smith.

Fixes PR46484: Clang crash in clang/lib/Sema/SemaChecking.cpp:10028

Differential Revision: https://reviews.llvm.org/D85601
This commit is contained in:
Mark de Wever 2020-08-16 18:32:38 +02:00
parent f25d47b7ed
commit 827ba67e38
2 changed files with 27 additions and 4 deletions

View File

@ -10368,10 +10368,16 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
MaxWidth, InConstantContext);
// Otherwise, conservatively merge.
IntRange L =
GetExprRange(C, CO->getTrueExpr(), MaxWidth, InConstantContext);
IntRange R =
GetExprRange(C, CO->getFalseExpr(), MaxWidth, InConstantContext);
// GetExprRange requires an integer expression, but a throw expression
// results in a void type.
Expr *E = CO->getTrueExpr();
IntRange L = E->getType()->isVoidType()
? IntRange{0, true}
: GetExprRange(C, E, MaxWidth, InConstantContext);
E = CO->getFalseExpr();
IntRange R = E->getType()->isVoidType()
? IntRange{0, true}
: GetExprRange(C, E, MaxWidth, InConstantContext);
return IntRange::join(L, R);
}

View File

@ -409,3 +409,20 @@ namespace lifetime_extension {
D d = b ? D{B()} : D{C()};
}
}
namespace PR46484 {
// expected-error@+4{{expected ':'}}
// expected-note@+3{{to match this '?'}}
// expected-warning@+2{{variable 'b' is uninitialized}}
// expected-error@+1 2 {{expected ';' after top level declarator}}
int a long b = a = b ? throw 0 1
void g() {
extern int a;
extern long b;
long c = a = b ? throw 0 : 1;
long d = a = b ? 1 : throw 0;
// expected-error@+1 {{assigning to 'int' from incompatible type 'void'}}
long e = a = b ? throw 0 : throw 1;
}
} // namespace PR46484