Skip to content

Commit dea9d57

Browse files
committed
[clang] Small improvments after Adding APValue to ConstantExpr
Summary: this patch has multiple small improvements related to the APValue in ConstantExpr. changes: - APValue in ConstantExpr are now cleaned up using ASTContext::addDestruction instead of there own system. - ConstantExprBits Stores the ValueKind of the result beaing stored. - VerifyIntegerConstantExpression now stores the evaluated value in ConstantExpr. - the Constant Evaluator uses the stored value of ConstantExpr when available. Reviewers: rsmith Reviewed By: rsmith Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D63376 llvm-svn: 364011
1 parent 38a2f50 commit dea9d57

File tree

8 files changed

+61
-35
lines changed

8 files changed

+61
-35
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,12 +2751,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
27512751
///
27522752
/// \param Data Pointer data that will be provided to the callback function
27532753
/// when it is called.
2754-
void AddDeallocation(void (*Callback)(void*), void *Data);
2754+
void AddDeallocation(void (*Callback)(void *), void *Data) const;
27552755

27562756
/// If T isn't trivially destructible, calls AddDeallocation to register it
27572757
/// for destruction.
2758-
template <typename T>
2759-
void addDestruction(T *Ptr) {
2758+
template <typename T> void addDestruction(T *Ptr) const {
27602759
if (!std::is_trivially_destructible<T>::value) {
27612760
auto DestroyPtr = [](void *V) { static_cast<T *>(V)->~T(); };
27622761
AddDeallocation(DestroyPtr, Ptr);
@@ -2819,10 +2818,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
28192818
APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E,
28202819
bool MayCreate);
28212820

2822-
/// Adds an APValue that will be destructed during the destruction of the
2823-
/// ASTContext.
2824-
void AddAPValueCleanup(APValue *Ptr) const { APValueCleanups.push_back(Ptr); }
2825-
28262821
/// Return a string representing the human readable name for the specified
28272822
/// function declaration or file name. Used by SourceLocExpr and
28282823
/// PredefinedExpr to cache evaluated results.
@@ -2989,7 +2984,7 @@ OPT_LIST(V)
29892984
// in order to track and run destructors while we're tearing things down.
29902985
using DeallocationFunctionsAndArguments =
29912986
llvm::SmallVector<std::pair<void (*)(void *), void *>, 16>;
2992-
DeallocationFunctionsAndArguments Deallocations;
2987+
mutable DeallocationFunctionsAndArguments Deallocations;
29932988

29942989
// FIXME: This currently contains the set of StoredDeclMaps used
29952990
// by DeclContext objects. This probably should not be in ASTContext,

clang/include/clang/AST/Expr.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -998,6 +998,9 @@ class ConstantExpr final
998998
EmptyShell Empty);
999999

10001000
static ResultStorageKind getStorageKind(const APValue &Value);
1001+
static ResultStorageKind getStorageKind(const Type *T,
1002+
const ASTContext &Context);
1003+
10011004
SourceLocation getBeginLoc() const LLVM_READONLY {
10021005
return SubExpr->getBeginLoc();
10031006
}
@@ -1009,25 +1012,20 @@ class ConstantExpr final
10091012
return T->getStmtClass() == ConstantExprClass;
10101013
}
10111014

1012-
void SetResult(APValue Value) { MoveIntoResult(Value); }
1013-
void MoveIntoResult(APValue &Value);
1015+
void SetResult(APValue Value, const ASTContext &Context) {
1016+
MoveIntoResult(Value, Context);
1017+
}
1018+
void MoveIntoResult(APValue &Value, const ASTContext &Context);
10141019

