[clang] 4b03dd7 - PR45534: don't ignore unmodeled side-effects when constant-evaluating a call to __builtin_constant_p.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 20 21:23:42 PDT 2020
Author: Richard Smith
Date: 2020-04-20T21:23:35-07:00
New Revision: 4b03dd7b849e8f5068dc8d72c6eab724c22a2805
URL: https://github.com/llvm/llvm-project/commit/4b03dd7b849e8f5068dc8d72c6eab724c22a2805
DIFF: https://github.com/llvm/llvm-project/commit/4b03dd7b849e8f5068dc8d72c6eab724c22a2805.diff
LOG: PR45534: don't ignore unmodeled side-effects when constant-evaluating a call to __builtin_constant_p.
Such side-effects should result in the call evaluating to 'false', even
if we can still determine what value the argument expression will
evaluate to.
Added:
Modified:
clang/lib/AST/ExprConstant.cpp
clang/test/SemaCXX/builtin-constant-p.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8bc7a1128e7a..ad61221a6a91 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10438,7 +10438,7 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
ArgType->isAnyComplexType() || ArgType->isPointerType() ||
ArgType->isNullPtrType()) {
APValue V;
- if (!::EvaluateAsRValue(Info, Arg, V)) {
+ if (!::EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects) {
Fold.keepDiagnostics();
return false;
}
diff --git a/clang/test/SemaCXX/builtin-constant-p.cpp b/clang/test/SemaCXX/builtin-constant-p.cpp
index f70676d250e0..1b8cf455ef27 100644
--- a/clang/test/SemaCXX/builtin-constant-p.cpp
+++ b/clang/test/SemaCXX/builtin-constant-p.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++17 -verify %s
+// RUN: %clang_cc1 -std=c++20 -verify %s
using intptr_t = __INTPTR_TYPE__;
@@ -135,3 +136,33 @@ static_assert(mutate6(true) == 10);
// not being a pointer to the start of a string literal.
namespace std { struct type_info; }
static_assert(__builtin_constant_p(&typeid(int)));
+
+void mutate_as_side_effect() {
+ int a;
+ static_assert(!__builtin_constant_p(((void)++a, 1)));
+}
+
+namespace dtor_side_effect {
+ struct A {
+ constexpr A() {}
+ ~A();
+ };
+ static_assert(!__builtin_constant_p((A{}, 123)));
+}
+
+#if __cplusplus >= 202002L
+namespace constexpr_dtor {
+ struct A {
+ int *p;
+ constexpr ~A() { *p = 0; }
+ };
+ struct Q { int n; constexpr int *get() { return &n; } };
+ static_assert(!__builtin_constant_p((A{}, 123)));
+ // FIXME: We should probably accept this. GCC does.
+ // However, GCC appears to do so by running the destructors at the end of the
+ // enclosing full-expression, which seems broken; running them at the end of
+ // the evaluation of the __builtin_constant_p argument would be more
+ // defensible.
+ static_assert(!__builtin_constant_p((A{Q().get()}, 123)));
+}
+#endif
More information about the cfe-commits
mailing list