xref: /minix3/external/bsd/llvm/dist/clang/lib/Sema/SemaAttr.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements semantic analysis for non-trivial attributes and
11f4a2713aSLionel Sambuc // pragmas.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "clang/Sema/SemaInternal.h"
16f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h"
17f4a2713aSLionel Sambuc #include "clang/AST/Attr.h"
18f4a2713aSLionel Sambuc #include "clang/AST/Expr.h"
19f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
20f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h"
21f4a2713aSLionel Sambuc #include "clang/Sema/Lookup.h"
22f4a2713aSLionel Sambuc using namespace clang;
23f4a2713aSLionel Sambuc 
24f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
25f4a2713aSLionel Sambuc // Pragma 'pack' and 'options align'
26f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
27f4a2713aSLionel Sambuc 
28f4a2713aSLionel Sambuc namespace {
29f4a2713aSLionel Sambuc   struct PackStackEntry {
30f4a2713aSLionel Sambuc     // We just use a sentinel to represent when the stack is set to mac68k
31f4a2713aSLionel Sambuc     // alignment.
32f4a2713aSLionel Sambuc     static const unsigned kMac68kAlignmentSentinel = ~0U;
33f4a2713aSLionel Sambuc 
34f4a2713aSLionel Sambuc     unsigned Alignment;
35f4a2713aSLionel Sambuc     IdentifierInfo *Name;
36f4a2713aSLionel Sambuc   };
37f4a2713aSLionel Sambuc 
38f4a2713aSLionel Sambuc   /// PragmaPackStack - Simple class to wrap the stack used by #pragma
39f4a2713aSLionel Sambuc   /// pack.
40f4a2713aSLionel Sambuc   class PragmaPackStack {
41f4a2713aSLionel Sambuc     typedef std::vector<PackStackEntry> stack_ty;
42f4a2713aSLionel Sambuc 
43f4a2713aSLionel Sambuc     /// Alignment - The current user specified alignment.
44f4a2713aSLionel Sambuc     unsigned Alignment;
45f4a2713aSLionel Sambuc 
46f4a2713aSLionel Sambuc     /// Stack - Entries in the #pragma pack stack, consisting of saved
47f4a2713aSLionel Sambuc     /// alignments and optional names.
48f4a2713aSLionel Sambuc     stack_ty Stack;
49f4a2713aSLionel Sambuc 
50f4a2713aSLionel Sambuc   public:
PragmaPackStack()51f4a2713aSLionel Sambuc     PragmaPackStack() : Alignment(0) {}
52f4a2713aSLionel Sambuc 
setAlignment(unsigned A)53f4a2713aSLionel Sambuc     void setAlignment(unsigned A) { Alignment = A; }
getAlignment()54f4a2713aSLionel Sambuc     unsigned getAlignment() { return Alignment; }
55f4a2713aSLionel Sambuc 
56f4a2713aSLionel Sambuc     /// push - Push the current alignment onto the stack, optionally
57f4a2713aSLionel Sambuc     /// using the given \arg Name for the record, if non-zero.
push(IdentifierInfo * Name)58f4a2713aSLionel Sambuc     void push(IdentifierInfo *Name) {
59f4a2713aSLionel Sambuc       PackStackEntry PSE = { Alignment, Name };
60f4a2713aSLionel Sambuc       Stack.push_back(PSE);
61f4a2713aSLionel Sambuc     }
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc     /// pop - Pop a record from the stack and restore the current
64f4a2713aSLionel Sambuc     /// alignment to the previous value. If \arg Name is non-zero then
65f4a2713aSLionel Sambuc     /// the first such named record is popped, otherwise the top record
66f4a2713aSLionel Sambuc     /// is popped. Returns true if the pop succeeded.
67f4a2713aSLionel Sambuc     bool pop(IdentifierInfo *Name, bool IsReset);
68f4a2713aSLionel Sambuc   };
69f4a2713aSLionel Sambuc }  // end anonymous namespace.
70f4a2713aSLionel Sambuc 
pop(IdentifierInfo * Name,bool IsReset)71f4a2713aSLionel Sambuc bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
72f4a2713aSLionel Sambuc   // If name is empty just pop top.
73f4a2713aSLionel Sambuc   if (!Name) {
74f4a2713aSLionel Sambuc     // An empty stack is a special case...
75f4a2713aSLionel Sambuc     if (Stack.empty()) {
76f4a2713aSLionel Sambuc       // If this isn't a reset, it is always an error.
77f4a2713aSLionel Sambuc       if (!IsReset)
78f4a2713aSLionel Sambuc         return false;
79f4a2713aSLionel Sambuc 
80f4a2713aSLionel Sambuc       // Otherwise, it is an error only if some alignment has been set.
81f4a2713aSLionel Sambuc       if (!Alignment)
82f4a2713aSLionel Sambuc         return false;
83f4a2713aSLionel Sambuc 
84f4a2713aSLionel Sambuc       // Otherwise, reset to the default alignment.
85f4a2713aSLionel Sambuc       Alignment = 0;
86f4a2713aSLionel Sambuc     } else {
87f4a2713aSLionel Sambuc       Alignment = Stack.back().Alignment;
88f4a2713aSLionel Sambuc       Stack.pop_back();
89f4a2713aSLionel Sambuc     }
90f4a2713aSLionel Sambuc 
91f4a2713aSLionel Sambuc     return true;
92f4a2713aSLionel Sambuc   }
93f4a2713aSLionel Sambuc 
94f4a2713aSLionel Sambuc   // Otherwise, find the named record.
95f4a2713aSLionel Sambuc   for (unsigned i = Stack.size(); i != 0; ) {
96f4a2713aSLionel Sambuc     --i;
97f4a2713aSLionel Sambuc     if (Stack[i].Name == Name) {
98f4a2713aSLionel Sambuc       // Found it, pop up to and including this record.
99f4a2713aSLionel Sambuc       Alignment = Stack[i].Alignment;
100f4a2713aSLionel Sambuc       Stack.erase(Stack.begin() + i, Stack.end());
101f4a2713aSLionel Sambuc       return true;
102f4a2713aSLionel Sambuc     }
103f4a2713aSLionel Sambuc   }
104f4a2713aSLionel Sambuc 
105f4a2713aSLionel Sambuc   return false;
106f4a2713aSLionel Sambuc }
107f4a2713aSLionel Sambuc 
108f4a2713aSLionel Sambuc 
109f4a2713aSLionel Sambuc /// FreePackedContext - Deallocate and null out PackContext.
FreePackedContext()110f4a2713aSLionel Sambuc void Sema::FreePackedContext() {
111f4a2713aSLionel Sambuc   delete static_cast<PragmaPackStack*>(PackContext);
112*0a6a1f1dSLionel Sambuc   PackContext = nullptr;
113f4a2713aSLionel Sambuc }
114f4a2713aSLionel Sambuc 
AddAlignmentAttributesForRecord(RecordDecl * RD)115f4a2713aSLionel Sambuc void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
116f4a2713aSLionel Sambuc   // If there is no pack context, we don't need any attributes.
117f4a2713aSLionel Sambuc   if (!PackContext)
118f4a2713aSLionel Sambuc     return;
119f4a2713aSLionel Sambuc 
120f4a2713aSLionel Sambuc   PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
121f4a2713aSLionel Sambuc 
122f4a2713aSLionel Sambuc   // Otherwise, check to see if we need a max field alignment attribute.
123f4a2713aSLionel Sambuc   if (unsigned Alignment = Stack->getAlignment()) {
124f4a2713aSLionel Sambuc     if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
125*0a6a1f1dSLionel Sambuc       RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
126f4a2713aSLionel Sambuc     else
127*0a6a1f1dSLionel Sambuc       RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
128f4a2713aSLionel Sambuc                                                         Alignment * 8));
129f4a2713aSLionel Sambuc   }
130f4a2713aSLionel Sambuc }
131f4a2713aSLionel Sambuc 
AddMsStructLayoutForRecord(RecordDecl * RD)132f4a2713aSLionel Sambuc void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) {
133*0a6a1f1dSLionel Sambuc   if (MSStructPragmaOn)
134*0a6a1f1dSLionel Sambuc     RD->addAttr(MsStructAttr::CreateImplicit(Context));
135*0a6a1f1dSLionel Sambuc 
136*0a6a1f1dSLionel Sambuc   // FIXME: We should merge AddAlignmentAttributesForRecord with
137*0a6a1f1dSLionel Sambuc   // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes
138*0a6a1f1dSLionel Sambuc   // all active pragmas and applies them as attributes to class definitions.
139*0a6a1f1dSLionel Sambuc   if (VtorDispModeStack.back() != getLangOpts().VtorDispMode)
140*0a6a1f1dSLionel Sambuc     RD->addAttr(
141*0a6a1f1dSLionel Sambuc         MSVtorDispAttr::CreateImplicit(Context, VtorDispModeStack.back()));
142f4a2713aSLionel Sambuc }
143f4a2713aSLionel Sambuc 
ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,SourceLocation PragmaLoc)144f4a2713aSLionel Sambuc void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
145f4a2713aSLionel Sambuc                                    SourceLocation PragmaLoc) {
146*0a6a1f1dSLionel Sambuc   if (!PackContext)
147f4a2713aSLionel Sambuc     PackContext = new PragmaPackStack();
148f4a2713aSLionel Sambuc 
149f4a2713aSLionel Sambuc   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
150f4a2713aSLionel Sambuc 
151f4a2713aSLionel Sambuc   switch (Kind) {
152f4a2713aSLionel Sambuc     // For all targets we support native and natural are the same.
153f4a2713aSLionel Sambuc     //
154f4a2713aSLionel Sambuc     // FIXME: This is not true on Darwin/PPC.
155f4a2713aSLionel Sambuc   case POAK_Native:
156f4a2713aSLionel Sambuc   case POAK_Power:
157f4a2713aSLionel Sambuc   case POAK_Natural:
158*0a6a1f1dSLionel Sambuc     Context->push(nullptr);
159f4a2713aSLionel Sambuc     Context->setAlignment(0);
160f4a2713aSLionel Sambuc     break;
161f4a2713aSLionel Sambuc 
162f4a2713aSLionel Sambuc     // Note that '#pragma options align=packed' is not equivalent to attribute
163f4a2713aSLionel Sambuc     // packed, it has a different precedence relative to attribute aligned.
164f4a2713aSLionel Sambuc   case POAK_Packed:
165*0a6a1f1dSLionel Sambuc     Context->push(nullptr);
166f4a2713aSLionel Sambuc     Context->setAlignment(1);
167f4a2713aSLionel Sambuc     break;
168f4a2713aSLionel Sambuc 
169f4a2713aSLionel Sambuc   case POAK_Mac68k:
170f4a2713aSLionel Sambuc     // Check if the target supports this.
171*0a6a1f1dSLionel Sambuc     if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) {
172f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
173f4a2713aSLionel Sambuc       return;
174f4a2713aSLionel Sambuc     }
175*0a6a1f1dSLionel Sambuc     Context->push(nullptr);
176f4a2713aSLionel Sambuc     Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
177f4a2713aSLionel Sambuc     break;
178f4a2713aSLionel Sambuc 
179f4a2713aSLionel Sambuc   case POAK_Reset:
180f4a2713aSLionel Sambuc     // Reset just pops the top of the stack, or resets the current alignment to
181f4a2713aSLionel Sambuc     // default.
182*0a6a1f1dSLionel Sambuc     if (!Context->pop(nullptr, /*IsReset=*/true)) {
183f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
184f4a2713aSLionel Sambuc         << "stack empty";
185f4a2713aSLionel Sambuc     }
186f4a2713aSLionel Sambuc     break;
187f4a2713aSLionel Sambuc   }
188f4a2713aSLionel Sambuc }
189f4a2713aSLionel Sambuc 
ActOnPragmaPack(PragmaPackKind Kind,IdentifierInfo * Name,Expr * alignment,SourceLocation PragmaLoc,SourceLocation LParenLoc,SourceLocation RParenLoc)190f4a2713aSLionel Sambuc void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
191f4a2713aSLionel Sambuc                            Expr *alignment, SourceLocation PragmaLoc,
192f4a2713aSLionel Sambuc                            SourceLocation LParenLoc, SourceLocation RParenLoc) {
193f4a2713aSLionel Sambuc   Expr *Alignment = static_cast<Expr *>(alignment);
194f4a2713aSLionel Sambuc 
195f4a2713aSLionel Sambuc   // If specified then alignment must be a "small" power of two.
196f4a2713aSLionel Sambuc   unsigned AlignmentVal = 0;
197f4a2713aSLionel Sambuc   if (Alignment) {
198f4a2713aSLionel Sambuc     llvm::APSInt Val;
199f4a2713aSLionel Sambuc 
200f4a2713aSLionel Sambuc     // pack(0) is like pack(), which just works out since that is what
201f4a2713aSLionel Sambuc     // we use 0 for in PackAttr.
202f4a2713aSLionel Sambuc     if (Alignment->isTypeDependent() ||
203f4a2713aSLionel Sambuc         Alignment->isValueDependent() ||
204f4a2713aSLionel Sambuc         !Alignment->isIntegerConstantExpr(Val, Context) ||
205f4a2713aSLionel Sambuc         !(Val == 0 || Val.isPowerOf2()) ||
206f4a2713aSLionel Sambuc         Val.getZExtValue() > 16) {
207f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
208f4a2713aSLionel Sambuc       return; // Ignore
209f4a2713aSLionel Sambuc     }
210f4a2713aSLionel Sambuc 
211f4a2713aSLionel Sambuc     AlignmentVal = (unsigned) Val.getZExtValue();
212f4a2713aSLionel Sambuc   }
213f4a2713aSLionel Sambuc 
214*0a6a1f1dSLionel Sambuc   if (!PackContext)
215f4a2713aSLionel Sambuc     PackContext = new PragmaPackStack();
216f4a2713aSLionel Sambuc 
217f4a2713aSLionel Sambuc   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
218f4a2713aSLionel Sambuc 
219f4a2713aSLionel Sambuc   switch (Kind) {
220f4a2713aSLionel Sambuc   case Sema::PPK_Default: // pack([n])
221f4a2713aSLionel Sambuc     Context->setAlignment(AlignmentVal);
222f4a2713aSLionel Sambuc     break;
223f4a2713aSLionel Sambuc 
224f4a2713aSLionel Sambuc   case Sema::PPK_Show: // pack(show)
225f4a2713aSLionel Sambuc     // Show the current alignment, making sure to show the right value
226f4a2713aSLionel Sambuc     // for the default.
227f4a2713aSLionel Sambuc     AlignmentVal = Context->getAlignment();
228f4a2713aSLionel Sambuc     // FIXME: This should come from the target.
229f4a2713aSLionel Sambuc     if (AlignmentVal == 0)
230f4a2713aSLionel Sambuc       AlignmentVal = 8;
231f4a2713aSLionel Sambuc     if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
232f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
233f4a2713aSLionel Sambuc     else
234f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
235f4a2713aSLionel Sambuc     break;
236f4a2713aSLionel Sambuc 
237f4a2713aSLionel Sambuc   case Sema::PPK_Push: // pack(push [, id] [, [n])
238f4a2713aSLionel Sambuc     Context->push(Name);
239f4a2713aSLionel Sambuc     // Set the new alignment if specified.
240f4a2713aSLionel Sambuc     if (Alignment)
241f4a2713aSLionel Sambuc       Context->setAlignment(AlignmentVal);
242f4a2713aSLionel Sambuc     break;
243f4a2713aSLionel Sambuc 
244f4a2713aSLionel Sambuc   case Sema::PPK_Pop: // pack(pop [, id] [,  n])
245f4a2713aSLionel Sambuc     // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
246f4a2713aSLionel Sambuc     // "#pragma pack(pop, identifier, n) is undefined"
247f4a2713aSLionel Sambuc     if (Alignment && Name)
248f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
249f4a2713aSLionel Sambuc 
250f4a2713aSLionel Sambuc     // Do the pop.
251f4a2713aSLionel Sambuc     if (!Context->pop(Name, /*IsReset=*/false)) {
252f4a2713aSLionel Sambuc       // If a name was specified then failure indicates the name
253f4a2713aSLionel Sambuc       // wasn't found. Otherwise failure indicates the stack was
254f4a2713aSLionel Sambuc       // empty.
255*0a6a1f1dSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pop_failed)
256*0a6a1f1dSLionel Sambuc           << "pack" << (Name ? "no record matching name" : "stack empty");
257f4a2713aSLionel Sambuc 
258f4a2713aSLionel Sambuc       // FIXME: Warn about popping named records as MSVC does.
259f4a2713aSLionel Sambuc     } else {
260f4a2713aSLionel Sambuc       // Pop succeeded, set the new alignment if specified.
261f4a2713aSLionel Sambuc       if (Alignment)
262f4a2713aSLionel Sambuc         Context->setAlignment(AlignmentVal);
263f4a2713aSLionel Sambuc     }
264f4a2713aSLionel Sambuc     break;
265f4a2713aSLionel Sambuc   }
266f4a2713aSLionel Sambuc }
267f4a2713aSLionel Sambuc 
ActOnPragmaMSStruct(PragmaMSStructKind Kind)268f4a2713aSLionel Sambuc void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) {
269f4a2713aSLionel Sambuc   MSStructPragmaOn = (Kind == PMSST_ON);
270f4a2713aSLionel Sambuc }
271f4a2713aSLionel Sambuc 
ActOnPragmaMSComment(PragmaMSCommentKind Kind,StringRef Arg)272f4a2713aSLionel Sambuc void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg) {
273f4a2713aSLionel Sambuc   // FIXME: Serialize this.
274f4a2713aSLionel Sambuc   switch (Kind) {
275f4a2713aSLionel Sambuc   case PCK_Unknown:
276f4a2713aSLionel Sambuc     llvm_unreachable("unexpected pragma comment kind");
277f4a2713aSLionel Sambuc   case PCK_Linker:
278f4a2713aSLionel Sambuc     Consumer.HandleLinkerOptionPragma(Arg);
279f4a2713aSLionel Sambuc     return;
280f4a2713aSLionel Sambuc   case PCK_Lib:
281f4a2713aSLionel Sambuc     Consumer.HandleDependentLibrary(Arg);
282f4a2713aSLionel Sambuc     return;
283f4a2713aSLionel Sambuc   case PCK_Compiler:
284f4a2713aSLionel Sambuc   case PCK_ExeStr:
285f4a2713aSLionel Sambuc   case PCK_User:
286f4a2713aSLionel Sambuc     return;  // We ignore all of these.
287f4a2713aSLionel Sambuc   }
288f4a2713aSLionel Sambuc   llvm_unreachable("invalid pragma comment kind");
289f4a2713aSLionel Sambuc }
290f4a2713aSLionel Sambuc 
ActOnPragmaDetectMismatch(StringRef Name,StringRef Value)291f4a2713aSLionel Sambuc void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) {
292f4a2713aSLionel Sambuc   // FIXME: Serialize this.
293f4a2713aSLionel Sambuc   Consumer.HandleDetectMismatch(Name, Value);
294f4a2713aSLionel Sambuc }
295f4a2713aSLionel Sambuc 
ActOnPragmaMSPointersToMembers(LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,SourceLocation PragmaLoc)296*0a6a1f1dSLionel Sambuc void Sema::ActOnPragmaMSPointersToMembers(
297*0a6a1f1dSLionel Sambuc     LangOptions::PragmaMSPointersToMembersKind RepresentationMethod,
298*0a6a1f1dSLionel Sambuc     SourceLocation PragmaLoc) {
299*0a6a1f1dSLionel Sambuc   MSPointerToMemberRepresentationMethod = RepresentationMethod;
300*0a6a1f1dSLionel Sambuc   ImplicitMSInheritanceAttrLoc = PragmaLoc;
301*0a6a1f1dSLionel Sambuc }
302*0a6a1f1dSLionel Sambuc 
ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind,SourceLocation PragmaLoc,MSVtorDispAttr::Mode Mode)303*0a6a1f1dSLionel Sambuc void Sema::ActOnPragmaMSVtorDisp(PragmaVtorDispKind Kind,
304*0a6a1f1dSLionel Sambuc                                  SourceLocation PragmaLoc,
305*0a6a1f1dSLionel Sambuc                                  MSVtorDispAttr::Mode Mode) {
306*0a6a1f1dSLionel Sambuc   switch (Kind) {
307*0a6a1f1dSLionel Sambuc   case PVDK_Set:
308*0a6a1f1dSLionel Sambuc     VtorDispModeStack.back() = Mode;
309*0a6a1f1dSLionel Sambuc     break;
310*0a6a1f1dSLionel Sambuc   case PVDK_Push:
311*0a6a1f1dSLionel Sambuc     VtorDispModeStack.push_back(Mode);
312*0a6a1f1dSLionel Sambuc     break;
313*0a6a1f1dSLionel Sambuc   case PVDK_Reset:
314*0a6a1f1dSLionel Sambuc     VtorDispModeStack.clear();
315*0a6a1f1dSLionel Sambuc     VtorDispModeStack.push_back(MSVtorDispAttr::Mode(LangOpts.VtorDispMode));
316*0a6a1f1dSLionel Sambuc     break;
317*0a6a1f1dSLionel Sambuc   case PVDK_Pop:
318*0a6a1f1dSLionel Sambuc     VtorDispModeStack.pop_back();
319*0a6a1f1dSLionel Sambuc     if (VtorDispModeStack.empty()) {
320*0a6a1f1dSLionel Sambuc       Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp"
321*0a6a1f1dSLionel Sambuc                                                     << "stack empty";
322*0a6a1f1dSLionel Sambuc       VtorDispModeStack.push_back(MSVtorDispAttr::Mode(LangOpts.VtorDispMode));
323*0a6a1f1dSLionel Sambuc     }
324*0a6a1f1dSLionel Sambuc     break;
325*0a6a1f1dSLionel Sambuc   }
326*0a6a1f1dSLionel Sambuc }
327*0a6a1f1dSLionel Sambuc 
328*0a6a1f1dSLionel Sambuc template<typename ValueType>
Act(SourceLocation PragmaLocation,PragmaMsStackAction Action,llvm::StringRef StackSlotLabel,ValueType Value)329*0a6a1f1dSLionel Sambuc void Sema::PragmaStack<ValueType>::Act(SourceLocation PragmaLocation,
330*0a6a1f1dSLionel Sambuc                                        PragmaMsStackAction Action,
331*0a6a1f1dSLionel Sambuc                                        llvm::StringRef StackSlotLabel,
332*0a6a1f1dSLionel Sambuc                                        ValueType Value) {
333*0a6a1f1dSLionel Sambuc   if (Action == PSK_Reset) {
334*0a6a1f1dSLionel Sambuc     CurrentValue = nullptr;
335*0a6a1f1dSLionel Sambuc     return;
336*0a6a1f1dSLionel Sambuc   }
337*0a6a1f1dSLionel Sambuc   if (Action & PSK_Push)
338*0a6a1f1dSLionel Sambuc     Stack.push_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation));
339*0a6a1f1dSLionel Sambuc   else if (Action & PSK_Pop) {
340*0a6a1f1dSLionel Sambuc     if (!StackSlotLabel.empty()) {
341*0a6a1f1dSLionel Sambuc       // If we've got a label, try to find it and jump there.
342*0a6a1f1dSLionel Sambuc       auto I = std::find_if(Stack.rbegin(), Stack.rend(),
343*0a6a1f1dSLionel Sambuc         [&](const Slot &x) { return x.StackSlotLabel == StackSlotLabel; });
344*0a6a1f1dSLionel Sambuc       // If we found the label so pop from there.
345*0a6a1f1dSLionel Sambuc       if (I != Stack.rend()) {
346*0a6a1f1dSLionel Sambuc         CurrentValue = I->Value;
347*0a6a1f1dSLionel Sambuc         CurrentPragmaLocation = I->PragmaLocation;
348*0a6a1f1dSLionel Sambuc         Stack.erase(std::prev(I.base()), Stack.end());
349*0a6a1f1dSLionel Sambuc       }
350*0a6a1f1dSLionel Sambuc     } else if (!Stack.empty()) {
351*0a6a1f1dSLionel Sambuc       // We don't have a label, just pop the last entry.
352*0a6a1f1dSLionel Sambuc       CurrentValue = Stack.back().Value;
353*0a6a1f1dSLionel Sambuc       CurrentPragmaLocation = Stack.back().PragmaLocation;
354*0a6a1f1dSLionel Sambuc       Stack.pop_back();
355*0a6a1f1dSLionel Sambuc     }
356*0a6a1f1dSLionel Sambuc   }
357*0a6a1f1dSLionel Sambuc   if (Action & PSK_Set) {
358*0a6a1f1dSLionel Sambuc     CurrentValue = Value;
359*0a6a1f1dSLionel Sambuc     CurrentPragmaLocation = PragmaLocation;
360*0a6a1f1dSLionel Sambuc   }
361*0a6a1f1dSLionel Sambuc }
362*0a6a1f1dSLionel Sambuc 
UnifySection(StringRef SectionName,int SectionFlags,DeclaratorDecl * Decl)363*0a6a1f1dSLionel Sambuc bool Sema::UnifySection(StringRef SectionName,
364*0a6a1f1dSLionel Sambuc                         int SectionFlags,
365*0a6a1f1dSLionel Sambuc                         DeclaratorDecl *Decl) {
366*0a6a1f1dSLionel Sambuc   auto Section = Context.SectionInfos.find(SectionName);
367*0a6a1f1dSLionel Sambuc   if (Section == Context.SectionInfos.end()) {
368*0a6a1f1dSLionel Sambuc     Context.SectionInfos[SectionName] =
369*0a6a1f1dSLionel Sambuc         ASTContext::SectionInfo(Decl, SourceLocation(), SectionFlags);
370*0a6a1f1dSLionel Sambuc     return false;
371*0a6a1f1dSLionel Sambuc   }
372*0a6a1f1dSLionel Sambuc   // A pre-declared section takes precedence w/o diagnostic.
373*0a6a1f1dSLionel Sambuc   if (Section->second.SectionFlags == SectionFlags ||
374*0a6a1f1dSLionel Sambuc       !(Section->second.SectionFlags & ASTContext::PSF_Implicit))
375*0a6a1f1dSLionel Sambuc     return false;
376*0a6a1f1dSLionel Sambuc   auto OtherDecl = Section->second.Decl;
377*0a6a1f1dSLionel Sambuc   Diag(Decl->getLocation(), diag::err_section_conflict)
378*0a6a1f1dSLionel Sambuc       << Decl << OtherDecl;
379*0a6a1f1dSLionel Sambuc   Diag(OtherDecl->getLocation(), diag::note_declared_at)
380*0a6a1f1dSLionel Sambuc       << OtherDecl->getName();
381*0a6a1f1dSLionel Sambuc   if (auto A = Decl->getAttr<SectionAttr>())
382*0a6a1f1dSLionel Sambuc     if (A->isImplicit())
383*0a6a1f1dSLionel Sambuc       Diag(A->getLocation(), diag::note_pragma_entered_here);
384*0a6a1f1dSLionel Sambuc   if (auto A = OtherDecl->getAttr<SectionAttr>())
385*0a6a1f1dSLionel Sambuc     if (A->isImplicit())
386*0a6a1f1dSLionel Sambuc       Diag(A->getLocation(), diag::note_pragma_entered_here);
387*0a6a1f1dSLionel Sambuc   return true;
388*0a6a1f1dSLionel Sambuc }
389*0a6a1f1dSLionel Sambuc 
UnifySection(StringRef SectionName,int SectionFlags,SourceLocation PragmaSectionLocation)390*0a6a1f1dSLionel Sambuc bool Sema::UnifySection(StringRef SectionName,
391*0a6a1f1dSLionel Sambuc                         int SectionFlags,
392*0a6a1f1dSLionel Sambuc                         SourceLocation PragmaSectionLocation) {
393*0a6a1f1dSLionel Sambuc   auto Section = Context.SectionInfos.find(SectionName);
394*0a6a1f1dSLionel Sambuc   if (Section != Context.SectionInfos.end()) {
395*0a6a1f1dSLionel Sambuc     if (Section->second.SectionFlags == SectionFlags)
396*0a6a1f1dSLionel Sambuc       return false;
397*0a6a1f1dSLionel Sambuc     if (!(Section->second.SectionFlags & ASTContext::PSF_Implicit)) {
398*0a6a1f1dSLionel Sambuc       Diag(PragmaSectionLocation, diag::err_section_conflict)
399*0a6a1f1dSLionel Sambuc           << "this" << "a prior #pragma section";
400*0a6a1f1dSLionel Sambuc       Diag(Section->second.PragmaSectionLocation,
401*0a6a1f1dSLionel Sambuc            diag::note_pragma_entered_here);
402*0a6a1f1dSLionel Sambuc       return true;
403*0a6a1f1dSLionel Sambuc     }
404*0a6a1f1dSLionel Sambuc   }
405*0a6a1f1dSLionel Sambuc   Context.SectionInfos[SectionName] =
406*0a6a1f1dSLionel Sambuc       ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags);
407*0a6a1f1dSLionel Sambuc   return false;
408*0a6a1f1dSLionel Sambuc }
409*0a6a1f1dSLionel Sambuc 
410*0a6a1f1dSLionel Sambuc /// \brief Called on well formed \#pragma bss_seg().
ActOnPragmaMSSeg(SourceLocation PragmaLocation,PragmaMsStackAction Action,llvm::StringRef StackSlotLabel,StringLiteral * SegmentName,llvm::StringRef PragmaName)411*0a6a1f1dSLionel Sambuc void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation,
412*0a6a1f1dSLionel Sambuc                             PragmaMsStackAction Action,
413*0a6a1f1dSLionel Sambuc                             llvm::StringRef StackSlotLabel,
414*0a6a1f1dSLionel Sambuc                             StringLiteral *SegmentName,
415*0a6a1f1dSLionel Sambuc                             llvm::StringRef PragmaName) {
416*0a6a1f1dSLionel Sambuc   PragmaStack<StringLiteral *> *Stack =
417*0a6a1f1dSLionel Sambuc     llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName)
418*0a6a1f1dSLionel Sambuc         .Case("data_seg", &DataSegStack)
419*0a6a1f1dSLionel Sambuc         .Case("bss_seg", &BSSSegStack)
420*0a6a1f1dSLionel Sambuc         .Case("const_seg", &ConstSegStack)
421*0a6a1f1dSLionel Sambuc         .Case("code_seg", &CodeSegStack);
422*0a6a1f1dSLionel Sambuc   if (Action & PSK_Pop && Stack->Stack.empty())
423*0a6a1f1dSLionel Sambuc     Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName
424*0a6a1f1dSLionel Sambuc         << "stack empty";
425*0a6a1f1dSLionel Sambuc   Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName);
426*0a6a1f1dSLionel Sambuc }
427*0a6a1f1dSLionel Sambuc 
428*0a6a1f1dSLionel Sambuc /// \brief Called on well formed \#pragma bss_seg().
ActOnPragmaMSSection(SourceLocation PragmaLocation,int SectionFlags,StringLiteral * SegmentName)429*0a6a1f1dSLionel Sambuc void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation,
430*0a6a1f1dSLionel Sambuc                                 int SectionFlags, StringLiteral *SegmentName) {
431*0a6a1f1dSLionel Sambuc   UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation);
432*0a6a1f1dSLionel Sambuc }
433*0a6a1f1dSLionel Sambuc 
ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,StringLiteral * SegmentName)434*0a6a1f1dSLionel Sambuc void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
435*0a6a1f1dSLionel Sambuc                                 StringLiteral *SegmentName) {
436*0a6a1f1dSLionel Sambuc   // There's no stack to maintain, so we just have a current section.  When we
437*0a6a1f1dSLionel Sambuc   // see the default section, reset our current section back to null so we stop
438*0a6a1f1dSLionel Sambuc   // tacking on unnecessary attributes.
439*0a6a1f1dSLionel Sambuc   CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr : SegmentName;
440*0a6a1f1dSLionel Sambuc   CurInitSegLoc = PragmaLocation;
441*0a6a1f1dSLionel Sambuc }
442*0a6a1f1dSLionel Sambuc 
ActOnPragmaUnused(const Token & IdTok,Scope * curScope,SourceLocation PragmaLoc)443f4a2713aSLionel Sambuc void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
444f4a2713aSLionel Sambuc                              SourceLocation PragmaLoc) {
445f4a2713aSLionel Sambuc 
446f4a2713aSLionel Sambuc   IdentifierInfo *Name = IdTok.getIdentifierInfo();
447f4a2713aSLionel Sambuc   LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
448*0a6a1f1dSLionel Sambuc   LookupParsedName(Lookup, curScope, nullptr, true);
449f4a2713aSLionel Sambuc 
450f4a2713aSLionel Sambuc   if (Lookup.empty()) {
451f4a2713aSLionel Sambuc     Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
452f4a2713aSLionel Sambuc       << Name << SourceRange(IdTok.getLocation());
453f4a2713aSLionel Sambuc     return;
454f4a2713aSLionel Sambuc   }
455f4a2713aSLionel Sambuc 
456f4a2713aSLionel Sambuc   VarDecl *VD = Lookup.getAsSingle<VarDecl>();
457f4a2713aSLionel Sambuc   if (!VD) {
458f4a2713aSLionel Sambuc     Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
459f4a2713aSLionel Sambuc       << Name << SourceRange(IdTok.getLocation());
460f4a2713aSLionel Sambuc     return;
461f4a2713aSLionel Sambuc   }
462f4a2713aSLionel Sambuc 
463f4a2713aSLionel Sambuc   // Warn if this was used before being marked unused.
464f4a2713aSLionel Sambuc   if (VD->isUsed())
465f4a2713aSLionel Sambuc     Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
466f4a2713aSLionel Sambuc 
467*0a6a1f1dSLionel Sambuc   VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation()));
468f4a2713aSLionel Sambuc }
469f4a2713aSLionel Sambuc 
AddCFAuditedAttribute(Decl * D)470f4a2713aSLionel Sambuc void Sema::AddCFAuditedAttribute(Decl *D) {
471f4a2713aSLionel Sambuc   SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc();
472f4a2713aSLionel Sambuc   if (!Loc.isValid()) return;
473f4a2713aSLionel Sambuc 
474f4a2713aSLionel Sambuc   // Don't add a redundant or conflicting attribute.
475f4a2713aSLionel Sambuc   if (D->hasAttr<CFAuditedTransferAttr>() ||
476f4a2713aSLionel Sambuc       D->hasAttr<CFUnknownTransferAttr>())
477f4a2713aSLionel Sambuc     return;
478f4a2713aSLionel Sambuc 
479*0a6a1f1dSLionel Sambuc   D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
480*0a6a1f1dSLionel Sambuc }
481*0a6a1f1dSLionel Sambuc 
ActOnPragmaOptimize(bool On,SourceLocation PragmaLoc)482*0a6a1f1dSLionel Sambuc void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
483*0a6a1f1dSLionel Sambuc   if(On)
484*0a6a1f1dSLionel Sambuc     OptimizeOffPragmaLocation = SourceLocation();
485*0a6a1f1dSLionel Sambuc   else
486*0a6a1f1dSLionel Sambuc     OptimizeOffPragmaLocation = PragmaLoc;
487*0a6a1f1dSLionel Sambuc }
488*0a6a1f1dSLionel Sambuc 
AddRangeBasedOptnone(FunctionDecl * FD)489*0a6a1f1dSLionel Sambuc void Sema::AddRangeBasedOptnone(FunctionDecl *FD) {
490*0a6a1f1dSLionel Sambuc   // In the future, check other pragmas if they're implemented (e.g. pragma
491*0a6a1f1dSLionel Sambuc   // optimize 0 will probably map to this functionality too).
492*0a6a1f1dSLionel Sambuc   if(OptimizeOffPragmaLocation.isValid())
493*0a6a1f1dSLionel Sambuc     AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation);
494*0a6a1f1dSLionel Sambuc }
495*0a6a1f1dSLionel Sambuc 
AddOptnoneAttributeIfNoConflicts(FunctionDecl * FD,SourceLocation Loc)496*0a6a1f1dSLionel Sambuc void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD,
497*0a6a1f1dSLionel Sambuc                                             SourceLocation Loc) {
498*0a6a1f1dSLionel Sambuc   // Don't add a conflicting attribute. No diagnostic is needed.
499*0a6a1f1dSLionel Sambuc   if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>())
500*0a6a1f1dSLionel Sambuc     return;
501*0a6a1f1dSLionel Sambuc 
502*0a6a1f1dSLionel Sambuc   // Add attributes only if required. Optnone requires noinline as well, but if
503*0a6a1f1dSLionel Sambuc   // either is already present then don't bother adding them.
504*0a6a1f1dSLionel Sambuc   if (!FD->hasAttr<OptimizeNoneAttr>())
505*0a6a1f1dSLionel Sambuc     FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc));
506*0a6a1f1dSLionel Sambuc   if (!FD->hasAttr<NoInlineAttr>())
507*0a6a1f1dSLionel Sambuc     FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc));
508f4a2713aSLionel Sambuc }
509f4a2713aSLionel Sambuc 
510f4a2713aSLionel Sambuc typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
511*0a6a1f1dSLionel Sambuc enum : unsigned { NoVisibility = ~0U };
512f4a2713aSLionel Sambuc 
AddPushedVisibilityAttribute(Decl * D)513f4a2713aSLionel Sambuc void Sema::AddPushedVisibilityAttribute(Decl *D) {
514f4a2713aSLionel Sambuc   if (!VisContext)
515f4a2713aSLionel Sambuc     return;
516f4a2713aSLionel Sambuc 
517f4a2713aSLionel Sambuc   NamedDecl *ND = dyn_cast<NamedDecl>(D);
518f4a2713aSLionel Sambuc   if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue))
519f4a2713aSLionel Sambuc     return;
520f4a2713aSLionel Sambuc 
521f4a2713aSLionel Sambuc   VisStack *Stack = static_cast<VisStack*>(VisContext);
522f4a2713aSLionel Sambuc   unsigned rawType = Stack->back().first;
523f4a2713aSLionel Sambuc   if (rawType == NoVisibility) return;
524f4a2713aSLionel Sambuc 
525f4a2713aSLionel Sambuc   VisibilityAttr::VisibilityType type
526f4a2713aSLionel Sambuc     = (VisibilityAttr::VisibilityType) rawType;
527f4a2713aSLionel Sambuc   SourceLocation loc = Stack->back().second;
528f4a2713aSLionel Sambuc 
529*0a6a1f1dSLionel Sambuc   D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc));
530f4a2713aSLionel Sambuc }
531f4a2713aSLionel Sambuc 
532f4a2713aSLionel Sambuc /// FreeVisContext - Deallocate and null out VisContext.
FreeVisContext()533f4a2713aSLionel Sambuc void Sema::FreeVisContext() {
534f4a2713aSLionel Sambuc   delete static_cast<VisStack*>(VisContext);
535*0a6a1f1dSLionel Sambuc   VisContext = nullptr;
536f4a2713aSLionel Sambuc }
537f4a2713aSLionel Sambuc 
PushPragmaVisibility(Sema & S,unsigned type,SourceLocation loc)538f4a2713aSLionel Sambuc static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
539f4a2713aSLionel Sambuc   // Put visibility on stack.
540f4a2713aSLionel Sambuc   if (!S.VisContext)
541f4a2713aSLionel Sambuc     S.VisContext = new VisStack;
542f4a2713aSLionel Sambuc 
543f4a2713aSLionel Sambuc   VisStack *Stack = static_cast<VisStack*>(S.VisContext);
544f4a2713aSLionel Sambuc   Stack->push_back(std::make_pair(type, loc));
545f4a2713aSLionel Sambuc }
546f4a2713aSLionel Sambuc 
ActOnPragmaVisibility(const IdentifierInfo * VisType,SourceLocation PragmaLoc)547f4a2713aSLionel Sambuc void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType,
548f4a2713aSLionel Sambuc                                  SourceLocation PragmaLoc) {
549f4a2713aSLionel Sambuc   if (VisType) {
550f4a2713aSLionel Sambuc     // Compute visibility to use.
551f4a2713aSLionel Sambuc     VisibilityAttr::VisibilityType T;
552f4a2713aSLionel Sambuc     if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) {
553f4a2713aSLionel Sambuc       Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType;
554f4a2713aSLionel Sambuc       return;
555f4a2713aSLionel Sambuc     }
556f4a2713aSLionel Sambuc     PushPragmaVisibility(*this, T, PragmaLoc);
557f4a2713aSLionel Sambuc   } else {
558f4a2713aSLionel Sambuc     PopPragmaVisibility(false, PragmaLoc);
559f4a2713aSLionel Sambuc   }
560f4a2713aSLionel Sambuc }
561f4a2713aSLionel Sambuc 
ActOnPragmaFPContract(tok::OnOffSwitch OOS)562f4a2713aSLionel Sambuc void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
563f4a2713aSLionel Sambuc   switch (OOS) {
564f4a2713aSLionel Sambuc   case tok::OOS_ON:
565f4a2713aSLionel Sambuc     FPFeatures.fp_contract = 1;
566f4a2713aSLionel Sambuc     break;
567f4a2713aSLionel Sambuc   case tok::OOS_OFF:
568f4a2713aSLionel Sambuc     FPFeatures.fp_contract = 0;
569f4a2713aSLionel Sambuc     break;
570f4a2713aSLionel Sambuc   case tok::OOS_DEFAULT:
571f4a2713aSLionel Sambuc     FPFeatures.fp_contract = getLangOpts().DefaultFPContract;
572f4a2713aSLionel Sambuc     break;
573f4a2713aSLionel Sambuc   }
574f4a2713aSLionel Sambuc }
575f4a2713aSLionel Sambuc 
PushNamespaceVisibilityAttr(const VisibilityAttr * Attr,SourceLocation Loc)576f4a2713aSLionel Sambuc void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
577f4a2713aSLionel Sambuc                                        SourceLocation Loc) {
578f4a2713aSLionel Sambuc   // Visibility calculations will consider the namespace's visibility.
579f4a2713aSLionel Sambuc   // Here we just want to note that we're in a visibility context
580f4a2713aSLionel Sambuc   // which overrides any enclosing #pragma context, but doesn't itself
581f4a2713aSLionel Sambuc   // contribute visibility.
582f4a2713aSLionel Sambuc   PushPragmaVisibility(*this, NoVisibility, Loc);
583f4a2713aSLionel Sambuc }
584f4a2713aSLionel Sambuc 
PopPragmaVisibility(bool IsNamespaceEnd,SourceLocation EndLoc)585f4a2713aSLionel Sambuc void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
586f4a2713aSLionel Sambuc   if (!VisContext) {
587f4a2713aSLionel Sambuc     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
588f4a2713aSLionel Sambuc     return;
589f4a2713aSLionel Sambuc   }
590f4a2713aSLionel Sambuc 
591f4a2713aSLionel Sambuc   // Pop visibility from stack
592f4a2713aSLionel Sambuc   VisStack *Stack = static_cast<VisStack*>(VisContext);
593f4a2713aSLionel Sambuc 
594f4a2713aSLionel Sambuc   const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
595f4a2713aSLionel Sambuc   bool StartsWithPragma = Back->first != NoVisibility;
596f4a2713aSLionel Sambuc   if (StartsWithPragma && IsNamespaceEnd) {
597f4a2713aSLionel Sambuc     Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
598f4a2713aSLionel Sambuc     Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
599f4a2713aSLionel Sambuc 
600f4a2713aSLionel Sambuc     // For better error recovery, eat all pushes inside the namespace.
601f4a2713aSLionel Sambuc     do {
602f4a2713aSLionel Sambuc       Stack->pop_back();
603f4a2713aSLionel Sambuc       Back = &Stack->back();
604f4a2713aSLionel Sambuc       StartsWithPragma = Back->first != NoVisibility;
605f4a2713aSLionel Sambuc     } while (StartsWithPragma);
606f4a2713aSLionel Sambuc   } else if (!StartsWithPragma && !IsNamespaceEnd) {
607f4a2713aSLionel Sambuc     Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
608f4a2713aSLionel Sambuc     Diag(Back->second, diag::note_surrounding_namespace_starts_here);
609f4a2713aSLionel Sambuc     return;
610f4a2713aSLionel Sambuc   }
611f4a2713aSLionel Sambuc 
612f4a2713aSLionel Sambuc   Stack->pop_back();
613f4a2713aSLionel Sambuc   // To simplify the implementation, never keep around an empty stack.
614f4a2713aSLionel Sambuc   if (Stack->empty())
615f4a2713aSLionel Sambuc     FreeVisContext();
616f4a2713aSLionel Sambuc }
617