aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r--clang/lib/AST/ExprConstant.cpp94
1 files changed, 46 insertions, 48 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9808298..20b7c44 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -9741,10 +9741,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_AddressSpaceConversion:
if (!Visit(SubExpr))
return false;
- // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are
- // permitted in constant expressions in C++11. Bitcasts from cv void* are
- // also static_casts, but we disallow them as a resolution to DR1312.
- if (!E->getType()->isVoidPointerType()) {
+ if (E->getType()->isFunctionPointerType() ||
+ SubExpr->getType()->isFunctionPointerType()) {
+ // Casting between two function pointer types, or between a function
+ // pointer and an object pointer, is always a reinterpret_cast.
+ CCEDiag(E, diag::note_constexpr_invalid_cast)
+ << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
+ << Info.Ctx.getLangOpts().CPlusPlus;
+ Result.Designator.setInvalid();
+ } else if (!E->getType()->isVoidPointerType()) {
+ // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are
+ // permitted in constant expressions in C++11. Bitcasts from cv void* are
+ // also static_casts, but we disallow them as a resolution to DR1312.
+ //
// In some circumstances, we permit casting from void* to cv1 T*, when the
// actual pointee object is actually a cv2 T.
bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid &&
@@ -16849,31 +16858,31 @@ static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
CheckMemoryLeaks(Info);
}
-static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
+static bool FastEvaluateAsRValue(const Expr *Exp, APValue &Result,
const ASTContext &Ctx, bool &IsConst) {
// Fast-path evaluations of integer literals, since we sometimes see files
// containing vast quantities of these.
if (const auto *L = dyn_cast<IntegerLiteral>(Exp)) {
- Result.Val = APValue(APSInt(L->getValue(),
- L->getType()->isUnsignedIntegerType()));
+ Result =
+ APValue(APSInt(L->getValue(), L->getType()->isUnsignedIntegerType()));
IsConst = true;
return true;
}
if (const auto *L = dyn_cast<CXXBoolLiteralExpr>(Exp)) {
- Result.Val = APValue(APSInt(APInt(1, L->getValue())));
+ Result = APValue(APSInt(APInt(1, L->getValue())));
IsConst = true;
return true;
}
if (const auto *FL = dyn_cast<FloatingLiteral>(Exp)) {
- Result.Val = APValue(FL->getValue());
+ Result = APValue(FL->getValue());
IsConst = true;
return true;
}
if (const auto *L = dyn_cast<CharacterLiteral>(Exp)) {
- Result.Val = APValue(Ctx.MakeIntValue(L->getValue(), L->getType()));
+ Result = APValue(Ctx.MakeIntValue(L->getValue(), L->getType()));
IsConst = true;
return true;
}
@@ -16882,7 +16891,7 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
if (CE->hasAPValueResult()) {
APValue APV = CE->getAPValueResult();
if (!APV.isLValue()) {
- Result.Val = std::move(APV);
+ Result = std::move(APV);
IsConst = true;
return true;
}
@@ -16912,7 +16921,7 @@ static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result,
const ASTContext &Ctx, EvalInfo &Info) {
assert(!E->isValueDependent());
bool IsConst;
- if (FastEvaluateAsRValue(E, Result, Ctx, IsConst))
+ if (FastEvaluateAsRValue(E, Result.Val, Ctx, IsConst))
return IsConst;
return EvaluateAsRValue(Info, E, Result.Val);
@@ -17069,7 +17078,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
bool IsConst;
- if (FastEvaluateAsRValue(this, Result, Ctx, IsConst) && Result.Val.hasValue())
+ if (FastEvaluateAsRValue(this, Result.Val, Ctx, IsConst) &&
+ Result.Val.hasValue())
return true;
ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateAsConstantExpr");
@@ -17284,7 +17294,7 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
ExprTimeTraceScope TimeScope(this, Ctx, "EvaluateForOverflow");
bool IsConst;
EvalResult EVResult;
- if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) {
+ if (!FastEvaluateAsRValue(this, EVResult.Val, Ctx, IsConst)) {
EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
Info.CheckingForUndefinedBehavior = true;
(void)::EvaluateAsRValue(Info, this, EVResult.Val);
@@ -17303,8 +17313,7 @@ bool Expr::EvalResult::isGlobalLValue() const {
/// comma, etc
// CheckICE - This function does the fundamental ICE checking: the returned
-// ICEDiag contains an ICEKind indicating whether the expression is an ICE,
-// and a (possibly null) SourceLocation indicating the location of the problem.
+// ICEDiag contains an ICEKind indicating whether the expression is an ICE.
//
// Note that to reduce code duplication, this helper does no evaluation
// itself; the caller checks whether the expression is evaluatable, and
@@ -17768,60 +17777,51 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
/// Evaluate an expression as a C++11 integral constant expression.
static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx,
const Expr *E,
- llvm::APSInt *Value,
- SourceLocation *Loc) {
- if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
- if (Loc) *Loc = E->getExprLoc();
+ llvm::APSInt *Value) {
+ if (!E->getType()->isIntegralOrUnscopedEnumerationType())
return false;
- }
APValue Result;
- if (!E->isCXX11ConstantExpr(Ctx, &Result, Loc))
+ if (!E->isCXX11ConstantExpr(Ctx, &Result))
return false;
- if (!Result.isInt()) {
- if (Loc) *Loc = E->getExprLoc();
+ if (!Result.isInt())
return false;
- }
if (Value) *Value = Result.getInt();
return true;
}
-bool Expr::isIntegerConstantExpr(const ASTContext &Ctx,
- SourceLocation *Loc) const {
+bool Expr::isIntegerConstantExpr(const ASTContext &Ctx) const {
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
ExprTimeTraceScope TimeScope(this, Ctx, "isIntegerConstantExpr");
if (Ctx.getLangOpts().CPlusPlus11)
- return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc);
+ return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr);
ICEDiag D = CheckICE(this, Ctx);
- if (D.Kind != IK_ICE) {
- if (Loc) *Loc = D.Loc;
+ if (D.Kind != IK_ICE)
return false;
- }
return true;
}
std::optional<llvm::APSInt>
-Expr::getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc) const {
+Expr::getIntegerConstantExpr(const ASTContext &Ctx) const {
if (isValueDependent()) {
// Expression evaluator can't succeed on a dependent expression.
return std::nullopt;
}
- APSInt Value;
-
if (Ctx.getLangOpts().CPlusPlus11) {
- if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc))
+ APSInt Value;
+ if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value))
return Value;
return std::nullopt;
}
- if (!isIntegerConstantExpr(Ctx, Loc))
+ if (!isIntegerConstantExpr(Ctx))
return std::nullopt;
// The only possible side-effects here are due to UB discovered in the
@@ -17846,8 +17846,7 @@ bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const {
return CheckICE(this, Ctx).Kind == IK_ICE;
}
-bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
- SourceLocation *Loc) const {
+bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result) const {
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");
@@ -17855,28 +17854,27 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
// issues.
assert(Ctx.getLangOpts().CPlusPlus);
+ bool IsConst;
+ APValue Scratch;
+ if (FastEvaluateAsRValue(this, Scratch, Ctx, IsConst) && Scratch.hasValue()) {
+ if (Result)
+ *Result = Scratch;
+ return true;
+ }
+
// Build evaluation settings.
Expr::EvalStatus Status;
SmallVector<PartialDiagnosticAt, 8> Diags;
Status.Diag = &Diags;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
- APValue Scratch;
bool IsConstExpr =
::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) &&
// FIXME: We don't produce a diagnostic for this, but the callers that
// call us on arbitrary full-expressions should generally not care.
Info.discardCleanups() && !Status.HasSideEffects;
- if (!Diags.empty()) {
- IsConstExpr = false;
- if (Loc) *Loc = Diags[0].first;
- } else if (!IsConstExpr) {
- // FIXME: This shouldn't happen.
- if (Loc) *Loc = getExprLoc();
- }
-
- return IsConstExpr;
+ return IsConstExpr && Diags.empty();
}
bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,