SemaAttr.cpp revision 4421d2b341d041df44013769f23c306308bbab83
15a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===//
25a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//
35a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//                     The LLVM Compiler Infrastructure
45a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//
55a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner// This file is distributed under the University of Illinois Open Source
65a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner// License. See LICENSE.TXT for details.
75a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//
85a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//===----------------------------------------------------------------------===//
95a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//
10574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner// This file implements semantic analysis for non-trivial attributes and
11574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner// pragmas.
125a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//
135a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner//===----------------------------------------------------------------------===//
145a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
152d88708cbe4e4ec5e04e4acb6bd7f5be68557379John McCall#include "clang/Sema/SemaInternal.h"
16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor#include "clang/Sema/Lookup.h"
17cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt#include "clang/AST/Attr.h"
185a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner#include "clang/AST/Expr.h"
19613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar#include "clang/Basic/TargetInfo.h"
20613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar#include "clang/Lex/Preprocessor.h"
215a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattnerusing namespace clang;
225a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
23574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner//===----------------------------------------------------------------------===//
24ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar// Pragma 'pack' and 'options align'
25574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner//===----------------------------------------------------------------------===//
26574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
27574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattnernamespace {
28ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar  struct PackStackEntry {
29c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    // We just use a sentinel to represent when the stack is set to mac68k
30c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    // alignment.
31c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    static const unsigned kMac68kAlignmentSentinel = ~0U;
32c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar
33ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar    unsigned Alignment;
34ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar    IdentifierInfo *Name;
35ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar  };
36ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar
37574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  /// PragmaPackStack - Simple class to wrap the stack used by #pragma
38574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  /// pack.
39574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  class PragmaPackStack {
40ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar    typedef std::vector<PackStackEntry> stack_ty;
41574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
42574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// Alignment - The current user specified alignment.
43574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    unsigned Alignment;
44574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
45574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// Stack - Entries in the #pragma pack stack, consisting of saved
46574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// alignments and optional names.
47574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    stack_ty Stack;
481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  public:
50574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    PragmaPackStack() : Alignment(0) {}
51574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
52574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    void setAlignment(unsigned A) { Alignment = A; }
53574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    unsigned getAlignment() { return Alignment; }
54574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
55574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// push - Push the current alignment onto the stack, optionally
56574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// using the given \arg Name for the record, if non-zero.
57574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    void push(IdentifierInfo *Name) {
58ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar      PackStackEntry PSE = { Alignment, Name };
59ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar      Stack.push_back(PSE);
60574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    }
61574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
62574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// pop - Pop a record from the stack and restore the current
63574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// alignment to the previous value. If \arg Name is non-zero then
64574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// the first such named record is popped, otherwise the top record
65574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    /// is popped. Returns true if the pop succeeded.
66ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar    bool pop(IdentifierInfo *Name, bool IsReset);
67574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  };
68574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner}  // end anonymous namespace.
69574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
70ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbarbool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
71574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  // If name is empty just pop top.
72574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  if (!Name) {
73ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar    // An empty stack is a special case...
74ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar    if (Stack.empty()) {
75ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      // If this isn't a reset, it is always an error.
76ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      if (!IsReset)
77ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar        return false;
78ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar
79ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      // Otherwise, it is an error only if some alignment has been set.
80ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      if (!Alignment)
81ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar        return false;
82ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar
83ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      // Otherwise, reset to the default alignment.
84ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      Alignment = 0;
85ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar    } else {
86ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      Alignment = Stack.back().Alignment;
87ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar      Stack.pop_back();
88ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar    }
89ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar
90574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    return true;
911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  }
921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
93574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  // Otherwise, find the named record.
94574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  for (unsigned i = Stack.size(); i != 0; ) {
95574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    --i;
96ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar    if (Stack[i].Name == Name) {
97574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner      // Found it, pop up to and including this record.
98ae2232b9957302374ee8d8626aeedcb4e4c0441eDaniel Dunbar      Alignment = Stack[i].Alignment;
99574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner      Stack.erase(Stack.begin() + i, Stack.end());
100574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner      return true;
101574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    }
102574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  }
1031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
104574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  return false;
105574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner}
106574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
107574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
108574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner/// FreePackedContext - Deallocate and null out PackContext.
109574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattnervoid Sema::FreePackedContext() {
110574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  delete static_cast<PragmaPackStack*>(PackContext);
111574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  PackContext = 0;
112574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner}
113574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
1149f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbarvoid Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
1159f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbar  // If there is no pack context, we don't need any attributes.
1169f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbar  if (!PackContext)
1179f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbar    return;
1189f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbar
1199f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbar  PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
1209f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbar
1219f21f89c323ccf32f6b27acd2e739f6535440df0Daniel Dunbar  // Otherwise, check to see if we need a max field alignment attribute.
122c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar  if (unsigned Alignment = Stack->getAlignment()) {
123c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
124cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context));
125c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    else
126cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(),
127cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                                                        Context,
128cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                                                        Alignment * 8));
129c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar  }
130574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner}
131574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner
132ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbarvoid Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
133ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar                                   SourceLocation PragmaLoc,
134ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar                                   SourceLocation KindLoc) {
135ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar  if (PackContext == 0)
136ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar    PackContext = new PragmaPackStack();
137ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar
138ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
139ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar
140ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar  // Reset just pops the top of the stack, or resets the current alignment to
141ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar  // default.
142f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall  if (Kind == Sema::POAK_Reset) {
143ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar    if (!Context->pop(0, /*IsReset=*/true)) {
144ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar      Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
145ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar        << "stack empty";
146ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar    }
147ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar    return;
148ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar  }
149ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar
150ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar  switch (Kind) {
151638e7cf3a09436dce7f3150ff8e4f27d190bd2edDaniel Dunbar    // For all targets we support native and natural are the same.
152638e7cf3a09436dce7f3150ff8e4f27d190bd2edDaniel Dunbar    //
153638e7cf3a09436dce7f3150ff8e4f27d190bd2edDaniel Dunbar    // FIXME: This is not true on Darwin/PPC.
154638e7cf3a09436dce7f3150ff8e4f27d190bd2edDaniel Dunbar  case POAK_Native:
155450f79340808e54cd4b39738f943217f6fc0c2beDaniel Dunbar  case POAK_Power:
156d6b305dcba95fc4928a2baa6bbeb15d22db9d061Daniel Dunbar  case POAK_Natural:
157450f79340808e54cd4b39738f943217f6fc0c2beDaniel Dunbar    Context->push(0);
158450f79340808e54cd4b39738f943217f6fc0c2beDaniel Dunbar    Context->setAlignment(0);
159450f79340808e54cd4b39738f943217f6fc0c2beDaniel Dunbar    break;
160450f79340808e54cd4b39738f943217f6fc0c2beDaniel Dunbar
1616f739145b94ede1ca98b5a5e0e179c817c405d7bDaniel Dunbar    // Note that '#pragma options align=packed' is not equivalent to attribute
1626f739145b94ede1ca98b5a5e0e179c817c405d7bDaniel Dunbar    // packed, it has a different precedence relative to attribute aligned.
1636f739145b94ede1ca98b5a5e0e179c817c405d7bDaniel Dunbar  case POAK_Packed:
1646f739145b94ede1ca98b5a5e0e179c817c405d7bDaniel Dunbar    Context->push(0);
1656f739145b94ede1ca98b5a5e0e179c817c405d7bDaniel Dunbar    Context->setAlignment(1);
1666f739145b94ede1ca98b5a5e0e179c817c405d7bDaniel Dunbar    break;
1676f739145b94ede1ca98b5a5e0e179c817c405d7bDaniel Dunbar
168613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar  case POAK_Mac68k:
169613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar    // Check if the target supports this.
170613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar    if (!PP.getTargetInfo().hasAlignMac68kSupport()) {
171613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar      Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
172613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar      return;
173613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar    }
174c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    Context->push(0);
175c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
176613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar    break;
177613fd67e575ff1c038535b18dafebca070f3ed91Daniel Dunbar
178ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar  default:
179ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar    Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option)
180ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar      << KindLoc;
181ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar    break;
182ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar  }
183ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar}
184ea75a8286fb87ce7549e08d9dcb597f91479f54dDaniel Dunbar
1851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
1861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                           ExprTy *alignment, SourceLocation PragmaLoc,
1875a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
1885a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  Expr *Alignment = static_cast<Expr *>(alignment);
1895a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
1905a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  // If specified then alignment must be a "small" power of two.
1915a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  unsigned AlignmentVal = 0;
1925a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  if (Alignment) {
1935a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    llvm::APSInt Val;
1941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
19579cd11620c6f05dbf7bb706744eba354574e8b54Daniel Dunbar    // pack(0) is like pack(), which just works out since that is what
19679cd11620c6f05dbf7bb706744eba354574e8b54Daniel Dunbar    // we use 0 for in PackAttr.
197ac06a0e1e3feb95c2ffd352c086882b492a65b99Douglas Gregor    if (Alignment->isTypeDependent() ||
198ac06a0e1e3feb95c2ffd352c086882b492a65b99Douglas Gregor        Alignment->isValueDependent() ||
199ac06a0e1e3feb95c2ffd352c086882b492a65b99Douglas Gregor        !Alignment->isIntegerConstantExpr(Val, Context) ||
20079cd11620c6f05dbf7bb706744eba354574e8b54Daniel Dunbar        !(Val == 0 || Val.isPowerOf2()) ||
2015a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner        Val.getZExtValue() > 16) {
2025a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
2035a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      return; // Ignore
2045a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    }
2055a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
2065a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    AlignmentVal = (unsigned) Val.getZExtValue();
2075a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  }
2081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
209574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  if (PackContext == 0)
210574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    PackContext = new PragmaPackStack();
2111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
212574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
2131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2145a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  switch (Kind) {
215f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall  case Sema::PPK_Default: // pack([n])
216574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    Context->setAlignment(AlignmentVal);
2175a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    break;
2185a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
219f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall  case Sema::PPK_Show: // pack(show)
2205a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    // Show the current alignment, making sure to show the right value
2215a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    // for the default.
222574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    AlignmentVal = Context->getAlignment();
2235a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    // FIXME: This should come from the target.
2245a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    if (AlignmentVal == 0)
2255a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      AlignmentVal = 8;
226c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
227c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar      Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
228c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar    else
229c6082fe347a414a2e19f2ad8fe41720f10733296Daniel Dunbar      Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
2305a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    break;
2315a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
232f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall  case Sema::PPK_Push: // pack(push [, id] [, [n])
233574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner    Context->push(Name);
2345a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    // Set the new alignment if specified.
2355a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    if (Alignment)
2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      Context->setAlignment(AlignmentVal);
2375a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    break;
2385a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
239f312b1ea179f1c44371f9ee0cd0bc006f612de11John McCall  case Sema::PPK_Pop: // pack(pop [, id] [,  n])
2405a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
2415a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    // "#pragma pack(pop, identifier, n) is undefined"
2425a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    if (Alignment && Name)
2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
2441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2455a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    // Do the pop.
246ddc6ff6b9aff656504c1e84ee7dc9f617a20f866Daniel Dunbar    if (!Context->pop(Name, /*IsReset=*/false)) {
2475a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      // If a name was specified then failure indicates the name
2485a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      // wasn't found. Otherwise failure indicates the stack was
2495a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      // empty.
2505a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
2515a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner        << (Name ? "no record matching name" : "stack empty");
2525a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
2535a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      // FIXME: Warn about popping named records as MSVC does.
2545a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    } else {
2555a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      // Pop succeeded, set the new alignment if specified.
2565a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner      if (Alignment)
257574aa40703ffb2fddad5b076cec1c2fc27f0b2d3Chris Lattner        Context->setAlignment(AlignmentVal);
2585a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    }
2595a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    break;
2605a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
2615a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  default:
2625a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner    assert(0 && "Invalid #pragma pack kind.");
2635a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner  }
2645a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner}
2655a0c35150102f95ab270f741cdab5907c9bd9017Chris Lattner
266b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidisvoid Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,
267b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis                             SourceLocation PragmaLoc) {
2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
269b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  IdentifierInfo *Name = IdTok.getIdentifierInfo();
270b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
271b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  LookupParsedName(Lookup, curScope, NULL, true);
2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
273b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  if (Lookup.empty()) {
274b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis    Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
275b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis      << Name << SourceRange(IdTok.getLocation());
276b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis    return;
277b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  }
2782127eccbe15fd3b1b29aa53ccedd2e0f55ad27f9Anders Carlsson
279b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  VarDecl *VD = Lookup.getAsSingle<VarDecl>();
2802a5c45b1ae4406459fbb39cb477951987c59cb0fArgyrios Kyrtzidis  if (!VD) {
2812a5c45b1ae4406459fbb39cb477951987c59cb0fArgyrios Kyrtzidis    Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg)
282b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis      << Name << SourceRange(IdTok.getLocation());
283b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis    return;
2844726d03ab3abce41911c31d1354a18f1258cae4dTed Kremenek  }
285b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis
286b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  // Warn if this was used before being marked unused.
287b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  if (VD->isUsed())
288b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis    Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name;
289b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis
290b918d0f5d8f147e1e26c34e6cf42a79af2d2ec41Argyrios Kyrtzidis  VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context));
2914726d03ab3abce41911c31d1354a18f1258cae4dTed Kremenek}
292aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
29390f1450c109fbbd333001165bbd986061f7c4513John McCalltypedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
29490f1450c109fbbd333001165bbd986061f7c4513John McCallenum { NoVisibility = (unsigned) -1 };
295aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
296aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedmanvoid Sema::AddPushedVisibilityAttribute(Decl *D) {
297aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  if (!VisContext)
298aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    return;
299aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
3004421d2b341d041df44013769f23c306308bbab83Douglas Gregor  if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility())
301aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    return;
302aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
303aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  VisStack *Stack = static_cast<VisStack*>(VisContext);
30490f1450c109fbbd333001165bbd986061f7c4513John McCall  unsigned rawType = Stack->back().first;
30590f1450c109fbbd333001165bbd986061f7c4513John McCall  if (rawType == NoVisibility) return;
30690f1450c109fbbd333001165bbd986061f7c4513John McCall
30790f1450c109fbbd333001165bbd986061f7c4513John McCall  VisibilityAttr::VisibilityType type
30890f1450c109fbbd333001165bbd986061f7c4513John McCall    = (VisibilityAttr::VisibilityType) rawType;
309cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  SourceLocation loc = Stack->back().second;
310aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
311cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
312aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman}
313aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
314aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman/// FreeVisContext - Deallocate and null out VisContext.
315aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedmanvoid Sema::FreeVisContext() {
316aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  delete static_cast<VisStack*>(VisContext);
317aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  VisContext = 0;
318aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman}
319aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
32090f1450c109fbbd333001165bbd986061f7c4513John McCallstatic void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
321ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall  // Put visibility on stack.
322ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall  if (!S.VisContext)
323ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall    S.VisContext = new VisStack;
324ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall
325ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall  VisStack *Stack = static_cast<VisStack*>(S.VisContext);
326ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall  Stack->push_back(std::make_pair(type, loc));
327ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall}
328ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall
329aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedmanvoid Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
330aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman                                 SourceLocation PragmaLoc) {
331aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  if (IsPush) {
332aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    // Compute visibility to use.
333cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    VisibilityAttr::VisibilityType type;
334aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    if (VisType->isStr("default"))
335cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      type = VisibilityAttr::Default;
336aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    else if (VisType->isStr("hidden"))
337cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      type = VisibilityAttr::Hidden;
338aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    else if (VisType->isStr("internal"))
339cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      type = VisibilityAttr::Hidden; // FIXME
340aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    else if (VisType->isStr("protected"))
341cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      type = VisibilityAttr::Protected;
342aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    else {
343aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman      Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
344aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman        VisType->getName();
345aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman      return;
346aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    }
347ea318642072d3d94b5c3cff0fa6f4b33d2db0768John McCall    PushPragmaVisibility(*this, type, PragmaLoc);
348aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  } else {
349aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    PopPragmaVisibility();
350aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  }
351aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman}
352aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
353321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbournevoid Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) {
354321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne  switch (OOS) {
355321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne  case tok::OOS_ON:
356321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne    FPFeatures.fp_contract = 1;
357321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne    break;
358321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne  case tok::OOS_OFF:
359321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne    FPFeatures.fp_contract = 0;
360321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne    break;
361321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne  case tok::OOS_DEFAULT:
362321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne    FPFeatures.fp_contract = getLangOptions().DefaultFPContract;
363321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne    break;
364321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne  }
365321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne}
366321b8179afaf803dcc56b2a19f7b0891a03c92c8Peter Collingbourne
36790f1450c109fbbd333001165bbd986061f7c4513John McCallvoid Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) {
36890f1450c109fbbd333001165bbd986061f7c4513John McCall  // Visibility calculations will consider the namespace's visibility.
36990f1450c109fbbd333001165bbd986061f7c4513John McCall  // Here we just want to note that we're in a visibility context
37090f1450c109fbbd333001165bbd986061f7c4513John McCall  // which overrides any enclosing #pragma context, but doesn't itself
37190f1450c109fbbd333001165bbd986061f7c4513John McCall  // contribute visibility.
37290f1450c109fbbd333001165bbd986061f7c4513John McCall  PushPragmaVisibility(*this, NoVisibility, SourceLocation());
373aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman}
374aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
375aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedmanvoid Sema::PopPragmaVisibility() {
376aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  // Pop visibility from stack, if there is one on the stack.
377aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  if (VisContext) {
378aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    VisStack *Stack = static_cast<VisStack*>(VisContext);
379aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman
380aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    Stack->pop_back();
381aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    // To simplify the implementation, never keep around an empty stack.
382aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman    if (Stack->empty())
383aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman      FreeVisContext();
384aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  }
385aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman  // FIXME: Add diag for pop without push.
386aa8b0d19244a6e7e8e5798fcc6aef003c274d3e0Eli Friedman}
387