diff options
author | Zarko Todorovski <zarko@ca.ibm.com> | 2022-07-13 15:32:16 -0400 |
---|---|---|
committer | Zarko Todorovski <zarko@ca.ibm.com> | 2022-07-13 15:32:29 -0400 |
commit | a61b202d4e3b00bf6bfd71dc1ea354d37f73b791 (patch) | |
tree | bd2784537f1271ce7d297843b36a4da2f6a22679 /clang/lib/Sema/SemaChecking.cpp | |
parent | 0466d1df23b9157144c32e03f6477ed250991215 (diff) | |
download | llvm-a61b202d4e3b00bf6bfd71dc1ea354d37f73b791.zip llvm-a61b202d4e3b00bf6bfd71dc1ea354d37f73b791.tar.gz llvm-a61b202d4e3b00bf6bfd71dc1ea354d37f73b791.tar.bz2 |
[Clang][Sema][AIX][PowerPC] Emit byval alignment warning only when struct is passed to a function
Previous warning went on whenever a struct with a struct member with alignment => 16
was declared. This led to too many false positives and led to diagnostic lit failures
due to it being emitted too frequently. Only emit the warning when such a struct and
that struct contains a member that has an alignment of 16 bytes is passed to a caller
function since this is where the potential binary compatibility issue with XL 16.1.0
and older exists.
Reviewed By: sfertile, aaron.ballman
Differential Revision: https://reviews.llvm.org/D118350
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index d392936..df602f1 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5626,6 +5626,40 @@ static void CheckNonNullArguments(Sema &S, } } +// 16 byte ByVal alignment not due to a vector member is not honoured by XL +// on AIX. Emit a warning here that users are generating binary incompatible +// code to be safe. +// Here we try to get information about the alignment of the struct member +// from the struct passed to the caller function. We only warn when the struct +// is passed byval, hence the series of checks and early returns if we are a not +// passing a struct byval. +void Sema::checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg) { + const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg->IgnoreParens()); + if (!ICE) + return; + + const auto *DR = dyn_cast<DeclRefExpr>(ICE->getSubExpr()); + if (!DR) + return; + + const auto *PD = dyn_cast<ParmVarDecl>(DR->getDecl()); + if (!PD || !PD->getType()->isRecordType()) + return; + + QualType ArgType = Arg->getType(); + for (const FieldDecl *FD : + ArgType->castAs<RecordType>()->getDecl()->fields()) { + if (const auto *AA = FD->getAttr<AlignedAttr>()) { + CharUnits Alignment = + Context.toCharUnitsFromBits(AA->getAlignment(Context)); + if (Alignment.getQuantity() == 16) { + Diag(FD->getLocation(), diag::warn_not_xl_compatible) << FD; + Diag(Loc, diag::note_misaligned_member_used_here) << PD; + } + } + } +} + /// Warn if a pointer or reference argument passed to a function points to an /// object that is less aligned than the parameter. This can happen when /// creating a typedef with a lower alignment than the original type and then @@ -5736,6 +5770,12 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, if (Arg->containsErrors()) continue; + if (Context.getTargetInfo().getTriple().isOSAIX() && FDecl && Arg && + FDecl->hasLinkage() && + FDecl->getFormalLinkage() != InternalLinkage && + CallType == VariadicDoesNotApply) + checkAIXMemberAlignment((Arg->getExprLoc()), Arg); + QualType ParamTy = Proto->getParamType(ArgIdx); QualType ArgTy = Arg->getType(); CheckArgAlignment(Arg->getExprLoc(), FDecl, std::to_string(ArgIdx + 1), |