[PATCH] D87702: [Frontend] Add pragma align natural and sort out pragma pack stack effect

Jason Liu via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 8 13:57:41 PDT 2020


jasonliu added inline comments.


================
Comment at: clang/include/clang/Basic/LangOptions.def:340
 
+LANGOPT(AIXPragmaPack, 1, 0, "AIX #pragma pack handling")
+
----------------
Not sure if AIXPragmaPack is the best name here. 
It's more like IBM xl pragma pack handling on AIX.
Would it be better if we name it `XLPragmaPackOnAIX`?


================
Comment at: clang/include/clang/Sema/Sema.h:493
+          PackNumber(M == Packed ? 1
+                                 : (M == Mac68k ? Mac68kAlignmentSentinel
+                                                : UninitPackVal)),
----------------
I think one of the idea is to use `enum Mode::Mac68k` to replace the need of Mac68kAlignmentSentinel.
Is there any reason that you would still need PackNumber to contain `Mac68kAlignmentSentinel`?


================
Comment at: clang/include/clang/Sema/Sema.h:497
+
+    AlignPackInfo() : AlignPackInfo(Native, false) {}
+
----------------
We could have a empty stack on AIX that returns false when it was asked if it's an AIX stack?
It's a bit confusing here. 


================
Comment at: clang/include/clang/Sema/Sema.h:637
   PragmaStack<MSVtorDispMode> VtorDispStack;
-  // #pragma pack.
-  // Sentinel to represent when the stack is set to mac68k alignment.
-  static const unsigned kMac68kAlignmentSentinel = ~0U;
-  PragmaStack<unsigned> PackStack;
+  PragmaStack<AlignPackInfo> PackStack;
   // The current #pragma pack values and locations at each #include.
----------------
We should consider renaming PackStack to AlignPackStack across Clang. Maybe even as a NFC first. As it is right now, clang already uses one stack to record those two informations from `Pragma align` and `Pragma pack`. Leave it as PackStack is too confusing, and people could actually ignore the pragma Align when developing with PackStack. 


================
Comment at: clang/include/clang/Sema/Sema.h:488
+    AlignPackInfo(AlignPackInfo::Mode M, int Num, bool IsAIX)
+        : PackAttr(true), AlignMode(M), PackNumber(Num), AIXStack(IsAIX) {}
+
----------------
Xiangling_L wrote:
> jasonliu wrote:
> > I noticed PackNumber is an unsigned char and we are passing an int type into it.
> > Could we add an assertion in the constructor to make sure Num would never be something that's going to get truncated when it converts to an unsigned char?
> I think the warning/error `expected #pragma pack parameter to be '1', '2', '4', '8', or '16'` have already guaranteed that for us? Or maybe using `unsigned int` makes people more comfortable?
Using a char instead of an int could make this class more compact, especially when we actually don't need to represent a big range. 
I understand there is a warning/error somewhere to prevent out of range from happening. But an assert here would make sure that no one could pass in an unexpected value into here by accident when developing. 


================
Comment at: clang/include/clang/Sema/Sema.h:515
+    bool operator==(AlignPackInfo Info) const {
+      return AlignMode == Info.AlignMode && PackNumber == Info.PackNumber;
+    }
----------------
Xiangling_L wrote:
> jasonliu wrote:
> > This could return true when `PackAttr` in AlignPackInfo are not the same. Wouldn't that cause an issue?
> (1) You mean we have two `AlignPackInfo` with same AlignMode and PackNumber, but one is PackAttr and the other one is AlignAttr?
> The example I can think of is:
> 
> 
> ```
> a)#pragma align(packed)
>   #pragma pack(1)   //AlignMode = Packed, PackNumber = 1
> 
> b) #pragma align(packed)  //AlignMode = Packed, PackNumber = 1
> ```
> 
> But I don't think we have any issue in this case. Before and after my patch, a == b.
> Please let me know any other cases concerning you if any.
> 
> (2) However, your concerns leads me to think of another case, where behavior changes with my patch.
> 
> ```
> a) 
> #pragma align(natural)
> #pragma pack(1)   /AlignMode = Native,  PackNumber = 1
> 
> b)
> #pragma align(packed) ///AlignMode = Packed, PackNumber = 1
> 
> ```
> Without this patch, a == b for other targets.
> And I suppose a != b for AIX.
> 
In your first example, if I understand correctly,
a) would return true for IsPackAttr()
b) would return false for IsPackAttr()
and yet a == b ?
I think that's confusing. 