10151020
APValue::ValueKind getResultAPValueKind() const {
1016-
switch (ConstantExprBits.ResultKind) {
1017-
case ConstantExpr::RSK_APValue:
1018-
return APValueResult().getKind();
1019-
case ConstantExpr::RSK_Int64:
1020-
return APValue::Int;
1021-
case ConstantExpr::RSK_None:
1022-
return APValue::None;
1023-
}
1024-
llvm_unreachable("invalid ResultKind");
1021+
return static_cast<APValue::ValueKind>(ConstantExprBits.APValueKind);
10251022
}
10261023
ResultStorageKind getResultStorageKind() const {
10271024
return static_cast<ResultStorageKind>(ConstantExprBits.ResultKind);
10281025
}
10291026
APValue getAPValueResult() const;
1030-
1027+
const APValue &getResultAsAPValue() const { return APValueResult(); }
1028+
llvm::APSInt getResultAsAPSInt() const;
10311029
// Iterators
10321030
child_range children() { return child_range(&SubExpr, &SubExpr+1); }
10331031
const_child_range children() const {

clang/include/clang/AST/Stmt.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ class alignas(void *) Stmt {
332332
/// The kind of result that is trail-allocated.
333333
unsigned ResultKind : 2;
334334

335+
/// Kind of Result as defined by APValue::Kind
336+
unsigned APValueKind : 4;
337+
335338
/// When ResultKind == RSK_Int64. whether the trail-allocated integer is
336339
/// signed.
337340
unsigned IsUnsigned : 1;
@@ -340,6 +343,10 @@ class alignas(void *) Stmt {
340343
/// integer. 7 bits because it is the minimal number of bit to represent a
341344
/// value from 0 to 64 (the size of the trail-allocated number).
342345
unsigned BitWidth : 7;
346+
347+
/// When ResultKind == RSK_APValue. Wether the ASTContext will cleanup the
348+
/// destructor on the trail-allocated APValue.
349+
unsigned HasCleanup : 1;
343350
};
344351

345352
class PredefinedExprBitfields {

clang/lib/AST/ASTContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@ void ASTContext::setTraversalScope(const std::vector<Decl *> &TopLevelDecls) {
908908
Parents.reset();
909909
}
910910

911-
void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) {
911+
void ASTContext::AddDeallocation(void (*Callback)(void *), void *Data) const {
912912
Deallocations.push_back({Callback, Data});
913913
}
914914

clang/lib/AST/Expr.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ ConstantExpr::ResultStorageKind
239239
ConstantExpr::getStorageKind(const APValue &Value) {
240240
switch (Value.getKind()) {
241241
case APValue::None:
242+
case APValue::Indeterminate:
242243
return ConstantExpr::RSK_None;
243244
case APValue::Int:
244245
if (!Value.getInt().needsCleanup())
@@ -249,9 +250,18 @@ ConstantExpr::getStorageKind(const APValue &Value) {
249250
}
250251
}
251252

253+
ConstantExpr::ResultStorageKind
254+
ConstantExpr::getStorageKind(const Type *T, const ASTContext &Context) {
255+
if (T->isIntegralOrEnumerationType() && Context.getTypeInfo(T).Width <= 64)
256+
return ConstantExpr::RSK_Int64;
257+
return ConstantExpr::RSK_APValue;
258+
}
259+
252260
void ConstantExpr::DefaultInit(ResultStorageKind StorageKind) {
253261
ConstantExprBits.ResultKind = StorageKind;
254-
if (StorageKind == RSK_APValue)
262+
ConstantExprBits.APValueKind = APValue::None;
263+
ConstantExprBits.HasCleanup = false;
264+
if (StorageKind == ConstantExpr::RSK_APValue)
255265
::new (getTrailingObjects<APValue>()) APValue();
256266
}
257267

@@ -269,16 +279,14 @@ ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E,
269279
StorageKind == ConstantExpr::RSK_Int64);
270280
void *Mem = Context.Allocate(Size, alignof(ConstantExpr));
271281
ConstantExpr *Self = new (Mem) ConstantExpr(E, StorageKind);
272-
if (StorageKind == ConstantExpr::RSK_APValue)
273-
Context.AddAPValueCleanup(&Self->APValueResult());
274282
return Self;
275283
}
276284

277285
ConstantExpr *ConstantExpr::Create(const ASTContext &Context, Expr *E,
278286
const APValue &Result) {
279287
ResultStorageKind StorageKind = getStorageKind(Result);
280288
ConstantExpr *Self = Create(Context, E, StorageKind);
281-
Self->SetResult(Result);
289+
Self->SetResult(Result, Context);
282290
return Self;
283291
}
284292

@@ -296,14 +304,13 @@ ConstantExpr *ConstantExpr::CreateEmpty(const ASTContext &Context,
296304
StorageKind == ConstantExpr::RSK_Int64);
297305
void *Mem = Context.Allocate(Size, alignof(ConstantExpr));
298306
ConstantExpr *Self = new (Mem) ConstantExpr(StorageKind, Empty);
299-
if (StorageKind == ConstantExpr::RSK_APValue)
300-
Context.AddAPValueCleanup(&Self->APValueResult());
301307
return Self;
302308
}
303309

304-
void ConstantExpr::MoveIntoResult(APValue &Value) {
310+
void ConstantExpr::MoveIntoResult(APValue &Value, const ASTContext &Context) {
305311
assert(getStorageKind(Value) == ConstantExprBits.ResultKind &&
306312
"Invalid storage for this value kind");
313+
ConstantExprBits.APValueKind = Value.getKind();
307314
switch (ConstantExprBits.ResultKind) {
308315
case RSK_None:
309316
return;
@@ -313,12 +320,28 @@ void ConstantExpr::MoveIntoResult(APValue &Value) {
313320
ConstantExprBits.IsUnsigned = Value.getInt().isUnsigned();
314321
return;
315322
case RSK_APValue:
323+
if (!ConstantExprBits.HasCleanup && Value.needsCleanup()) {
324+
ConstantExprBits.HasCleanup = true;
325+
Context.addDestruction(&APValueResult());
326+
}
316327
APValueResult() = std::move(Value);
317328
return;
318329
}
319330
llvm_unreachable("Invalid ResultKind Bits");
320331
}
321332

333+
llvm::APSInt ConstantExpr::getResultAsAPSInt() const {
334+
switch (ConstantExprBits.ResultKind) {
335+
case ConstantExpr::RSK_APValue:
336+
return APValueResult().getInt();
337+
case ConstantExpr::RSK_Int64:
338+
return llvm::APSInt(llvm::APInt(ConstantExprBits.BitWidth, Int64Result()),
339+
ConstantExprBits.IsUnsigned);
340+
default:
341+
llvm_unreachable("invalid Accessor");
342+
}
343+
}
344+
322345
APValue ConstantExpr::getAPValueResult() const {
323346
switch (ConstantExprBits.ResultKind) {
324347
case ConstantExpr::RSK_APValue:

clang/lib/AST/ExprConstant.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8963,6 +8963,8 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
89638963

89648964
bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) {
89658965
llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
8966+
if (E->getResultAPValueKind() != APValue::None)
8967+
return Success(E->getAPValueResult(), E);
89668968
return ExprEvaluatorBaseTy::VisitConstantExpr(E);
89678969
}
89688970

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14013,8 +14013,6 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
1401314013
ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
1401414014
if (Converted.isInvalid())
1401514015
Failed = true;
14016-
else
14017-
Converted = ConstantExpr::Create(Context, Converted.get());
1401814016

1401914017
llvm::APSInt Cond;
1402014018
if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond,

clang/lib/Sema/SemaExpr.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14538,14 +14538,13 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
1453814538
return ExprError();
1453914539
}
1454014540

14541-
if (!isa<ConstantExpr>(E))
14542-
E = ConstantExpr::Create(Context, E);
14543-
1454414541
// Circumvent ICE checking in C++11 to avoid evaluating the expression twice
1454514542
// in the non-ICE case.
1454614543
if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
1454714544
if (Result)
1454814545
*Result = E->EvaluateKnownConstIntCheckOverflow(Context);
14546+
if (!isa<ConstantExpr>(E))
14547+
E = ConstantExpr::Create(Context, E);
1454914548
return E;
1455014549
}
1455114550

@@ -14555,8 +14554,12 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
1455514554

1455614555
// Try to evaluate the expression, and produce diagnostics explaining why it's
1455714556
// not a constant expression as a side-effect.
14558-
bool Folded = E->EvaluateAsRValue(EvalResult, Context) &&
14559-
EvalResult.Val.isInt() && !EvalResult.HasSideEffects;
14557+
bool Folded =
14558+
E->EvaluateAsRValue(EvalResult, Context, /*isConstantContext*/ true) &&
14559+
EvalResult.Val.isInt() && !EvalResult.HasSideEffects;
14560+
14561+
if (!isa<ConstantExpr>(E))
14562+
E = ConstantExpr::Create(Context, E, EvalResult.Val);
1456014563

1456114564
// In C++11, we can rely on diagnostics being produced for any expression
1456214565
// which is not a constant expression. If no diagnostics were produced, then

0 commit comments

Comments
 (0)