Skip to content

Commit 9563746

Browse files
committed
[clang][Interp] Diagnose uninitialized global variables explicitly
There used to be some diagnostic differences between the new interpreter and the old one.
1 parent dfb70c3 commit 9563746

File tree

4 files changed

+28
-23
lines changed

4 files changed

+28
-23
lines changed

clang/lib/AST/Interp/Descriptor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ struct Descriptor final {
165165
return dyn_cast_if_present<ValueDecl>(asDecl());
166166
}
167167

168+
const VarDecl *asVarDecl() const {
169+
return dyn_cast_if_present<VarDecl>(asDecl());
170+
}
171+
168172
const FieldDecl *asFieldDecl() const {
169173
return dyn_cast_if_present<FieldDecl>(asDecl());
170174
}

clang/lib/AST/Interp/Interp.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,18 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
357357

358358
bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
359359
AccessKinds AK) {
360+
assert(Ptr.isLive());
361+
360362
if (Ptr.isInitialized())
361363
return true;
362364

363365
if (!S.checkingPotentialConstantExpression()) {
366+
if (const auto *VD = Ptr.getDeclDesc()->asVarDecl();
367+
VD && VD->hasGlobalStorage()) {
368+
const SourceInfo &Loc = S.Current->getSource(OpPC);
369+
S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
370+
S.Note(VD->getLocation(), diag::note_declared_at);
371+
}
364372
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit)
365373
<< AK << /*uninitialized=*/true << S.Current->getRange(OpPC);
366374
}

clang/test/AST/Interp/cxx17.cpp

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify %s
2-
// RUN: %clang_cc1 -std=c++17 -verify=ref %s
1+
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=expected,both %s
2+
// RUN: %clang_cc1 -std=c++17 -verify=ref,both %s
33

44
struct F { int a; int b;};
55
constexpr F getF() {
@@ -81,22 +81,15 @@ constexpr int b() {
8181
}
8282
static_assert(b() == 11);
8383

84-
/// The diagnostics between the two interpreters are different here.
84+
/// The diagnostics between the two interpreters used to be different here.
8585
struct S { int a; };
86-
constexpr S getS() { // expected-error {{constexpr function never produces a constant expression}} \\
87-
// ref-error {{constexpr function never produces a constant expression}}
88-
(void)(1/0); // expected-note 2{{division by zero}} \
89-
// expected-warning {{division by zero}} \
90-
// ref-note 2{{division by zero}} \
91-
// ref-warning {{division by zero}}
86+
constexpr S getS() { // both-error {{constexpr function never produces a constant expression}}
87+
(void)(1/0); // both-note 2{{division by zero}} \
88+
// both-warning {{division by zero}}
9289
return S{12};
9390
}
94-
constexpr S s = getS(); // expected-error {{must be initialized by a constant expression}} \
95-
// expected-note {{in call to 'getS()'}} \
96-
// ref-error {{must be initialized by a constant expression}} \\
97-
// ref-note {{in call to 'getS()'}} \
98-
// ref-note {{declared here}}
99-
static_assert(s.a == 12, ""); // expected-error {{not an integral constant expression}} \
100-
// expected-note {{read of uninitialized object}} \
101-
// ref-error {{not an integral constant expression}} \
102-
// ref-note {{initializer of 's' is not a constant expression}}
91+
constexpr S s = getS(); // both-error {{must be initialized by a constant expression}} \
92+
// both-note {{in call to 'getS()'}} \
93+
// both-note {{declared here}}
94+
static_assert(s.a == 12, ""); // both-error {{not an integral constant expression}} \
95+
// both-note {{initializer of 's' is not a constant expression}}

clang/test/AST/Interp/records.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,10 @@ namespace DeriveFailures {
420420

421421
constexpr Derived D(12); // both-error {{must be initialized by a constant expression}} \
422422
// both-note {{in call to 'Derived(12)'}} \
423-
// ref-note {{declared here}}
423+
// both-note {{declared here}}
424424

425425
static_assert(D.Val == 0, ""); // both-error {{not an integral constant expression}} \
426-
// ref-note {{initializer of 'D' is not a constant expression}} \
427-
// expected-note {{read of uninitialized object}}
426+
// both-note {{initializer of 'D' is not a constant expression}}
428427
#endif
429428

430429
struct AnotherBase {
@@ -478,10 +477,11 @@ namespace ConditionalInit {
478477
namespace DeclRefs {
479478
struct A{ int m; const int &f = m; }; // expected-note {{implicit use of 'this'}}
480479

481-
constexpr A a{10}; // expected-error {{must be initialized by a constant expression}}
480+
constexpr A a{10}; // expected-error {{must be initialized by a constant expression}} \
481+
// expected-note {{declared here}}
482482
static_assert(a.m == 10, "");
483483
static_assert(a.f == 10, ""); // expected-error {{not an integral constant expression}} \
484-
// expected-note {{read of uninitialized object}}
484+
// expected-note {{initializer of 'a' is not a constant expression}}
485485

486486
class Foo {
487487
public:

0 commit comments

Comments
 (0)