From bf8b63ed296c1ecad03c83b798ffbfa039cbceb4 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 28 Apr 2020 16:04:26 -0700 Subject: [clang codegen] Fix alignment of "Address" for incomplete array pointer. The code was assuming all incomplete types don't have meaningful alignment, but incomplete arrays do have meaningful alignment. Fixes https://bugs.llvm.org/show_bug.cgi?id=45710 Differential Revision: https://reviews.llvm.org/D79052 --- clang/lib/CodeGen/CodeGenModule.cpp | 57 ++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 7a9df700581e..f0ab5165584c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5990,6 +5990,9 @@ CharUnits CodeGenModule::getNaturalTypeAlignment(QualType T, if (TBAAInfo) *TBAAInfo = getTBAAAccessInfo(T); + // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown. But + // that doesn't return the information we need to compute BaseInfo. + // Honor alignment typedef attributes even on incomplete types. // We also honor them straight for C++ class types, even as pointees; // there's an expressivity gap here. @@ -6001,32 +6004,46 @@ CharUnits CodeGenModule::getNaturalTypeAlignment(QualType T, } } + bool AlignForArray = T->isArrayType(); + + // Analyze the base element type, so we don't get confused by incomplete + // array types. + T = getContext().getBaseElementType(T); + + if (T->isIncompleteType()) { + // We could try to replicate the logic from + // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the + // type is incomplete, so it's impossible to test. We could try to reuse + // getTypeAlignIfKnown, but that doesn't return the information we need + // to set BaseInfo. So just ignore the possibility that the alignment is + // greater than one. + if (BaseInfo) + *BaseInfo = LValueBaseInfo(AlignmentSource::Type); + return CharUnits::One(); + } + if (BaseInfo) *BaseInfo = LValueBaseInfo(AlignmentSource::Type); CharUnits Alignment; - if (T->isIncompleteType()) { - Alignment = CharUnits::One(); // Shouldn't be used, but pessimistic is best. + // For C++ class pointees, we don't know whether we're pointing at a + // base or a complete object, so we generally need to use the + // non-virtual alignment. + const CXXRecordDecl *RD; + if (forPointeeType && !AlignForArray && (RD = T->getAsCXXRecordDecl())) { + Alignment = getClassPointerAlignment(RD); } else { - // For C++ class pointees, we don't know whether we're pointing at a - // base or a complete object, so we generally need to use the - // non-virtual alignment. - const CXXRecordDecl *RD; - if (forPointeeType && (RD = T->getAsCXXRecordDecl())) { - Alignment = getClassPointerAlignment(RD); - } else { - Alignment = getContext().getTypeAlignInChars(T); - if (T.getQualifiers().hasUnaligned()) - Alignment = CharUnits::One(); - } + Alignment = getContext().getTypeAlignInChars(T); + if (T.getQualifiers().hasUnaligned()) + Alignment = CharUnits::One(); + } - // Cap to the global maximum type alignment unless the alignment - // was somehow explicit on the type. - if (unsigned MaxAlign = getLangOpts().MaxTypeAlign) { - if (Alignment.getQuantity() > MaxAlign && - !getContext().isAlignmentRequired(T)) - Alignment = CharUnits::fromQuantity(MaxAlign); - } + // Cap to the global maximum type alignment unless the alignment + // was somehow explicit on the type. + if (unsigned MaxAlign = getLangOpts().MaxTypeAlign) { + if (Alignment.getQuantity() > MaxAlign && + !getContext().isAlignmentRequired(T)) + Alignment = CharUnits::fromQuantity(MaxAlign); } return Alignment; } -- cgit v1.2.3