summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/SemaAttr.cpp16
-rw-r--r--test/FixIt/fixit-pragma-pack.c5
-rw-r--r--test/PCH/suspicious-pragma-pack.c4
-rw-r--r--test/Sema/pragma-pack.c2
5 files changed, 26 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index d75cc20f2d..e685311914 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -723,6 +723,8 @@ def warn_pragma_pack_no_pop_eof : Warning<"unterminated "
"'#pragma pack (push, ...)' at end of file">, InGroup<PragmaPack>;
def note_pragma_pack_here : Note<
"previous '#pragma pack' directive that modifies alignment is here">;
+def note_pragma_pack_pop_instead_reset : Note<
+ "did you intend to use '#pragma pack (pop)' instead of '#pragma pack()'?">;
// Follow the Microsoft implementation.
def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
def warn_pragma_pack_pop_identifer_and_alignment : Warning<
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index f7f1f61873..4ba2a317e1 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -250,8 +250,22 @@ void Sema::DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind,
void Sema::DiagnoseUnterminatedPragmaPack() {
if (PackStack.Stack.empty())
return;
- for (const auto &StackSlot : llvm::reverse(PackStack.Stack))
+ bool IsInnermost = true;
+ for (const auto &StackSlot : llvm::reverse(PackStack.Stack)) {
Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof);
+ // The user might have already reset the alignment, so suggest replacing
+ // the reset with a pop.
+ if (IsInnermost && PackStack.CurrentValue == PackStack.DefaultValue) {
+ DiagnosticBuilder DB = Diag(PackStack.CurrentPragmaLocation,
+ diag::note_pragma_pack_pop_instead_reset);
+ SourceLocation FixItLoc = Lexer::findLocationAfterToken(
+ PackStack.CurrentPragmaLocation, tok::l_paren, SourceMgr, LangOpts,
+ /*SkipTrailing=*/false);
+ if (FixItLoc.isValid())
+ DB << FixItHint::CreateInsertion(FixItLoc, "pop");
+ }
+ IsInnermost = false;
+ }
}
void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
diff --git a/test/FixIt/fixit-pragma-pack.c b/test/FixIt/fixit-pragma-pack.c
new file mode 100644
index 0000000000..acab4a8bb4
--- /dev/null
+++ b/test/FixIt/fixit-pragma-pack.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+#pragma pack (push, 1)
+#pragma pack()
+// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:14-[[@LINE-1]]:14}:"pop"
diff --git a/test/PCH/suspicious-pragma-pack.c b/test/PCH/suspicious-pragma-pack.c
index 01a66af34b..ac48ad3a89 100644
--- a/test/PCH/suspicious-pragma-pack.c
+++ b/test/PCH/suspicious-pragma-pack.c
@@ -4,5 +4,7 @@
#ifndef HEADER
#define HEADER
#pragma pack (push, 1)
+#else
+#pragma pack (2)
#endif
-// expected-warning@-2 {{unterminated '#pragma pack (push, ...)' at end of file}}
+// expected-warning@-4 {{unterminated '#pragma pack (push, ...)' at end of file}}
diff --git a/test/Sema/pragma-pack.c b/test/Sema/pragma-pack.c
index 84a946368f..2ed0874bfd 100644
--- a/test/Sema/pragma-pack.c
+++ b/test/Sema/pragma-pack.c
@@ -29,4 +29,4 @@
// Warn about unbalanced pushes.
#pragma pack (push,4) // expected-warning {{unterminated '#pragma pack (push, ...)' at end of file}}
#pragma pack (push) // expected-warning {{unterminated '#pragma pack (push, ...)' at end of file}}
-#pragma pack ()
+#pragma pack () // expected-note {{did you intend to use '#pragma pack (pop)' instead of '#pragma pack()'?}}