blob: 095f537f710214a1cc51178a0355e57ef733d4c3 [file] [log] [blame]
Chris Lattner5a0c3512009-02-17 00:57:29 +00001//===--- 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//
Chris Lattner574aa402009-02-17 01:09:29 +000010// This file implements semantic analysis for non-trivial attributes and
11// pragmas.
Chris Lattner5a0c3512009-02-17 00:57:29 +000012//
13//===----------------------------------------------------------------------===//
14
15#include "Sema.h"
John McCall7d384dd2009-11-18 07:57:50 +000016#include "Lookup.h"
Chris Lattner5a0c3512009-02-17 00:57:29 +000017#include "clang/AST/Expr.h"
18using namespace clang;
19
Chris Lattner574aa402009-02-17 01:09:29 +000020//===----------------------------------------------------------------------===//
21// Pragma Packed
22//===----------------------------------------------------------------------===//
23
24namespace {
25 /// PragmaPackStack - Simple class to wrap the stack used by #pragma
26 /// pack.
27 class PragmaPackStack {
28 typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty;
29
30 /// Alignment - The current user specified alignment.
31 unsigned Alignment;
32
33 /// Stack - Entries in the #pragma pack stack, consisting of saved
34 /// alignments and optional names.
35 stack_ty Stack;
Mike Stump1eb44332009-09-09 15:08:12 +000036
37 public:
Chris Lattner574aa402009-02-17 01:09:29 +000038 PragmaPackStack() : Alignment(0) {}
39
40 void setAlignment(unsigned A) { Alignment = A; }
41 unsigned getAlignment() { return Alignment; }
42
43 /// push - Push the current alignment onto the stack, optionally
44 /// using the given \arg Name for the record, if non-zero.
45 void push(IdentifierInfo *Name) {
46 Stack.push_back(std::make_pair(Alignment, Name));
47 }
48
49 /// pop - Pop a record from the stack and restore the current
50 /// alignment to the previous value. If \arg Name is non-zero then
51 /// the first such named record is popped, otherwise the top record
52 /// is popped. Returns true if the pop succeeded.
53 bool pop(IdentifierInfo *Name);
54 };
55} // end anonymous namespace.
56
57bool PragmaPackStack::pop(IdentifierInfo *Name) {
58 if (Stack.empty())
59 return false;
Mike Stump1eb44332009-09-09 15:08:12 +000060
Chris Lattner574aa402009-02-17 01:09:29 +000061 // If name is empty just pop top.
62 if (!Name) {
63 Alignment = Stack.back().first;
64 Stack.pop_back();
65 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000066 }
67
Chris Lattner574aa402009-02-17 01:09:29 +000068 // Otherwise, find the named record.
69 for (unsigned i = Stack.size(); i != 0; ) {
70 --i;
71 if (Stack[i].second == Name) {
72 // Found it, pop up to and including this record.
73 Alignment = Stack[i].first;
74 Stack.erase(Stack.begin() + i, Stack.end());
75 return true;
76 }
77 }
Mike Stump1eb44332009-09-09 15:08:12 +000078
Chris Lattner574aa402009-02-17 01:09:29 +000079 return false;
80}
81
82
83/// FreePackedContext - Deallocate and null out PackContext.
84void Sema::FreePackedContext() {
85 delete static_cast<PragmaPackStack*>(PackContext);
86 PackContext = 0;
87}
88
89/// getPragmaPackAlignment() - Return the current alignment as specified by
90/// the current #pragma pack directive, or 0 if none is currently active.
91unsigned Sema::getPragmaPackAlignment() const {
92 if (PackContext)
93 return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
94 return 0;
95}
96
Mike Stump1eb44332009-09-09 15:08:12 +000097void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
98 ExprTy *alignment, SourceLocation PragmaLoc,
Chris Lattner5a0c3512009-02-17 00:57:29 +000099 SourceLocation LParenLoc, SourceLocation RParenLoc) {
100 Expr *Alignment = static_cast<Expr *>(alignment);
101
102 // If specified then alignment must be a "small" power of two.
103 unsigned AlignmentVal = 0;
104 if (Alignment) {
105 llvm::APSInt Val;
Mike Stump1eb44332009-09-09 15:08:12 +0000106
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000107 // pack(0) is like pack(), which just works out since that is what
108 // we use 0 for in PackAttr.
Chris Lattner5a0c3512009-02-17 00:57:29 +0000109 if (!Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000110 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000111 Val.getZExtValue() > 16) {
112 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
113 Alignment->Destroy(Context);
114 return; // Ignore
115 }
116
117 AlignmentVal = (unsigned) Val.getZExtValue();
118 }
Mike Stump1eb44332009-09-09 15:08:12 +0000119
Chris Lattner574aa402009-02-17 01:09:29 +0000120 if (PackContext == 0)
121 PackContext = new PragmaPackStack();
Mike Stump1eb44332009-09-09 15:08:12 +0000122
Chris Lattner574aa402009-02-17 01:09:29 +0000123 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
Mike Stump1eb44332009-09-09 15:08:12 +0000124
Chris Lattner5a0c3512009-02-17 00:57:29 +0000125 switch (Kind) {
126 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000127 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000128 break;
129
130 case Action::PPK_Show: // pack(show)
131 // Show the current alignment, making sure to show the right value
132 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000133 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000134 // FIXME: This should come from the target.
135 if (AlignmentVal == 0)
136 AlignmentVal = 8;
137 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
138 break;
139
140 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000141 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000142 // Set the new alignment if specified.
143 if (Alignment)
Mike Stump1eb44332009-09-09 15:08:12 +0000144 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000145 break;
146
147 case Action::PPK_Pop: // pack(pop [, id] [, n])
148 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
149 // "#pragma pack(pop, identifier, n) is undefined"
150 if (Alignment && Name)
Mike Stump1eb44332009-09-09 15:08:12 +0000151 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
152
Chris Lattner5a0c3512009-02-17 00:57:29 +0000153 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000154 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000155 // If a name was specified then failure indicates the name
156 // wasn't found. Otherwise failure indicates the stack was
157 // empty.
158 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
159 << (Name ? "no record matching name" : "stack empty");
160
161 // FIXME: Warn about popping named records as MSVC does.
162 } else {
163 // Pop succeeded, set the new alignment if specified.
164 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000165 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000166 }
167 break;
168
169 default:
170 assert(0 && "Invalid #pragma pack kind.");
171 }
172}
173
Ted Kremenek7a02a372009-08-03 23:24:57 +0000174void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
175 Scope *curScope,
Ted Kremenek4726d032009-03-23 22:28:25 +0000176 SourceLocation PragmaLoc,
177 SourceLocation LParenLoc,
178 SourceLocation RParenLoc) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000179
Ted Kremenek7a02a372009-08-03 23:24:57 +0000180 for (unsigned i = 0; i < NumIdentifiers; ++i) {
181 const Token &Tok = Identifiers[i];
Mike Stump1eb44332009-09-09 15:08:12 +0000182 IdentifierInfo *Name = Tok.getIdentifierInfo();
John McCalla24dc2e2009-11-17 02:14:36 +0000183 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
184 LookupParsedName(Lookup, curScope, NULL, true);
Ted Kremenek4726d032009-03-23 22:28:25 +0000185
John McCall1bcee0a2009-12-02 08:25:40 +0000186 if (Lookup.empty()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000187 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
188 << Name << SourceRange(Tok.getLocation());
189 continue;
Ted Kremenek4726d032009-03-23 22:28:25 +0000190 }
Mike Stump1eb44332009-09-09 15:08:12 +0000191
John McCall1bcee0a2009-12-02 08:25:40 +0000192 VarDecl *VD = Lookup.getAsSingle<VarDecl>();
193 if (!VD || !VD->hasLocalStorage()) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000194 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
195 << Name << SourceRange(Tok.getLocation());
196 continue;
197 }
Mike Stump1eb44332009-09-09 15:08:12 +0000198
John McCall1bcee0a2009-12-02 08:25:40 +0000199 VD->addAttr(::new (Context) UnusedAttr());
Ted Kremenek4726d032009-03-23 22:28:25 +0000200 }
201}