SemaAttr.cpp revision c6082fe347a414a2e19f2ad8fe41720f10733296
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 "Sema.h"
16#include "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);
66  };
67}  // end anonymous namespace.
68
69bool PragmaPackStack::pop(IdentifierInfo *Name) {
70  if (Stack.empty())
71    return false;
72
73  // If name is empty just pop top.
74  if (!Name) {
75    Alignment = Stack.back().Alignment;
76    Stack.pop_back();
77    return true;
78  }
79
80  // Otherwise, find the named record.
81  for (unsigned i = Stack.size(); i != 0; ) {
82    --i;
83    if (Stack[i].Name == Name) {
84      // Found it, pop up to and including this record.
85      Alignment = Stack[i].Alignment;
86      Stack.erase(Stack.begin() + i, Stack.end());
87      return true;
88    }
89  }
90
91  return false;
92}
93
94
95/// FreePackedContext - Deallocate and null out PackContext.
96void Sema::FreePackedContext() {
97  delete static_cast<PragmaPackStack*>(PackContext);
98  PackContext = 0;
99}
100
101void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
102  // If there is no pack context, we don't need any attributes.
103  if (!PackContext)
104    return;
105
106  PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
107
108  // Otherwise, check to see if we need a max field alignment attribute.
109  if (unsigned Alignment = Stack->getAlignment()) {
110    if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
111      RD->addAttr(::new (Context) AlignMac68kAttr());
112    else
113      RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8));
114  }
115}
116
117void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
118                                   SourceLocation PragmaLoc,
119                                   SourceLocation KindLoc) {
120  if (PackContext == 0)
121    PackContext = new PragmaPackStack();
122
123  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
124
125  // Reset just pops the top of the stack.
126  if (Kind == Action::POAK_Reset) {
127    // Do the pop.
128    if (!Context->pop(0)) {
129      // If a name was specified then failure indicates the name
130      // wasn't found. Otherwise failure indicates the stack was
131      // empty.
132      Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
133        << "stack empty";
134    }
135    return;
136  }
137
138  // We don't support #pragma options align=power.
139  switch (Kind) {
140  case POAK_Natural:
141    Context->push(0);
142    Context->setAlignment(0);
143    break;
144
145  case POAK_Mac68k:
146    // Check if the target supports this.
147    if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
148      Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
149      return;
150    }
151    Context->push(0);
152    Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
153    break;
154
155  default:
156    Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
157      << KindLoc;
158    break;
159  }
160}
161
162void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
163                           ExprTy *alignment, SourceLocation PragmaLoc,
164                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
165  Expr *Alignment = static_cast<Expr *>(alignment);
166
167  // If specified then alignment must be a "small" power of two.
168  unsigned AlignmentVal = 0;
169  if (Alignment) {
170    llvm::APSInt Val;
171
172    // pack(0) is like pack(), which just works out since that is what
173    // we use 0 for in PackAttr.
174    if (Alignment->isTypeDependent() ||
175        Alignment->isValueDependent() ||
176        !Alignment->isIntegerConstantExpr(Val, Context) ||
177        !(Val == 0 || Val.isPowerOf2()) ||
178        Val.getZExtValue() > 16) {
179      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
180      Alignment->Destroy(Context);
181      return; // Ignore
182    }
183
184    AlignmentVal = (unsigned) Val.getZExtValue();
185  }
186
187  if (PackContext == 0)
188    PackContext = new PragmaPackStack();
189
190  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
191
192  switch (Kind) {
193  case Action::PPK_Default: // pack([n])
194    Context->setAlignment(AlignmentVal);
195    break;
196
197  case Action::PPK_Show: // pack(show)
198    // Show the current alignment, making sure to show the right value
199    // for the default.
200    AlignmentVal = Context->getAlignment();
201    // FIXME: This should come from the target.
202    if (AlignmentVal == 0)
203      AlignmentVal = 8;
204    if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
205      Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
206    else
207      Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
208    break;
209
210  case Action::PPK_Push: // pack(push [, id] [, [n])
211    Context->push(Name);
212    // Set the new alignment if specified.
213    if (Alignment)
214      Context->setAlignment(AlignmentVal);
215    break;
216
217  case Action::PPK_Pop: // pack(pop [, id] [,  n])
218    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
219    // "#pragma pack(pop, identifier, n) is undefined"
220    if (Alignment && Name)
221      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
222
223    // Do the pop.
224    if (!Context->pop(Name)) {
225      // If a name was specified then failure indicates the name
226      // wasn't found. Otherwise failure indicates the stack was
227      // empty.
228      Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
229        << (Name ? "no record matching name" : "stack empty");
230
231      // FIXME: Warn about popping named records as MSVC does.
232    } else {
233      // Pop succeeded, set the new alignment if specified.
234      if (Alignment)
235        Context->setAlignment(AlignmentVal);
236    }
237    break;
238
239  default:
240    assert(0 && "Invalid #pragma pack kind.");
241  }
242}
243
244void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
245                             Scope *curScope,
246                             SourceLocation PragmaLoc,
247                             SourceLocation LParenLoc,
248                             SourceLocation RParenLoc) {
249
250  for (unsigned i = 0; i < NumIdentifiers; ++i) {
251    const Token &Tok = Identifiers[i];
252    IdentifierInfo *Name = Tok.getIdentifierInfo();
253    LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
254    LookupParsedName(Lookup, curScope, NULL, true);
255
256    if (Lookup.empty()) {
257      Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
258        << Name << SourceRange(Tok.getLocation());
259      continue;
260    }
261
262    VarDecl *VD = Lookup.getAsSingle<VarDecl>();
263    if (!VD || !VD->hasLocalStorage()) {
264      Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
265        << Name << SourceRange(Tok.getLocation());
266      continue;
267    }
268
269    VD->addAttr(::new (Context) UnusedAttr());
270  }
271}
272