[clang] [clang][bytecode] Improve diagnostis on typeid field access (PR #209101)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 13 00:43:08 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
Do some extra work to extract the requested field name.
---
Full diff: https://github.com/llvm/llvm-project/pull/209101.diff
2 Files Affected:
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+32-6)
- (modified) clang/test/AST/ByteCode/typeid.cpp (+5)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 0adcdfe6e78c9..f5ffca0d0fa8b 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1554,6 +1554,34 @@ bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T) {
return false;
}
+static bool diagnoseTypeIdField(InterpState &S, CodePtr OpPC,
+ const Pointer &Ptr, unsigned Offset) {
+ assert(Ptr.isTypeidPointer());
+ const Record *R = S.getContext().getRecord(
+ Ptr.asTypeidPointer().TypeInfoType->getAsRecordDecl());
+ if (!R)
+ return false;
+ const Record::Field *Field =
+ llvm::find_if(R->fields(), [=](const Record::Field &F) -> bool {
+ return F.Offset == Offset;
+ });
+ if (!Field)
+ return false;
+
+ std::string TypeIdStr;
+ llvm::raw_string_ostream SS(TypeIdStr);
+ SS << "typeid(";
+ QualType(Ptr.asTypeidPointer().TypePtr, 0)
+ .print(SS, S.getASTContext().getPrintingPolicy());
+ SS << ").";
+ SS << Field->Decl->getNameAsString();
+
+ S.FFDiag(S.Current->getSource(OpPC),
+ diag::note_constexpr_access_unreadable_object)
+ << AK_Read << TypeIdStr;
+ return false;
+}
+
static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
uint32_t Off) {
if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
@@ -1577,12 +1605,10 @@ static bool getField(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
}
if (!Ptr.isBlockPointer()) {
- // FIXME: The only time we (seem to) get here is when trying to access a
- // field of a typeid pointer. In that case, we're supposed to diagnose e.g.
- // `typeid(int).name`, but we currently diagnose `&typeid(int)`.
- S.FFDiag(S.Current->getSource(OpPC),
- diag::note_constexpr_access_unreadable_object)
- << AK_Read << Ptr.toDiagnosticString(S.getASTContext());
+ // If we're trying to get the field of a TypeId pointer, try to produce a
+ // proper diagnostic.
+ if (Ptr.isTypeidPointer())
+ return diagnoseTypeIdField(S, OpPC, Ptr, Off);
return false;
}
diff --git a/clang/test/AST/ByteCode/typeid.cpp b/clang/test/AST/ByteCode/typeid.cpp
index 4e7664f505c23..4b9c024632354 100644
--- a/clang/test/AST/ByteCode/typeid.cpp
+++ b/clang/test/AST/ByteCode/typeid.cpp
@@ -22,6 +22,8 @@ class type_info : public __pointer_type_info {
protected:
typedef __type_info_implementations::__impl __impl;
__impl::__type_name_t __type_name;
+public:
+ const char *name;
};
}; // namespace std
@@ -32,6 +34,9 @@ static_assert(&typeid(int) < &typeid(long)); // both-error {{not an integral con
static_assert(&typeid(int) > &typeid(long)); // both-error {{not an integral constant expression}} \
// both-note {{comparison between pointers to unrelated objects '&typeid(int)' and '&typeid(long)' has unspecified value}}
+constexpr auto name = typeid(int).name; // both-error {{constant expression}} \
+ // both-note {{read of object 'typeid(int).name' whose value is not known}}
+
struct Base {
virtual void func() ;
};
``````````
</details>
https://github.com/llvm/llvm-project/pull/209101
More information about the cfe-commits
mailing list