[clang][Interp] Emit dummy values for unknown C variables (#66749)
We can't load anything from them, but we can still take their address or return them as lvalues.
This commit is contained in:
@@ -2547,6 +2547,9 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
|
||||
// Retry.
|
||||
return this->VisitDeclRefExpr(E);
|
||||
}
|
||||
|
||||
if (std::optional<unsigned> I = P.getOrCreateDummy(D))
|
||||
return this->emitGetPtrGlobal(*I, E);
|
||||
}
|
||||
|
||||
return this->emitInvalidDeclRef(E, E);
|
||||
|
||||
@@ -139,7 +139,7 @@ bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
|
||||
if (!Ptr.isExtern())
|
||||
return true;
|
||||
|
||||
if (!S.checkingPotentialConstantExpression()) {
|
||||
if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {
|
||||
const auto *VD = Ptr.getDeclDesc()->asValueDecl();
|
||||
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
||||
S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
|
||||
|
||||
@@ -138,17 +138,16 @@ std::optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD,
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
|
||||
|
||||
std::optional<unsigned> Program::getOrCreateDummy(const ValueDecl *PD) {
|
||||
// Dedup blocks since they are immutable and pointers cannot be compared.
|
||||
if (auto It = DummyParams.find(PD);
|
||||
It != DummyParams.end())
|
||||
return It->second;
|
||||
|
||||
auto &ASTCtx = Ctx.getASTContext();
|
||||
// Create a pointer to an incomplete array of the specified elements.
|
||||
QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
|
||||
QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
|
||||
QualType ElemTy = PD->getType();
|
||||
QualType Ty =
|
||||
Ctx.getASTContext().getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
|
||||
|
||||
if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
|
||||
DummyParams[PD] = *Idx;
|
||||
|
||||
@@ -82,8 +82,8 @@ public:
|
||||
std::optional<unsigned> getOrCreateGlobal(const ValueDecl *VD,
|
||||
const Expr *Init = nullptr);
|
||||
|
||||
/// Returns or creates a dummy value for parameters.
|
||||
std::optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD);
|
||||
/// Returns or creates a dummy value for unknown declarations.
|
||||
std::optional<unsigned> getOrCreateDummy(const ValueDecl *PD);
|
||||
|
||||
/// Creates a global and returns its index.
|
||||
std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *E);
|
||||
@@ -208,7 +208,7 @@ private:
|
||||
llvm::DenseMap<const RecordDecl *, Record *> Records;
|
||||
|
||||
/// Dummy parameter to generate pointers from.
|
||||
llvm::DenseMap<const ParmVarDecl *, unsigned> DummyParams;
|
||||
llvm::DenseMap<const ValueDecl *, unsigned> DummyParams;
|
||||
|
||||
/// Creates a new descriptor.
|
||||
template <typename... Ts>
|
||||
|
||||
@@ -28,15 +28,25 @@ const int b = 3;
|
||||
_Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
|
||||
// pedantic-expected-warning {{not an integer constant expression}}
|
||||
|
||||
/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics.
|
||||
const int c; // ref-note {{declared here}} \
|
||||
// pedantic-ref-note {{declared here}} \
|
||||
// expected-note {{declared here}} \
|
||||
// pedantic-expected-note {{declared here}}
|
||||
// pedantic-ref-note {{declared here}}
|
||||
_Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \
|
||||
// ref-note {{initializer of 'c' is unknown}} \
|
||||
// pedantic-ref-error {{not an integral constant expression}} \
|
||||
// pedantic-ref-note {{initializer of 'c' is unknown}} \
|
||||
// expected-error {{not an integral constant expression}} \
|
||||
// expected-note {{initializer of 'c' is unknown}} \
|
||||
// pedantic-expected-error {{not an integral constant expression}} \
|
||||
// pedantic-expected-note {{initializer of 'c' is unknown}}
|
||||
// pedantic-expected-error {{not an integral constant expression}}
|
||||
|
||||
_Static_assert(&c != 0, ""); // ref-warning {{always true}} \
|
||||
// pedantic-ref-warning {{always true}} \
|
||||
// pedantic-ref-warning {{is a GNU extension}} \
|
||||
// expected-warning {{always true}} \
|
||||
// pedantic-expected-warning {{always true}} \
|
||||
// pedantic-expected-warning {{is a GNU extension}}
|
||||
_Static_assert(&a != 0, ""); // ref-warning {{always true}} \
|
||||
// pedantic-ref-warning {{always true}} \
|
||||
// pedantic-ref-warning {{is a GNU extension}} \
|
||||
// expected-warning {{always true}} \
|
||||
// pedantic-expected-warning {{always true}} \
|
||||
// pedantic-expected-warning {{is a GNU extension}}
|
||||
|
||||
Reference in New Issue
Block a user