Skip to content

Commit

Permalink
Revert "Properly track whether a variable is constant-initialized."
Browse files Browse the repository at this point in the history
This reverts commit 08c8d5bc51c512e605840b8003fcf38c86d0fc96:

  Properly track whether a variable is constant-initialized.

  This fixes miscomputation of __builtin_constant_evaluated in the
  initializer of a variable that's not usable in constant expressions, but
  is readable when constant-folding.

  If evaluation of a constant initializer fails, we throw away the
  evaluated result instead of keeping it as a non-constant-initializer
  value for the variable, because it might not be a correct value.
  To avoid regressions for initializers that are foldable but not formally
  constant initializers, we now try constant-evaluating some globals in
  C++ twice: once to check for a constant initializer (in an mode where
  is_constannt_evaluated returns true) and again to determine the runtime
  value if the initializer is not a constant initializer.

This is to work around an issue in the bootstrap phase of the gcc ports,
which depend on some __builtin_constant_p() expressions not emitting
references to undefined global variables in gcc's generator tools (e.g.
gencondmd and friends), even with optimization turned off.

PR:		255570
  • Loading branch information
DimitryAndric committed Jun 12, 2021
1 parent c000f16 commit 9c6443e
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 41 deletions.
11 changes: 4 additions & 7 deletions contrib/llvm-project/clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1276,15 +1276,12 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
EvaluatedStmt *getEvaluatedStmt() const;

/// Attempt to evaluate the value of the initializer attached to this
/// declaration, and produce notes explaining why it cannot be evaluated.
/// Returns a pointer to the value if evaluation succeeded, 0 otherwise.
/// declaration, and produce notes explaining why it cannot be evaluated or is
/// not a constant expression. Returns a pointer to the value if evaluation
/// succeeded, 0 otherwise.
APValue *evaluateValue() const;
APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &Notes) const;

private:
APValue *evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
bool IsConstantInitialization) const;

public:
/// Return the already-evaluated value of this variable's
/// initializer, or NULL if the value is not yet known. Returns pointer
/// to untyped APValue if the value could not be evaluated.
Expand Down
3 changes: 1 addition & 2 deletions contrib/llvm-project/clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -699,8 +699,7 @@ class Expr : public ValueStmt {
/// notes will be produced if the expression is not a constant expression.
bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx,
const VarDecl *VD,
SmallVectorImpl<PartialDiagnosticAt> &Notes,
bool IsConstantInitializer) const;
SmallVectorImpl<PartialDiagnosticAt> &Notes) const;

/// EvaluateWithSubstitution - Evaluate an expression as if from the context
/// of a call to the given function with the given arguments, inside an
Expand Down
29 changes: 7 additions & 22 deletions contrib/llvm-project/clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2384,11 +2384,11 @@ EvaluatedStmt *VarDecl::getEvaluatedStmt() const {

APValue *VarDecl::evaluateValue() const {
SmallVector<PartialDiagnosticAt, 8> Notes;
return evaluateValueImpl(Notes, hasConstantInitialization());
return evaluateValue(Notes);
}

APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
bool IsConstantInitialization) const {
APValue *VarDecl::evaluateValue(
SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
EvaluatedStmt *Eval = ensureEvaluatedStmt();

const auto *Init = cast<Expr>(Eval->Value);
Expand All @@ -2407,24 +2407,16 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,

Eval->IsEvaluating = true;

ASTContext &Ctx = getASTContext();
bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes,
IsConstantInitialization);

// In C++11, this isn't a constant initializer if we produced notes. In that
// case, we can't keep the result, because it may only be correct under the
// assumption that the initializer is a constant context.
if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus11 &&
!Notes.empty())
Result = false;
bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(),
this, Notes);

// Ensure the computed APValue is cleaned up later if evaluation succeeded,
// or that it's empty (so that there's nothing to clean up) if evaluation
// failed.
if (!Result)
Eval->Evaluated = APValue();
else if (Eval->Evaluated.needsCleanup())
Ctx.addDestruction(&Eval->Evaluated);
getASTContext().addDestruction(&Eval->Evaluated);

Eval->IsEvaluating = false;
Eval->WasEvaluated = true;
Expand Down Expand Up @@ -2478,14 +2470,7 @@ bool VarDecl::checkForConstantInitialization(
assert(!cast<Expr>(Eval->Value)->isValueDependent());

// Evaluate the initializer to check whether it's a constant expression.
Eval->HasConstantInitialization =
evaluateValueImpl(Notes, true) && Notes.empty();

// If evaluation as a constant initializer failed, allow re-evaluation as a
// non-constant initializer if we later find we want the value.
if (!Eval->HasConstantInitialization)
Eval->WasEvaluated = false;

Eval->HasConstantInitialization = evaluateValue(Notes) && Notes.empty();
return Eval->HasConstantInitialization;
}

Expand Down
19 changes: 10 additions & 9 deletions contrib/llvm-project/clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3302,9 +3302,12 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,

// Check that we can fold the initializer. In C++, we will have already done
// this in the cases where it matters for conformance.
if (!VD->evaluateValue()) {
Info.FFDiag(E, diag::note_constexpr_var_init_non_constant, 1) << VD;
SmallVector<PartialDiagnosticAt, 8> Notes;
if (!VD->evaluateValue(Notes)) {
Info.FFDiag(E, diag::note_constexpr_var_init_non_constant,
Notes.size() + 1) << VD;
NoteLValueLocation(Info, Base);
Info.addNotes(Notes);
return false;
}

Expand Down Expand Up @@ -14866,8 +14869,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx,

bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
const VarDecl *VD,
SmallVectorImpl<PartialDiagnosticAt> &Notes,
bool IsConstantInitialization) const {
SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
assert(!isValueDependent() &&
"Expression evaluator can't be called on a dependent expression.");

Expand All @@ -14880,12 +14882,11 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
Expr::EvalStatus EStatus;
EStatus.Diag = &Notes;

EvalInfo Info(Ctx, EStatus,
(IsConstantInitialization && Ctx.getLangOpts().CPlusPlus11)
? EvalInfo::EM_ConstantExpression
: EvalInfo::EM_ConstantFold);
EvalInfo Info(Ctx, EStatus, VD->isConstexpr()
? EvalInfo::EM_ConstantExpression
: EvalInfo::EM_ConstantFold);
Info.setEvaluatingDecl(VD, Value);
Info.InConstantContext = IsConstantInitialization;
Info.InConstantContext = true;

SourceLocation DeclLoc = VD->getLocation();
QualType DeclTy = VD->getType();
Expand Down
2 changes: 1 addition & 1 deletion contrib/llvm-project/clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1622,8 +1622,8 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) {
if (CD->isTrivial() && CD->isDefaultConstructor())
return CGM.EmitNullConstant(D.getType());
}
InConstantContext = true;
}
InConstantContext = D.hasConstantInitialization();

QualType destType = D.getType();

Expand Down

0 comments on commit 9c6443e

Please sign in to comment.