diff options
Diffstat (limited to 'clang/lib/AST')
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 13 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 121 |
2 files changed, 50 insertions, 84 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 54fd723d978..7e85619c819 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2317,6 +2317,19 @@ BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr); } +VarDecl *BindingDecl::getHoldingVar() const { + Expr *B = getBinding(); + if (!B) + return nullptr; + auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit()); + if (!DRE) + return nullptr; + + auto *VD = dyn_cast<VarDecl>(DRE->getDecl()); + assert(VD->isImplicit() && "holding var for binding decl not implicit"); + return VD; +} + void DecompositionDecl::anchor() {} DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC, diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 8fe27a515bb..107913ed61b 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3400,50 +3400,51 @@ enum EvalStmtResult { }; } -static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - // We don't need to evaluate the initializer for a static local. - if (!VD->hasLocalStorage()) - return true; - - LValue Result; - Result.set(VD, Info.CurrentCall->Index); - APValue &Val = Info.CurrentCall->createTemporary(VD, true); - - const Expr *InitE = VD->getInit(); - if (!InitE) { - Info.FFDiag(D->getLocStart(), diag::note_constexpr_uninitialized) - << false << VD->getType(); - Val = APValue(); - return false; - } +static bool EvaluateVarDecl(EvalInfo &Info, const VarDecl *VD) { + // We don't need to evaluate the initializer for a static local. + if (!VD->hasLocalStorage()) + return true; - if (InitE->isValueDependent()) - return false; + LValue Result; + Result.set(VD, Info.CurrentCall->Index); + APValue &Val = Info.CurrentCall->createTemporary(VD, true); - if (!EvaluateInPlace(Val, Info, Result, InitE)) { - // Wipe out any partially-computed value, to allow tracking that this - // evaluation failed. - Val = APValue(); - return false; - } + const Expr *InitE = VD->getInit(); + if (!InitE) { + Info.FFDiag(VD->getLocStart(), diag::note_constexpr_uninitialized) + << false << VD->getType(); + Val = APValue(); + return false; + } - // Evaluate initializers for any structured bindings. - if (auto *DD = dyn_cast<DecompositionDecl>(VD)) { - for (auto *BD : DD->bindings()) { - APValue &Val = Info.CurrentCall->createTemporary(BD, true); + if (InitE->isValueDependent()) + return false; - LValue Result; - if (!EvaluateLValue(BD->getBinding(), Result, Info)) - return false; - Result.moveInto(Val); - } - } + if (!EvaluateInPlace(Val, Info, Result, InitE)) { + // Wipe out any partially-computed value, to allow tracking that this + // evaluation failed. + Val = APValue(); + return false; } return true; } +static bool EvaluateDecl(EvalInfo &Info, const Decl *D) { + bool OK = true; + + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) + OK &= EvaluateVarDecl(Info, VD); + + if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(D)) + for (auto *BD : DD->bindings()) + if (auto *VD = BD->getHoldingVar()) + OK &= EvaluateDecl(Info, VD); + + return OK; +} + + /// Evaluate a condition (either a variable declaration or an expression). static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl, const Expr *Cond, bool &Result) { @@ -4736,7 +4737,6 @@ public: LValueExprEvaluatorBaseTy(Info, Result) {} bool VisitVarDecl(const Expr *E, const VarDecl *VD); - bool VisitBindingDecl(const Expr *E, const BindingDecl *BD); bool VisitUnaryPreIncDec(const UnaryOperator *UO); bool VisitDeclRefExpr(const DeclRefExpr *E); @@ -4799,7 +4799,7 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) return VisitVarDecl(E, VD); if (const BindingDecl *BD = dyn_cast<BindingDecl>(E->getDecl())) - return VisitBindingDecl(E, BD); + return Visit(BD->getBinding()); return Error(E); } @@ -4827,53 +4827,6 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { return Success(*V, E); } -bool LValueExprEvaluator::VisitBindingDecl(const Expr *E, - const BindingDecl *BD) { - // If we've already evaluated the binding, just return the lvalue. - if (APValue *Value = Info.CurrentCall->getTemporary(BD)) { - if (Value->isUninit()) { - if (!Info.checkingPotentialConstantExpression()) - Info.FFDiag(E, diag::note_constexpr_use_uninit_reference); - return false; - } - return Success(*Value, E); - } - - // We've not evaluated the initializer of this binding. It's still OK if it - // is initialized by a constant expression. - // - // FIXME: We should check this at the point of declaration, since we're not - // supposed to be able to use it if it references something that was declared - // later. - auto *Binding = BD->getBinding(); - if (!Binding) { - Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); - return false; - } - - // Evaluate in an independent context to check whether the binding was a - // constant expression in an absolute sense, and without mutating any of - // our local state. - Expr::EvalStatus InitStatus; - SmallVector<PartialDiagnosticAt, 8> Diag; - InitStatus.Diag = &Diag; - EvalInfo InitInfo(Info.Ctx, InitStatus, EvalInfo::EM_ConstantExpression); - - if (!EvaluateLValue(Binding, Result, InitInfo) || InitStatus.HasSideEffects || - !CheckLValueConstantExpression( - InitInfo, Binding->getExprLoc(), - Info.Ctx.getLValueReferenceType(BD->getType()), Result) || - !Diag.empty()) { - // FIXME: Diagnose this better. Maybe produce the Diags to explain why - // the initializer was not constant. - if (!Info.checkingPotentialConstantExpression()) - Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr); - return false; - } - - return true; -} - bool LValueExprEvaluator::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *E) { // Walk through the expression to find the materialized temporary itself. |