-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[clang][bytecode] Misc TypeidPointer fixes #135322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Fix comparing type id pointers, add mor info when print()ing them, use the most derived type in GetTypeidPtr() and the canonically unqualified type when we know the type statically.
|
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesFix comparing type id pointers, add mor info when print()ing them, use the most derived type in GetTypeidPtr() and the canonically unqualified type when we know the type statically. Full diff: https://github.com/llvm/llvm-project/pull/135322.diff 6 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index eafe735c2dce1..86b43585cd292 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3629,15 +3629,22 @@ template <class Emitter>
bool Compiler<Emitter>::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
const Type *TypeInfoType = E->getType().getTypePtr();
+ auto canonType = [](const Type *T) {
+ return T->getCanonicalTypeUnqualified().getTypePtr();
+ };
+
if (!E->isPotentiallyEvaluated()) {
if (DiscardResult)
return true;
if (E->isTypeOperand())
return this->emitGetTypeid(
- E->getTypeOperand(Ctx.getASTContext()).getTypePtr(), TypeInfoType, E);
- return this->emitGetTypeid(E->getExprOperand()->getType().getTypePtr(),
- TypeInfoType, E);
+ canonType(E->getTypeOperand(Ctx.getASTContext()).getTypePtr()),
+ TypeInfoType, E);
+
+ return this->emitGetTypeid(
+ canonType(E->getExprOperand()->getType().getTypePtr()), TypeInfoType,
+ E);
}
// Otherwise, we need to evaluate the expression operand.
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 768ae6e49b13e..0afd772c73b85 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1848,7 +1848,23 @@ bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType) {
if (!P.isBlockPointer())
return false;
- S.Stk.push<Pointer>(P.getType().getTypePtr(), TypeInfoType);
+ // Pick the most-derived type.
+ const Type *T = P.getDeclPtr().getType().getTypePtr();
+ // ... unless we're currently constructing this object.
+ // FIXME: We have a similar check to this in more places.
+ if (S.Current->getFunction()) {
+ for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
+ if (const Function *Func = Frame->getFunction();
+ Func && (Func->isConstructor() || Func->isDestructor()) &&
+ P.block() == Frame->getThis().block()) {
+ T = Func->getParentDecl()->getTypeForDecl();
+ break;
+ }
+ }
+ }
+
+ S.Stk.push<Pointer>(T->getCanonicalTypeUnqualified().getTypePtr(),
+ TypeInfoType);
return true;
}
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index e5813d6f7c982..4e84dcc8d551d 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1006,7 +1006,8 @@ inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
const Pointer &LHS = S.Stk.pop<Pointer>();
// Function pointers cannot be compared in an ordered way.
- if (LHS.isFunctionPointer() || RHS.isFunctionPointer()) {
+ if (LHS.isFunctionPointer() || RHS.isFunctionPointer() ||
+ LHS.isTypeidPointer() || RHS.isTypeidPointer()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
<< LHS.toDiagnosticString(S.getASTContext())
@@ -2478,13 +2479,15 @@ inline bool This(InterpState &S, CodePtr OpPC) {
// Ensure the This pointer has been cast to the correct base.
if (!This.isDummy()) {
assert(isa<CXXMethodDecl>(S.Current->getFunction()->getDecl()));
- [[maybe_unused]] const Record *R = This.getRecord();
- if (!R)
- R = This.narrow().getRecord();
- assert(R);
- assert(
- R->getDecl() ==
- cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())->getParent());
+ if (!This.isTypeidPointer()) {
+ [[maybe_unused]] const Record *R = This.getRecord();
+ if (!R)
+ R = This.narrow().getRecord();
+ assert(R);
+ assert(R->getDecl() ==
+ cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())
+ ->getParent());
+ }
}
S.Stk.push<Pointer>(This);
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 918a434301461..c09d3224b1f36 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -342,7 +342,9 @@ void Pointer::print(llvm::raw_ostream &OS) const {
<< " }";
break;
case Storage::Typeid:
- OS << "(Typeid)";
+ OS << "(Typeid) { " << (const void *)asTypeidPointer().TypePtr << ", "
+ << (const void *)asTypeidPointer().TypeInfoType << " + " << Offset
+ << "}";
}
}
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index f892cf1159b55..5eef9d2e1885e 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -469,6 +469,10 @@ class Pointer {
assert(isFunctionPointer());
return PointeeStorage.Fn;
}
+ [[nodiscard]] const TypeidPointer &asTypeidPointer() const {
+ assert(isTypeidPointer());
+ return PointeeStorage.Typeid;
+ }
bool isBlockPointer() const { return StorageKind == Storage::Block; }
bool isIntegralPointer() const { return StorageKind == Storage::Int; }
@@ -577,6 +581,8 @@ class Pointer {
uint64_t getByteOffset() const {
if (isIntegralPointer())
return asIntPointer().Value + Offset;
+ if (isTypeidPointer())
+ return reinterpret_cast<uintptr_t>(asTypeidPointer().TypePtr) + Offset;
if (isOnePastEnd())
return PastEndMark;
return Offset;
diff --git a/clang/test/AST/ByteCode/typeid.cpp b/clang/test/AST/ByteCode/typeid.cpp
new file mode 100644
index 0000000000000..5be5604016db5
--- /dev/null
+++ b/clang/test/AST/ByteCode/typeid.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s
+// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
+
+namespace std {
+struct __type_info_implementations {
+ struct __string_impl_base {
+ typedef const char *__type_name_t;
+ };
+ struct __unique_impl : __string_impl_base {
+
+ static bool __eq(__type_name_t __lhs, __type_name_t __rhs);
+ };
+ typedef __unique_impl __impl;
+};
+
+class type_info {
+protected:
+ typedef __type_info_implementations::__impl __impl;
+ __impl::__type_name_t __type_name;
+};
+}; // namespace std
+
+static_assert(&typeid(int) != &typeid(long));
+static_assert(&typeid(int) == &typeid(int));
+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}}
+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}}
+
+ struct Base {
+ virtual void func() ;
+ };
+ struct Derived : Base {};
+
+constexpr bool test() {
+ Derived derived;
+ Base const &as_base = derived;
+ if (&typeid(as_base) != &typeid(Derived))
+ __builtin_abort();
+ return true;
+}
+static_assert(test());
|
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/186/builds/8116 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/52/builds/7500 Here is the relevant piece of the build log for the reference |
Fix comparing type id pointers, add mor info when print()ing them, use the most derived type in GetTypeidPtr() and the canonically unqualified type when we know the type statically.