Author: Timm Baeder Date: 2026-07-13T12:19:26+02:00 New Revision: 717615829bba4035897a4ebdbdef919f31529762
URL: https://github.com/llvm/llvm-project/commit/717615829bba4035897a4ebdbdef919f31529762 DIFF: https://github.com/llvm/llvm-project/commit/717615829bba4035897a4ebdbdef919f31529762.diff LOG: [clang][bytecode] Improve diagnostics on typeid field access (#209101) Do some extra work to extract the requested field name. Added: Modified: clang/lib/AST/ByteCode/Interp.cpp clang/test/AST/ByteCode/typeid.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 20235b07fcc47..58bbf4aaf5f89 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1564,6 +1564,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() && @@ -1587,12 +1615,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() ; }; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
