aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.cpp17
-rw-r--r--clang/test/AST/Interp/arrays.cpp8
2 files changed, 22 insertions, 3 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index a27a0cb..975d3b6 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -3237,9 +3237,20 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
// Try to lazily visit (or emit dummy pointers for) declarations
// we haven't seen yet.
if (Ctx.getLangOpts().CPlusPlus) {
- if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isStaticLocal()) {
- if (std::optional<unsigned> I = P.getOrCreateDummy(D))
- return this->emitGetPtrGlobal(*I, E);
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ // Dummy for static locals
+ if (VD->isStaticLocal()) {
+ if (std::optional<unsigned> I = P.getOrCreateDummy(D))
+ return this->emitGetPtrGlobal(*I, E);
+ return false;
+ }
+ // Visit local const variables like normal.
+ if (VD->isLocalVarDecl() && VD->getType().isConstQualified()) {
+ if (!this->visitVarDecl(VD))
+ return false;
+ // Retry.
+ return this->VisitDeclRefExpr(E);
+ }
}
} else {
if (const auto *VD = dyn_cast<VarDecl>(D);
diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp
index 3c06ab5..a9450d8 100644
--- a/clang/test/AST/Interp/arrays.cpp
+++ b/clang/test/AST/Interp/arrays.cpp
@@ -537,3 +537,11 @@ namespace SelfComparison {
return s3->array[t.field] == s3->array[t.field]; // both-warning {{self-comparison always evaluates to true}}
};
}
+
+namespace LocalIndex {
+ void test() {
+ const int const_subscript = 3;
+ int array[2]; // both-note {{declared here}}
+ array[const_subscript] = 0; // both-warning {{array index 3 is past the end of the array (that has type 'int[2]')}}
+ }
+}