From 159f25301763215ffc49c3c3aa6cb8095a990b41 Mon Sep 17 00:00:00 2001 From: Timm Baeder Date: Mon, 21 Oct 2024 12:07:09 +0200 Subject: [PATCH] [clang][bytecode] Diagnose invalid declrefs differently if we've... (#113140) ... tried their initializer already. In that case, diagnose the non-const initializer instead of the reference to a non-constexpr variable later. This is used in a lot of openmp tests. --- clang/lib/AST/ByteCode/Compiler.cpp | 5 +++-- clang/lib/AST/ByteCode/Interp.h | 13 +++++++++++-- clang/lib/AST/ByteCode/Opcodes.td | 2 +- clang/test/AST/ByteCode/openmp.cpp | 13 +++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 clang/test/AST/ByteCode/openmp.cpp diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 3f068aa8c189a9..b960954d4754a8 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -6097,7 +6097,8 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { if (VD->evaluateValue()) return revisit(VD); - return this->emitInvalidDeclRef(cast(E), E); + return this->emitInvalidDeclRef(cast(E), + /*InitializerFailed=*/true, E); } } } else { @@ -6123,7 +6124,7 @@ bool Compiler::visitDeclRef(const ValueDecl *D, const Expr *E) { } if (const auto *DRE = dyn_cast(E)) - return this->emitInvalidDeclRef(DRE, E); + return this->emitInvalidDeclRef(DRE, /*InitializerFailed=*/false, E); return false; } diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 1469fac5a17776..c95b18ef72c966 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2818,9 +2818,18 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, return false; } -inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, - const DeclRefExpr *DR) { +inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR, + bool InitializerFailed) { assert(DR); + + if (InitializerFailed) { + const SourceInfo &Loc = S.Current->getSource(OpPC); + const auto *VD = cast(DR->getDecl()); + S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD; + S.Note(VD->getLocation(), diag::note_declared_at); + return false; + } + return CheckDeclRef(S, OpPC, DR); } diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index a1970f25ca977f..9136e6b51660d0 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -769,7 +769,7 @@ def InvalidCast : Opcode { } def InvalidDeclRef : Opcode { - let Args = [ArgDeclRef]; + let Args = [ArgDeclRef, ArgBool]; } def SizelessVectorElementSize : Opcode; diff --git a/clang/test/AST/ByteCode/openmp.cpp b/clang/test/AST/ByteCode/openmp.cpp new file mode 100644 index 00000000000000..e05fbe086625c8 --- /dev/null +++ b/clang/test/AST/ByteCode/openmp.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both -fopenmp %s +// RUN: %clang_cc1 -verify=ref,both -fopenmp %s + +int test1() { + int i; + int &j = i; // both-note {{declared here}} + float *f; + // both-note@+2 {{initializer of 'j' is not a constant expression}} + // both-error@+1 {{integral constant expression}} + #pragma omp for simd aligned(f:j) + for (int i = 0; i < 10; ++i); +} +