summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaCast.cpp3
-rw-r--r--clang/lib/Sema/SemaChecking.cpp67
-rw-r--r--clang/lib/Sema/SemaExpr.cpp6
-rw-r--r--clang/lib/Sema/SemaInit.cpp13
4 files changed, 88 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index e83dd071678..e19020c6ade 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -256,6 +256,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
Op.CheckConstCast();
if (Op.SrcExpr.isInvalid())
return ExprError();
+ DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.SrcExpr.get(), DestTInfo,
@@ -279,6 +280,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
Op.CheckReinterpretCast();
if (Op.SrcExpr.isInvalid())
return ExprError();
+ DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
@@ -291,6 +293,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
Op.CheckStaticCast();
if (Op.SrcExpr.isInvalid())
return ExprError();
+ DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
}
return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index ec01b04fcf9..ff18e094bda 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -8302,6 +8302,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
DiagnoseNullConversion(S, E, T, CC);
+ S.DiscardMisalignedMemberAddress(Target, E);
+
if (!Source->isIntegerType() || !Target->isIntegerType())
return;
@@ -9371,6 +9373,7 @@ void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc,
CheckUnsequencedOperations(E);
if (!IsConstexpr && !E->isValueDependent())
CheckForIntOverflow(E);
+ DiagnoseMisalignedMembers();
}
void Sema::CheckBitFieldInitialization(SourceLocation InitLoc,
@@ -10916,3 +10919,67 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
<< ArgumentExpr->getSourceRange()
<< TypeTagExpr->getSourceRange();
}
+
+void Sema::AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
+ CharUnits Alignment) {
+ MisalignedMembers.emplace_back(E, RD, MD, Alignment);
+}
+
+void Sema::DiagnoseMisalignedMembers() {
+ for (MisalignedMember &m : MisalignedMembers) {
+ Diag(m.E->getLocStart(), diag::warn_taking_address_of_packed_member)
+ << m.MD << m.RD << m.E->getSourceRange();
+ }
+ MisalignedMembers.clear();
+}
+
+void Sema::DiscardMisalignedMemberAddress(const Type *T, Expr *E) {
+ if (!T->isPointerType())
+ return;
+ if (isa<UnaryOperator>(E) &&
+ cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf) {
+ auto *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+ if (isa<MemberExpr>(Op)) {
+ auto MA = std::find(MisalignedMembers.begin(), MisalignedMembers.end(),
+ MisalignedMember(Op));
+ if (MA != MisalignedMembers.end() &&
+ Context.getTypeAlignInChars(T->getPointeeType()) <= MA->Alignment)
+ MisalignedMembers.erase(MA);
+ }
+ }
+}
+
+void Sema::RefersToMemberWithReducedAlignment(
+ Expr *E,
+ std::function<void(Expr *, RecordDecl *, ValueDecl *, CharUnits)> Action) {
+ const auto *ME = dyn_cast<MemberExpr>(E);
+ while (ME && isa<FieldDecl>(ME->getMemberDecl())) {
+ QualType BaseType = ME->getBase()->getType();
+ if (ME->isArrow())
+ BaseType = BaseType->getPointeeType();
+ RecordDecl *RD = BaseType->getAs<RecordType>()->getDecl();
+
+ ValueDecl *MD = ME->getMemberDecl();
+ bool ByteAligned = Context.getTypeAlignInChars(MD->getType()).isOne();
+ if (ByteAligned) // Attribute packed does not have any effect.
+ break;
+
+ if (!ByteAligned &&
+ (RD->hasAttr<PackedAttr>() || (MD->hasAttr<PackedAttr>()))) {
+ CharUnits Alignment = std::min(Context.getTypeAlignInChars(MD->getType()),
+ Context.getTypeAlignInChars(BaseType));
+ // Notify that this expression designates a member with reduced alignment
+ Action(E, RD, MD, Alignment);
+ break;
+ }
+ ME = dyn_cast<MemberExpr>(ME->getBase());
+ }
+}
+
+void Sema::CheckAddressOfPackedMember(Expr *rhs) {
+ using namespace std::placeholders;
+ RefersToMemberWithReducedAlignment(
+ rhs, std::bind(&Sema::AddPotentialMisalignedMembers, std::ref(*this), _1,
+ _2, _3, _4));
+}
+
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0c8a9136948..2a48798d3cb 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6001,7 +6001,9 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
CheckTollFreeBridgeCast(castType, CastExpr);
CheckObjCBridgeRelatedCast(castType, CastExpr);
-
+
+ DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr);
+
return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);
}
@@ -10534,6 +10536,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (op->getType()->isObjCObjectType())
return Context.getObjCObjectPointerType(op->getType());
+ CheckAddressOfPackedMember(op);
+
return Context.getPointerType(op->getType());
}
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 060ee3eef21..c88af08546e 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6457,6 +6457,15 @@ InitializationSequence::Perform(Sema &S,
ExtendingEntity->getDecl());
CheckForNullPointerDereference(S, CurInit.get());
+
+ S.RefersToMemberWithReducedAlignment(CurInit.get(), [&](Expr *E,
+ RecordDecl *RD,
+ ValueDecl *MD,
+ CharUnits) {
+ S.Diag(Kind.getLocation(), diag::err_binding_reference_to_packed_member)
+ << MD << RD << E->getSourceRange();
+ });
+
break;
case SK_BindReferenceToTemporary: {
@@ -6645,12 +6654,16 @@ InitializationSequence::Perform(Sema &S,
getAssignmentAction(Entity), CCK);
if (CurInitExprRes.isInvalid())
return ExprError();
+
+ S.DiscardMisalignedMemberAddress(Step->Type.getTypePtr(), CurInit.get());
+
CurInit = CurInitExprRes;
if (Step->Kind == SK_ConversionSequenceNoNarrowing &&
S.getLangOpts().CPlusPlus && !CurInit.get()->isValueDependent())
DiagnoseNarrowingInInitList(S, *Step->ICS, SourceType, Entity.getType(),
CurInit.get());
+
break;
}
OpenPOWER on IntegriCloud