aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorZarko Todorovski <zarko@ca.ibm.com>2022-07-13 15:32:16 -0400
committerZarko Todorovski <zarko@ca.ibm.com>2022-07-13 15:32:29 -0400
commita61b202d4e3b00bf6bfd71dc1ea354d37f73b791 (patch)
treebd2784537f1271ce7d297843b36a4da2f6a22679 /clang/lib/Sema/SemaChecking.cpp
parent0466d1df23b9157144c32e03f6477ed250991215 (diff)
downloadllvm-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.cpp40
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),