blob: 1bf8444c42b74d2da36fed67d8ebf266413ead9b [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"
16#include "clang/AST/Expr.h"
17using namespace clang;
18
Chris Lattner574aa402009-02-17 01:09:29 +000019//===----------------------------------------------------------------------===//
20// Pragma Packed
21//===----------------------------------------------------------------------===//
22
23namespace {
24 /// PragmaPackStack - Simple class to wrap the stack used by #pragma
25 /// pack.
26 class PragmaPackStack {
27 typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty;
28
29 /// Alignment - The current user specified alignment.
30 unsigned Alignment;
31
32 /// Stack - Entries in the #pragma pack stack, consisting of saved
33 /// alignments and optional names.
34 stack_ty Stack;
35
36 public:
37 PragmaPackStack() : Alignment(0) {}
38
39 void setAlignment(unsigned A) { Alignment = A; }
40 unsigned getAlignment() { return Alignment; }
41
42 /// push - Push the current alignment onto the stack, optionally
43 /// using the given \arg Name for the record, if non-zero.
44 void push(IdentifierInfo *Name) {
45 Stack.push_back(std::make_pair(Alignment, Name));
46 }
47
48 /// pop - Pop a record from the stack and restore the current
49 /// alignment to the previous value. If \arg Name is non-zero then
50 /// the first such named record is popped, otherwise the top record
51 /// is popped. Returns true if the pop succeeded.
52 bool pop(IdentifierInfo *Name);
53 };
54} // end anonymous namespace.
55
56bool PragmaPackStack::pop(IdentifierInfo *Name) {
57 if (Stack.empty())
58 return false;
59
60 // If name is empty just pop top.
61 if (!Name) {
62 Alignment = Stack.back().first;
63 Stack.pop_back();
64 return true;
65 }
66
67 // Otherwise, find the named record.
68 for (unsigned i = Stack.size(); i != 0; ) {
69 --i;
70 if (Stack[i].second == Name) {
71 // Found it, pop up to and including this record.
72 Alignment = Stack[i].first;
73 Stack.erase(Stack.begin() + i, Stack.end());
74 return true;
75 }
76 }
77
78 return false;
79}
80
81
82/// FreePackedContext - Deallocate and null out PackContext.
83void Sema::FreePackedContext() {
84 delete static_cast<PragmaPackStack*>(PackContext);
85 PackContext = 0;
86}
87
88/// getPragmaPackAlignment() - Return the current alignment as specified by
89/// the current #pragma pack directive, or 0 if none is currently active.
90unsigned Sema::getPragmaPackAlignment() const {
91 if (PackContext)
92 return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
93 return 0;
94}
95
Chris Lattner5a0c3512009-02-17 00:57:29 +000096void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
97 ExprTy *alignment, SourceLocation PragmaLoc,
98 SourceLocation LParenLoc, SourceLocation RParenLoc) {
99 Expr *Alignment = static_cast<Expr *>(alignment);
100
101 // If specified then alignment must be a "small" power of two.
102 unsigned AlignmentVal = 0;
103 if (Alignment) {
104 llvm::APSInt Val;
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000105
106 // pack(0) is like pack(), which just works out since that is what
107 // we use 0 for in PackAttr.
Chris Lattner5a0c3512009-02-17 00:57:29 +0000108 if (!Alignment->isIntegerConstantExpr(Val, Context) ||
Daniel Dunbar79cd1162009-03-06 20:45:54 +0000109 !(Val == 0 || Val.isPowerOf2()) ||
Chris Lattner5a0c3512009-02-17 00:57:29 +0000110 Val.getZExtValue() > 16) {
111 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
112 Alignment->Destroy(Context);
113 return; // Ignore
114 }
115
116 AlignmentVal = (unsigned) Val.getZExtValue();
117 }
Chris Lattner574aa402009-02-17 01:09:29 +0000118
119 if (PackContext == 0)
120 PackContext = new PragmaPackStack();
Chris Lattner574aa402009-02-17 01:09:29 +0000121
122 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
123
Chris Lattner5a0c3512009-02-17 00:57:29 +0000124 switch (Kind) {
125 case Action::PPK_Default: // pack([n])
Chris Lattner574aa402009-02-17 01:09:29 +0000126 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000127 break;
128
129 case Action::PPK_Show: // pack(show)
130 // Show the current alignment, making sure to show the right value
131 // for the default.
Chris Lattner574aa402009-02-17 01:09:29 +0000132 AlignmentVal = Context->getAlignment();
Chris Lattner5a0c3512009-02-17 00:57:29 +0000133 // FIXME: This should come from the target.
134 if (AlignmentVal == 0)
135 AlignmentVal = 8;
136 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
137 break;
138
139 case Action::PPK_Push: // pack(push [, id] [, [n])
Chris Lattner574aa402009-02-17 01:09:29 +0000140 Context->push(Name);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000141 // Set the new alignment if specified.
142 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000143 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000144 break;
145
146 case Action::PPK_Pop: // pack(pop [, id] [, n])
147 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
148 // "#pragma pack(pop, identifier, n) is undefined"
149 if (Alignment && Name)
150 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
151
152 // Do the pop.
Chris Lattner574aa402009-02-17 01:09:29 +0000153 if (!Context->pop(Name)) {
Chris Lattner5a0c3512009-02-17 00:57:29 +0000154 // If a name was specified then failure indicates the name
155 // wasn't found. Otherwise failure indicates the stack was
156 // empty.
157 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed)
158 << (Name ? "no record matching name" : "stack empty");
159
160 // FIXME: Warn about popping named records as MSVC does.
161 } else {
162 // Pop succeeded, set the new alignment if specified.
163 if (Alignment)
Chris Lattner574aa402009-02-17 01:09:29 +0000164 Context->setAlignment(AlignmentVal);
Chris Lattner5a0c3512009-02-17 00:57:29 +0000165 }
166 break;
167
168 default:
169 assert(0 && "Invalid #pragma pack kind.");
170 }
171}
172
Ted Kremenek4726d032009-03-23 22:28:25 +0000173void Sema::ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs,
174 SourceLocation PragmaLoc,
175 SourceLocation LParenLoc,
176 SourceLocation RParenLoc) {
177
178 // Verify that all of the expressions are valid before
179 // modifying the attributes of any referenced decl.
180 Expr *ErrorExpr = 0;
181
182 for (unsigned i = 0; i < NumExprs; ++i) {
183 Expr *Ex = (Expr*) Exprs[i];
184 if (!isa<DeclRefExpr>(Ex)) {
185 ErrorExpr = Ex;
186 break;
187 }
188
189 Decl *d = cast<DeclRefExpr>(Ex)->getDecl();;
190
191 if (!isa<VarDecl>(d) || !cast<VarDecl>(d)->hasLocalStorage()) {
192 ErrorExpr = Ex;
193 break;
194 }
195 }
196
197 // Delete the expressions if we encountered any error.
198 if (ErrorExpr) {
199 Diag(ErrorExpr->getLocStart(), diag::warn_pragma_unused_expected_localvar);
200 for (unsigned i = 0; i < NumExprs; ++i)
201 ((Expr*) Exprs[i])->Destroy(Context);
202 return;
203 }
204
205 // Otherwise, add the 'unused' attribute to each referenced declaration.
206 for (unsigned i = 0; i < NumExprs; ++i) {
207 DeclRefExpr *DR = (DeclRefExpr*) Exprs[i];
208 DR->getDecl()->addAttr(::new (Context) UnusedAttr());
Ted Kremenek45a3c052009-03-23 22:50:47 +0000209 DR->Destroy(Context);
Ted Kremenek4726d032009-03-23 22:28:25 +0000210 }
211}