SemaAttr.cpp revision e737f5041a36d0befb39ffeed8d50ba15916d3da
1//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements semantic analysis for non-trivial attributes and
11// pragmas.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Sema/Sema.h"
16#include "clang/Sema/Lookup.h"
17#include "clang/AST/Expr.h"
18#include "clang/Basic/TargetInfo.h"
19#include "clang/Lex/Preprocessor.h"
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// Pragma 'pack' and 'options align'
24//===----------------------------------------------------------------------===//
25
26namespace {
27  struct PackStackEntry {
28    // We just use a sentinel to represent when the stack is set to mac68k
29    // alignment.
30    static const unsigned kMac68kAlignmentSentinel = ~0U;
31
32    unsigned Alignment;
33    IdentifierInfo *Name;
34  };
35
36  /// PragmaPackStack - Simple class to wrap the stack used by #pragma
37  /// pack.
38  class PragmaPackStack {
39    typedef std::vector<PackStackEntry> stack_ty;
40
41    /// Alignment - The current user specified alignment.
42    unsigned Alignment;
43
44    /// Stack - Entries in the #pragma pack stack, consisting of saved
45    /// alignments and optional names.
46    stack_ty Stack;
47
48  public:
49    PragmaPackStack() : Alignment(0) {}
50
51    void setAlignment(unsigned A) { Alignment = A; }
52    unsigned getAlignment() { return Alignment; }
53
54    /// push - Push the current alignment onto the stack, optionally
55    /// using the given \arg Name for the record, if non-zero.
56    void push(IdentifierInfo *Name) {
57      PackStackEntry PSE = { Alignment, Name };
58      Stack.push_back(PSE);
59    }
60
61    /// pop - Pop a record from the stack and restore the current
62    /// alignment to the previous value. If \arg Name is non-zero then
63    /// the first such named record is popped, otherwise the top record
64    /// is popped. Returns true if the pop succeeded.
65    bool pop(IdentifierInfo *Name, bool IsReset);
66  };
67}  // end anonymous namespace.
68
69bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
70  // If name is empty just pop top.
71  if (!Name) {
72    // An empty stack is a special case...
73    if (Stack.empty()) {
74      // If this isn't a reset, it is always an error.
75      if (!IsReset)
76        return false;
77
78      // Otherwise, it is an error only if some alignment has been set.
79      if (!Alignment)
80        return false;
81
82      // Otherwise, reset to the default alignment.
83      Alignment = 0;
84    } else {
85      Alignment = Stack.back().Alignment;
86      Stack.pop_back();
87    }
88
89    return true;
90  }
91
92  // Otherwise, find the named record.
93  for (unsigned i = Stack.size(); i != 0; ) {
94    --i;
95    if (Stack[i].Name == Name) {
96      // Found it, pop up to and including this record.
97      Alignment = Stack[i].Alignment;
98      Stack.erase(Stack.begin() + i, Stack.end());
99      return true;
100    }
101  }
102
103  return false;
104}
105
106
107/// FreePackedContext - Deallocate and null out PackContext.
108void Sema::FreePackedContext() {
109  delete static_cast<PragmaPackStack*>(PackContext);
110  PackContext = 0;
111}
112
113void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
114  // If there is no pack context, we don't need any attributes.
115  if (!PackContext)
116    return;
117
118  PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
119
120  // Otherwise, check to see if we need a max field alignment attribute.
121  if (unsigned Alignment = Stack->getAlignment()) {
122    if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
123      RD->addAttr(::new (Context) AlignMac68kAttr());
124    else
125      RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
126  }
127}
128
129void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
130                                   SourceLocation PragmaLoc,
131                                   SourceLocation KindLoc) {
132  if (PackContext == 0)
133    PackContext = new PragmaPackStack();
134
135  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
136
137  // Reset just pops the top of the stack, or resets the current alignment to
138  // default.
139  if (Kind == Action::POAK_Reset) {
140    if (!Context->pop(0, /*IsReset=*/true)) {
141      Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
142        << "stack empty";
143    }
144    return;
145  }
146
147  switch (Kind) {
148    // For all targets we support native and natural are the same.
149    //
150    // FIXME: This is not true on Darwin/PPC.
151  case POAK_Native:
152  case POAK_Power:
153  case POAK_Natural:
154    Context->push(0);
155    Context->setAlignment(0);
156    break;
157
158    // Note that '#pragma options align=packed' is not equivalent to attribute
159    // packed, it has a different precedence relative to attribute aligned.
160  case POAK_Packed:
161    Context->push(0);
162    Context->setAlignment(1);
163    break;
164
165  case POAK_Mac68k:
166    // Check if the target supports this.
167    if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
168      Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
169      return;
170    }
171    Context->push(0);
172    Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
173    break;
174
175  default:
176    Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
177      << KindLoc;
178    break;
179  }
180}
181
182void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
183                           ExprTy *alignment, SourceLocation PragmaLoc,
184                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
185  Expr *Alignment = static_cast<Expr *>(alignment);
186
187  // If specified then alignment must be a "small" power of two.
188  unsigned AlignmentVal = 0;
189  if (Alignment) {
190    llvm::APSInt Val;
191
192    // pack(0) is like pack(), which just works out since that is what
193    // we use 0 for in PackAttr.
194    if (Alignment->isTypeDependent() ||
195        Alignment->isValueDependent() ||
196        !Alignment->isIntegerConstantExpr(Val, Context) ||
197        !(Val == 0 || Val.isPowerOf2()) ||
198        Val.getZExtValue() > 16) {
199      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
200      return; // Ignore
201    }
202
203    AlignmentVal = (unsigned) Val.getZExtValue();
204  }
205
206  if (PackContext == 0)
207    PackContext = new PragmaPackStack();
208
209  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
210
211  switch (Kind) {
212  case Action::PPK_Default: // pack([n])
213    Context->setAlignment(AlignmentVal);
214    break;
215
216  case Action::PPK_Show: // pack(show)
217    // Show the current alignment, making sure to show the right value
218    // for the default.
219    AlignmentVal = Context->getAlignment();
220    // FIXME: This should come from the target.
221    if (AlignmentVal == 0)
222      AlignmentVal = 8;
223    if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
224      Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
225    else
226      Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
227    break;
228
229  case Action::PPK_Push: // pack(push [, id] [, [n])
230    Context->push(Name);
231    // Set the new alignment if specified.
232    if (Alignment)
233      Context->setAlignment(AlignmentVal);
234    break;
235
236  case Action::PPK_Pop: // pack(pop [, id] [,  n])
237    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
238    // "#pragma pack(pop, identifier, n) is undefined"
239    if (Alignment && Name)
240      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
241
242    // Do the pop.
243    if (!Context->pop(Name, /*IsReset=*/false)) {
244      // If a name was specified then failure indicates the name
245      // wasn't found. Otherwise failure indicates the stack was
246      // empty.
247      Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
248        << (Name ? "no record matching name" : "stack empty");
249
250      // FIXME: Warn about popping named records as MSVC does.
251    } else {
252      // Pop succeeded, set the new alignment if specified.
253      if (Alignment)
254        Context->setAlignment(AlignmentVal);
255    }
256    break;
257
258  default:
259    assert(0 && "Invalid #pragma pack kind.");
260  }
261}
262
263void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
264                             Scope *curScope,
265                             SourceLocation PragmaLoc,
266                             SourceLocation LParenLoc,
267                             SourceLocation RParenLoc) {
268
269  for (unsigned i = 0; i < NumIdentifiers; ++i) {
270    const Token &Tok = Identifiers[i];
271    IdentifierInfo *Name = Tok.getIdentifierInfo();
272    LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
273    LookupParsedName(Lookup, curScope, NULL, true);
274
275    if (Lookup.empty()) {
276      Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
277        << Name << SourceRange(Tok.getLocation());
278      continue;
279    }
280
281    VarDecl *VD = Lookup.getAsSingle<VarDecl>();
282    if (!VD || !VD->hasLocalStorage()) {
283      Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
284        << Name << SourceRange(Tok.getLocation());
285      continue;
286    }
287
288    VD->addAttr(::new (Context) UnusedAttr());
289  }
290}
291
292typedef std::vector<VisibilityAttr::VisibilityTypes> VisStack;
293
294void Sema::AddPushedVisibilityAttribute(Decl *D) {
295  if (!VisContext)
296    return;
297
298  if (D->hasAttr<VisibilityAttr>())
299    return;
300
301  VisStack *Stack = static_cast<VisStack*>(VisContext);
302  VisibilityAttr::VisibilityTypes type = Stack->back();
303
304  D->addAttr(::new (Context) VisibilityAttr(type, true));
305}
306
307/// FreeVisContext - Deallocate and null out VisContext.
308void Sema::FreeVisContext() {
309  delete static_cast<VisStack*>(VisContext);
310  VisContext = 0;
311}
312
313void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
314                                 SourceLocation PragmaLoc) {
315  if (IsPush) {
316    // Compute visibility to use.
317    VisibilityAttr::VisibilityTypes type;
318    if (VisType->isStr("default"))
319      type = VisibilityAttr::DefaultVisibility;
320    else if (VisType->isStr("hidden"))
321      type = VisibilityAttr::HiddenVisibility;
322    else if (VisType->isStr("internal"))
323      type = VisibilityAttr::HiddenVisibility; // FIXME
324    else if (VisType->isStr("protected"))
325      type = VisibilityAttr::ProtectedVisibility;
326    else {
327      Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
328        VisType->getName();
329      return;
330    }
331    PushPragmaVisibility(type);
332  } else {
333    PopPragmaVisibility();
334  }
335}
336
337void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityTypes type) {
338  // Put visibility on stack.
339  if (!VisContext)
340    VisContext = new VisStack;
341
342  VisStack *Stack = static_cast<VisStack*>(VisContext);
343  Stack->push_back(type);
344}
345
346void Sema::PopPragmaVisibility() {
347  // Pop visibility from stack, if there is one on the stack.
348  if (VisContext) {
349    VisStack *Stack = static_cast<VisStack*>(VisContext);
350
351    Stack->pop_back();
352    // To simplify the implementation, never keep around an empty stack.
353    if (Stack->empty())
354      FreeVisContext();
355  }
356  // FIXME: Add diag for pop without push.
357}
358