SemaAttr.cpp revision 199482
135124Sjb//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
235124Sjb//
335124Sjb//                     The LLVM Compiler Infrastructure
435124Sjb//
535124Sjb// This file is distributed under the University of Illinois Open Source
635124Sjb// License. See LICENSE.TXT for details.
735124Sjb//
835124Sjb//===----------------------------------------------------------------------===//
935124Sjb//
1035124Sjb// This file implements semantic analysis for non-trivial attributes and
1135124Sjb// pragmas.
1235124Sjb//
13165968Simp//===----------------------------------------------------------------------===//
1435124Sjb
1535124Sjb#include "Sema.h"
1635124Sjb#include "Lookup.h"
1735124Sjb#include "clang/AST/Expr.h"
1835124Sjbusing namespace clang;
1935124Sjb
2035124Sjb//===----------------------------------------------------------------------===//
2135124Sjb// Pragma Packed
2235124Sjb//===----------------------------------------------------------------------===//
2335124Sjb
2435124Sjbnamespace {
2535124Sjb  /// PragmaPackStack - Simple class to wrap the stack used by #pragma
2635124Sjb  /// pack.
2735124Sjb  class PragmaPackStack {
2835124Sjb    typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty;
2950476Speter
3035124Sjb    /// Alignment - The current user specified alignment.
3135124Sjb    unsigned Alignment;
3235124Sjb
3335124Sjb    /// Stack - Entries in the #pragma pack stack, consisting of saved
3435124Sjb    /// alignments and optional names.
3535124Sjb    stack_ty Stack;
3635124Sjb
37199606Sjhb  public:
3835124Sjb    PragmaPackStack() : Alignment(0) {}
3935124Sjb
4035124Sjb    void setAlignment(unsigned A) { Alignment = A; }
4135124Sjb    unsigned getAlignment() { return Alignment; }
4235124Sjb
4335124Sjb    /// push - Push the current alignment onto the stack, optionally
4435124Sjb    /// using the given \arg Name for the record, if non-zero.
4535124Sjb    void push(IdentifierInfo *Name) {
4635124Sjb      Stack.push_back(std::make_pair(Alignment, Name));
47231868Skib    }
48231868Skib
49231868Skib    /// pop - Pop a record from the stack and restore the current
50231868Skib    /// alignment to the previous value. If \arg Name is non-zero then
51231868Skib    /// the first such named record is popped, otherwise the top record
52231868Skib    /// is popped. Returns true if the pop succeeded.
53231868Skib    bool pop(IdentifierInfo *Name);
54231868Skib  };
55231868Skib}  // end anonymous namespace.
56228843Scperciva
57228843Scpercivabool PragmaPackStack::pop(IdentifierInfo *Name) {
58228843Scperciva  if (Stack.empty())
59228843Scperciva    return false;
60228843Scperciva
61228843Scperciva  // If name is empty just pop top.
62228843Scperciva  if (!Name) {
63228843Scperciva    Alignment = Stack.back().first;
64228843Scperciva    Stack.pop_back();
65228843Scperciva    return true;
66228843Scperciva  }
6735124Sjb
6835124Sjb  // Otherwise, find the named record.
6935124Sjb  for (unsigned i = Stack.size(); i != 0; ) {
7035124Sjb    --i;
7135124Sjb    if (Stack[i].second == Name) {
7235124Sjb      // Found it, pop up to and including this record.
7335124Sjb      Alignment = Stack[i].first;
7471579Sdeischen      Stack.erase(Stack.begin() + i, Stack.end());
7535124Sjb      return true;
7635124Sjb    }
7735124Sjb  }
7835124Sjb
7935124Sjb  return false;
8035124Sjb}
8135124Sjb
8271579Sdeischen
8335124Sjb/// FreePackedContext - Deallocate and null out PackContext.
84234657Skibvoid Sema::FreePackedContext() {
85234657Skib  delete static_cast<PragmaPackStack*>(PackContext);
86234657Skib  PackContext = 0;
87234657Skib}
88234657Skib
89234657Skib/// getPragmaPackAlignment() - Return the current alignment as specified by
90234657Skib/// the current #pragma pack directive, or 0 if none is currently active.
91234657Skibunsigned Sema::getPragmaPackAlignment() const {
92234657Skib  if (PackContext)
93234657Skib    return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
94234657Skib  return 0;
95234657Skib}
96234657Skib
9793399Smarkmvoid Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
98106866Sdeischen                           ExprTy *alignment, SourceLocation PragmaLoc,
99106866Sdeischen                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
100106866Sdeischen  Expr *Alignment = static_cast<Expr *>(alignment);
101106866Sdeischen
102106866Sdeischen  // If specified then alignment must be a "small" power of two.
103106866Sdeischen  unsigned AlignmentVal = 0;
104156319Sdeischen  if (Alignment) {
105156319Sdeischen    llvm::APSInt Val;
106156319Sdeischen
107156319Sdeischen    // pack(0) is like pack(), which just works out since that is what
108156319Sdeischen    // we use 0 for in PackAttr.
109156319Sdeischen    if (!Alignment->isIntegerConstantExpr(Val, Context) ||
110156319Sdeischen        !(Val == 0 || Val.isPowerOf2()) ||
111156319Sdeischen        Val.getZExtValue() > 16) {
112156319Sdeischen      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
113156319Sdeischen      Alignment->Destroy(Context);
114156319Sdeischen      return; // Ignore
115156319Sdeischen    }
116156319Sdeischen
117156319Sdeischen    AlignmentVal = (unsigned) Val.getZExtValue();
118156319Sdeischen  }
119156319Sdeischen
120156319Sdeischen  if (PackContext == 0)
121156319Sdeischen    PackContext = new PragmaPackStack();
122156319Sdeischen
123156319Sdeischen  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
124156319Sdeischen
125156319Sdeischen  switch (Kind) {
126106866Sdeischen  case Action::PPK_Default: // pack([n])
127106866Sdeischen    Context->setAlignment(AlignmentVal);
128106866Sdeischen    break;
129106866Sdeischen
130156319Sdeischen  case Action::PPK_Show: // pack(show)
131106866Sdeischen    // Show the current alignment, making sure to show the right value
132156319Sdeischen    // for the default.
133156319Sdeischen    AlignmentVal = Context->getAlignment();
134156319Sdeischen    // FIXME: This should come from the target.
135106866Sdeischen    if (AlignmentVal == 0)
136156319Sdeischen      AlignmentVal = 8;
137106866Sdeischen    Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
138106866Sdeischen    break;
139156319Sdeischen
140106866Sdeischen  case Action::PPK_Push: // pack(push [, id] [, [n])
141156319Sdeischen    Context->push(Name);
142156319Sdeischen    // Set the new alignment if specified.
143156319Sdeischen    if (Alignment)
144106866Sdeischen      Context->setAlignment(AlignmentVal);
145106866Sdeischen    break;
146106866Sdeischen
147106866Sdeischen  case Action::PPK_Pop: // pack(pop [, id] [,  n])
148106866Sdeischen    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
149106866Sdeischen    // "#pragma pack(pop, identifier, n) is undefined"
150106866Sdeischen    if (Alignment && Name)
151106866Sdeischen      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
152106866Sdeischen
153106866Sdeischen    // Do the pop.
154106866Sdeischen    if (!Context->pop(Name)) {
155106866Sdeischen      // If a name was specified then failure indicates the name
156106866Sdeischen      // wasn't found. Otherwise failure indicates the stack was
157106866Sdeischen      // empty.
158156319Sdeischen      Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
159156319Sdeischen        << (Name ? "no record matching name" : "stack empty");
160106866Sdeischen
161106866Sdeischen      // FIXME: Warn about popping named records as MSVC does.
162156319Sdeischen    } else {
163201546Sdavidxu      // Pop succeeded, set the new alignment if specified.
164201546Sdavidxu      if (Alignment)
165213153Sdavidxu        Context->setAlignment(AlignmentVal);
166213153Sdavidxu    }
167106866Sdeischen    break;
168106866Sdeischen
169106866Sdeischen  default:
170106870Sdeischen    assert(0 && "Invalid #pragma pack kind.");
171106880Sdeischen  }
172106866Sdeischen}
173106880Sdeischen
174106866Sdeischenvoid Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
175106866Sdeischen                             Scope *curScope,
176111618Snectar                             SourceLocation PragmaLoc,
177111618Snectar                             SourceLocation LParenLoc,
178111618Snectar                             SourceLocation RParenLoc) {
179111618Snectar
180111618Snectar  for (unsigned i = 0; i < NumIdentifiers; ++i) {
181111618Snectar    const Token &Tok = Identifiers[i];
182133754Sdfr    IdentifierInfo *Name = Tok.getIdentifierInfo();
183133754Sdfr    LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
184133754Sdfr    LookupParsedName(Lookup, curScope, NULL, true);
185133754Sdfr
186111618Snectar    NamedDecl *ND = Lookup.getAsSingleDecl(Context);
187111618Snectar
188199606Sjhb    if (!ND) {
189199606Sjhb      Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
190199606Sjhb        << Name << SourceRange(Tok.getLocation());
191199606Sjhb      continue;
192199606Sjhb    }
193199606Sjhb
194133754Sdfr    if (!isa<VarDecl>(ND) || !cast<VarDecl>(ND)->hasLocalStorage()) {
195133754Sdfr      Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
196133754Sdfr        << Name << SourceRange(Tok.getLocation());
197133754Sdfr      continue;
198133754Sdfr    }
19993399Smarkm
20093399Smarkm    ND->addAttr(::new (Context) UnusedAttr());
20193399Smarkm  }
20293399Smarkm}
20393399Smarkm