Skip to content

Commit 9ece3eb

Browse files
committed
[clang][Interp] Check ConstantExpr results for initialization
They need to be fully initialized, similar to global variables.
1 parent 74d62c2 commit 9ece3eb

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

clang/lib/AST/Interp/EvalEmitter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
4141
bool ConvertResultToRValue) {
4242
S.setEvalLocation(E->getExprLoc());
4343
this->ConvertResultToRValue = ConvertResultToRValue;
44+
this->CheckFullyInitialized = isa<ConstantExpr>(E);
4445
EvalResult.setSource(E);
4546

4647
if (!this->visitExpr(E)) {
@@ -175,6 +176,10 @@ bool EvalEmitter::emitRetVoid(const SourceInfo &Info) {
175176

176177
bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
177178
const auto &Ptr = S.Stk.pop<Pointer>();
179+
180+
if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
181+
return false;
182+
178183
if (std::optional<APValue> APV = Ptr.toRValue(S.getCtx())) {
179184
EvalResult.setValue(*APV);
180185
return true;

clang/lib/AST/Interp/EvaluationResult.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,14 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S,
141141
const Pointer &Ptr) const {
142142
assert(Source);
143143
assert(empty());
144-
145-
// Our Source must be a VarDecl.
146-
const Decl *SourceDecl = Source.dyn_cast<const Decl *>();
147-
assert(SourceDecl);
148-
const auto *VD = cast<VarDecl>(SourceDecl);
149-
assert(VD->getType()->isRecordType() || VD->getType()->isArrayType());
150-
SourceLocation InitLoc = VD->getAnyInitializer()->getExprLoc();
151-
152144
assert(!Ptr.isZero());
153145

146+
SourceLocation InitLoc;
147+
if (const auto *D = Source.dyn_cast<const Decl *>())
148+
InitLoc = cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
149+
else if (const auto *E = Source.dyn_cast<const Expr *>())
150+
InitLoc = E->getExprLoc();
151+
154152
if (const Record *R = Ptr.getRecord())
155153
return CheckFieldsInitialized(S, InitLoc, Ptr, R);
156154
const auto *CAT =

clang/test/AST/Interp/cxx20.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,3 +797,20 @@ namespace self_referencing {
797797
S s(1);
798798
}
799799
}
800+
801+
namespace GH64949 {
802+
struct f {
803+
int g; // both-note {{subobject declared here}}
804+
constexpr ~f() {}
805+
};
806+
807+
class h {
808+
public:
809+
consteval h(char *) {}
810+
f i;
811+
};
812+
813+
void test() { h{nullptr}; } // both-error {{call to consteval function 'GH64949::h::h' is not a constant expression}} \
814+
// both-note {{subobject 'g' is not initialized}} \
815+
// both-warning {{expression result unused}}
816+
}

0 commit comments

Comments
 (0)