| //===--- ItaniumCXXABIUtils.cpp - Shared Itanium C++ ABI queries ----------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/CodeGenUtils/ItaniumCXXABIUtils.h" |
| #include "clang/AST/CXXInheritance.h" |
| #include "clang/AST/RecordLayout.h" |
| |
| namespace clang::CodeGenUtils { |
| |
| CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, |
| const CXXRecordDecl *Dst) { |
| CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, |
| /*DetectVirtual=*/false); |
| |
| // If Dst is not derived from Src we can skip the whole computation below and |
| // return that Src is not a public base of Dst. Record all inheritance paths. |
| if (!Dst->isDerivedFrom(Src, Paths)) |
| return CharUnits::fromQuantity(-2ULL); |
| |
| unsigned NumPublicPaths = 0; |
| CharUnits Offset; |
| |
| // Now walk all possible inheritance paths. |
| for (const CXXBasePath &Path : Paths) { |
| if (Path.Access != AS_public) // Ignore non-public inheritance. |
| continue; |
| |
| ++NumPublicPaths; |
| |
| for (const CXXBasePathElement &PathElement : Path) { |
| // If the path contains a virtual base class we can't give any hint. |
| // -1: no hint. |
| if (PathElement.Base->isVirtual()) |
| return CharUnits::fromQuantity(-1ULL); |
| |
| if (NumPublicPaths > 1) // Won't use offsets, skip computation. |
| continue; |
| |
| // Accumulate the base class offsets. |
| const ASTRecordLayout &L = Ctx.getASTRecordLayout(PathElement.Class); |
| Offset += L.getBaseClassOffset( |
| PathElement.Base->getType()->getAsCXXRecordDecl()); |
| } |
| } |
| |
| // -2: Src is not a public base of Dst. |
| if (NumPublicPaths == 0) |
| return CharUnits::fromQuantity(-2ULL); |
| |
| // -3: Src is a multiple public base type but never a virtual base type. |
| if (NumPublicPaths > 1) |
| return CharUnits::fromQuantity(-3ULL); |
| |
| // Otherwise, the Src type is a unique public nonvirtual base type of Dst. |
| // Return the offset of Src from the origin of Dst. |
| return Offset; |
| } |
| |
| } // namespace clang::CodeGenUtils |