Skip to content

Commit 69b9718

Browse files
author
Andres Madrid Ucha
committed
Clang: Fix mismatch in elementtype
When processing thunk functions and elementtypes with inheritance, there were logic errors in the direct base checking that could lead to incorrect function types being retained. The issue occurred in the following case: 1. Initial comparison: CurrentThisStructTy (ios_base) == NewThisTy (ios_base) - Both types are the same, so NewIsDirectBase is incorrectly set to true - ThunkFn type: void (%class._ZSt8ios_base*) - ThunkFnTy: (%class._ZSt8ios_base*) - Since types match, no update occurs 2. Second comparison: CurrentThisStructTy != NewThisTy - ThunkFn then gets updated to void (%class._ZSt9basic_iosIcSt11char_traitsIcEE*) - This is correct behavior 3. Third comparison: Same types again (ios_base == ios_base) - NewIsDirectBase is again set to true, which will then affect updating the ThunkFn - Current ThunkFn: void (%class._ZSt9basic_iosIcSt11char_traitsIcEE*) but the one we want to update to is void (%class._ZSt8ios_base*) - Because NewIsDirectBase is true, the update is skipped eventhough ThunkFn != ThunkFnTy. This leaves ThunkFn with the wrong type
1 parent 4240a25 commit 69b9718

File tree

1 file changed

+21
-33
lines changed

1 file changed

+21
-33
lines changed

clang/lib/CodeGen/CGVTables.cpp

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -577,57 +577,44 @@ llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
577577

578578
int thisIndex = ThunkFn->hasStructRetAttr() && !FnInfo.getReturnInfo().isSRetAfterThis() ? 1 : 0;
579579

580-
// CurrentThisTy is the value used for elementtype attribute
581-
// Extract the pointee type from the actual parameter to ensure consistency
582-
// between the function signature and the elementtype attribute
583-
llvm::Type* CurrentThisTy = nullptr;
584-
585-
if (thisIndex < ThunkFn->arg_size()) {
586-
llvm::Argument* ThisArg = ThunkFn->getArg(thisIndex);
587-
llvm::Type* ActualParamType = ThisArg->getType();
588-
auto* PtrTy = dyn_cast<llvm::PointerType>(ActualParamType);
589-
// The getPointerElementType function is depricated for Opaque pointers
590-
if (PtrTy && !PtrTy->isOpaque())
591-
CurrentThisTy = PtrTy->getPointerElementType();
592-
}
593-
594-
if (CurrentThisTy == nullptr)
595-
CurrentThisTy = CGM.getTypes().ConvertTypeForMem(cast<PointerType>(FnInfo.arg_begin()->type)->getPointeeType());
596-
597-
598-
if (!ThunkFn->hasParamAttribute(thisIndex, llvm::Attribute::ElementType))
599-
ThunkFn->addParamAttr(thisIndex, llvm::Attribute::get(CGM.getLLVMContext(), llvm::Attribute::ElementType, CurrentThisTy));
580+
llvm::Type* CurrentThisTy = CGM.getTypes().ConvertTypeForMem(cast<PointerType>(FnInfo.arg_begin()->type)->getPointeeType());
600581

601582
// If the type of the underlying GlobalValue is wrong, we'll have to replace
602583
// it. It should be a declaration.
603584
// CHEERP: If there are virtual bases it is possible that the type of `this` mismatches
604585
// between the existing and new think, but one is directbase of the other.
605586
// We keep the thunk with the most basic `this` type
587+
588+
if (!ThunkFn->hasParamAttribute(thisIndex, llvm::Attribute::ElementType))
589+
ThunkFn->addParamAttr(thisIndex, llvm::Attribute::get(CGM.getLLVMContext(), llvm::Attribute::ElementType, CurrentThisTy));
590+
606591
bool NewIsDirectBase = false;
607592
bool CurrentIsDirectBase = false;
608593
if (!CGM.getTarget().isByteAddressable()) {
609-
// Geth the `this` type. It can be the first or second parameter (if there is a
594+
// Get the `this` type. It can be the first or second parameter (if there is a
610595
// struct return pointer)
611596
llvm::StructType* CurrentThisStructTy = cast<llvm::StructType>(CurrentThisTy);
612597
llvm::StructType* NewThisTy = cast<llvm::StructType>(ThunkFn->getParamAttribute(thisIndex, llvm::Attribute::ElementType).getValueAsType());
613-
614-
// Check if one of the types is directbase of the other (check all the directbase hierarchy)
615-
for (llvm::StructType* I = NewThisTy; I != nullptr; I = I->getDirectBase()) {
616-
if (I == CurrentThisTy) {
617-
NewIsDirectBase = true;
618-
break;
598+
// If the attribute type is the same as current, or doesn't exist, skip the directbase check
599+
if (NewThisTy && NewThisTy != CurrentThisTy) {
600+
// Check if one of the types is directbase of the other (check all the directbase hierarchy)
601+
for (llvm::StructType* I = NewThisTy; I != nullptr; I = I->getDirectBase()) {
602+
if (I == CurrentThisTy) {
603+
NewIsDirectBase = true;
604+
break;
605+
}
619606
}
620-
}
621-
for (llvm::StructType* I = CurrentThisStructTy; I != nullptr; I = I->getDirectBase()) {
622-
if (I == NewThisTy) {
623-
CurrentIsDirectBase = true;
624-
break;
607+
for (llvm::StructType* I = CurrentThisStructTy; I != nullptr; I = I->getDirectBase()) {
608+
if (I == NewThisTy) {
609+
CurrentIsDirectBase = true;
610+
break;
611+
}
625612
}
626613
}
627614
}
615+
628616
if (ThunkFn->getFunctionType() != ThunkFnTy && !NewIsDirectBase) {
629617
llvm::GlobalValue *OldThunkFn = ThunkFn;
630-
631618
// If the types mismatch then we have to rewrite the definition.
632619
assert((OldThunkFn->isDeclaration() || CurrentIsDirectBase) &&
633620
"Shouldn't replace non-declaration");
@@ -651,6 +638,7 @@ llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
651638
OldThunkFn->eraseFromParent();
652639
}
653640

641+
654642
bool ABIHasKeyFunctions = CGM.getTarget().getCXXABI().hasKeyFunctions();
655643
bool UseAvailableExternallyLinkage = ForVTable && ABIHasKeyFunctions;
656644

0 commit comments

Comments
 (0)