Any reason why you don't want to just compare all the data members to make sure they are all equal?


================
Comment at: clang/lib/Sema/SemaAttr.cpp:367
+  // AIX pragma pack does not support identifier syntax.
+  if (getLangOpts().AIXPragmaPack && !SlotLabel.empty()) {
+    Diag(PragmaLoc, diag::warn_pragma_pack_identifer_not_supported);
----------------
Although IBM xl compiler does not support this form, do we see a harm for us to support this form in clang on AIX?
Also, if this is indeed not desired to support, we could move this check to the top of this function for an early return. 


================
Comment at: clang/lib/Sema/SemaAttr.cpp:403
   // Warn about modified alignment after #includes.
   if (PrevPackState.CurrentValue != PackStack.CurrentValue) {
     Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include);
----------------
Xiangling_L wrote:
> jasonliu wrote:
> > Since we changed the PackStack for it to contain AlignPackInfo instead of unsigned. 
> > This stack no longer only contains Pack information. So we need to rethink about how this diagnostic and the one follows should work.
> > i.e. What's the purpose of these diagnostic? Is it still only for pragma pack report? If so, what we are doing here is not correct, since the `CurrentValue` could be different, not because of the pragma pack change, but because of the pragma align change.
> > If it's not only for pragma pack any more, but also intend to detect the pragma align interaction, then possibly function name and diagnostic needs some modification, as they don't match the intent any more.
> Thanks for pointing this out. I agree that what we are doing here is not correct. 
> The original commit[45b40147117668ce65bff4f6a240bdae4ad4bf7d] message shows:
> 
> ```
>     This commit adds a new -Wpragma-pack warning. It warns in the following cases:
>     
>     - When a translation unit is missing terminating #pragma pack (pop) directives.
>     - When entering an included file if the current alignment value as determined
>       by '#pragma pack' directives is different from the default alignment value.
>     - When leaving an included file that changed the state of the current alignment
>       value.
> ```
> 
> So it looks these warnings are used only for `pragma pack`.
This might not be enough to make the diagnostic in `DiagnoseNonDefaultPragmaPack()` and  `DiagnoseUnterminatedPragmaPack()` work sensibly, when pragma align is involved. 
One example being if the source contains:

`#pragma align = natural`

We would get:
```
clang pragmapack.c -S 
pragmapack.c:1:9: warning: unterminated '#pragma pack (push, ...)' at end of file [-Wpragma-pack]
#pragma align = natural 
        ^
pragmapack.c:1:9: note: did you intend to use '#pragma pack (pop)' instead of '#pragma pack()'?
1 warning generated.

```

But this seems like an existing bug, as without your change, I'm still seeing this "incorrect" message.


================
Comment at: clang/lib/Serialization/ASTReader.cpp:7914
+      Sema::AlignPackInfo Info =
+          Sema::AlignPackInfo(SemaObj->PackStack.CurrentValue.getAlignMode(),
+                              Entry.Value, PP.getLangOpts().AIXPragmaPack);
----------------
I think we need to do something more to handle the PragmaPackStack here. 
It seems in ASTReader, we would always use CurrentValue.getAlignMode() for all the AlignPackInfo. 
Does that mean we are actually not able to capture the align mode even when there is an align mode set for the current entry?


================
Comment at: clang/lib/Serialization/ASTWriter.cpp:4162
   RecordData Record;
-  Record.push_back(SemaRef.PackStack.CurrentValue);
+  Record.push_back(SemaRef.PackStack.CurrentValue.getPackNumber());
   AddSourceLocation(SemaRef.PackStack.CurrentPragmaLocation, Record);
----------------
I think we would miss the serialization of pragma align mode, if we only record the pack number here. 


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87702/new/

https://reviews.llvm.org/D87702



More information about the cfe-commits mailing list