 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
85.2% |
52 / 61 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
100.0% |
61 / 61 |
| |
|
Line Coverage: |
96.1% |
73 / 76 |
| |
 |
|
 |
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 : using namespace clang;
19 :
20 : //===----------------------------------------------------------------------===//
21 : // Pragma Packed
22 : //===----------------------------------------------------------------------===//
23 :
24 : namespace {
25 : /// PragmaPackStack - Simple class to wrap the stack used by #pragma
26 : /// pack.
27 10: 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;
36 :
37 : public:
38 10: PragmaPackStack() : Alignment(0) {}
39 :
40 31: void setAlignment(unsigned A) { Alignment = A; }
41 37: 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 19: void push(IdentifierInfo *Name) {
46 19: Stack.push_back(std::make_pair(Alignment, Name));
47 19: }
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 :
57 13: bool PragmaPackStack::pop(IdentifierInfo *Name) {
1: branch 1 taken
12: branch 2 taken
58 13: if (Stack.empty())
59 1: return false;
60 :
61 : // If name is empty just pop top.
11: branch 0 taken
1: branch 1 taken
62 12: if (!Name) {
63 11: Alignment = Stack.back().first;
64 11: Stack.pop_back();
65 11: return true;
66 : }
67 :
68 : // Otherwise, find the named record.
2: branch 1 taken
0: branch 2 not taken
69 3: for (unsigned i = Stack.size(); i != 0; ) {
70 2: --i;
1: branch 1 taken
1: branch 2 taken
71 2: if (Stack[i].second == Name) {
72 : // Found it, pop up to and including this record.
73 1: Alignment = Stack[i].first;
74 1: Stack.erase(Stack.begin() + i, Stack.end());
75 1: return true;
76 : }
77 : }
78 :
79 0: return false;
80 : }
81 :
82 :
83 : /// FreePackedContext - Deallocate and null out PackContext.
84 10: void Sema::FreePackedContext() {
10: branch 0 taken
0: branch 1 not taken
85 10: delete static_cast<PragmaPackStack*>(PackContext);
86 10: PackContext = 0;
87 10: }
88 :
89 : /// getPragmaPackAlignment() - Return the current alignment as specified by
90 : /// the current #pragma pack directive, or 0 if none is currently active.
91 4492: unsigned Sema::getPragmaPackAlignment() const {
27: branch 0 taken
4465: branch 1 taken
92 4492: if (PackContext)
93 27: return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
94 4465: return 0;
95 : }
96 :
97 : void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
98 : ExprTy *alignment, SourceLocation PragmaLoc,
99 59: SourceLocation LParenLoc, SourceLocation RParenLoc) {
100 59: Expr *Alignment = static_cast<Expr *>(alignment);
101 :
102 : // If specified then alignment must be a "small" power of two.
103 59: unsigned AlignmentVal = 0;
28: branch 0 taken
31: branch 1 taken
104 59: if (Alignment) {
105 28: llvm::APSInt Val;
106 :
107 : // pack(0) is like pack(), which just works out since that is what
108 : // we use 0 for in PackAttr.
28: branch 1 taken
0: branch 2 not taken
27: branch 4 taken
1: branch 5 taken
26: branch 7 taken
1: branch 8 taken
0: branch 10 not taken
27: branch 11 taken
1: branch 12 taken
27: branch 13 taken
109 28: if (!Alignment->isIntegerConstantExpr(Val, Context) ||
110 : !(Val == 0 || Val.isPowerOf2()) ||
111 : Val.getZExtValue() > 16) {
112 1: Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
113 1: Alignment->Destroy(Context);
114 1: return; // Ignore
115 : }
116 :
27: branch 2 taken
1: branch 3 taken
117 27: AlignmentVal = (unsigned) Val.getZExtValue();
118 : }
119 :
10: branch 0 taken
48: branch 1 taken
120 58: if (PackContext == 0)
121 10: PackContext = new PragmaPackStack();
122 :
123 58: PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
124 :
16: branch 0 taken
10: branch 1 taken
19: branch 2 taken
13: branch 3 taken
0: branch 4 not taken
125 58: switch (Kind) {
126 : case Action::PPK_Default: // pack([n])
127 16: Context->setAlignment(AlignmentVal);
128 16: 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.
133 10: AlignmentVal = Context->getAlignment();
134 : // FIXME: This should come from the target.
3: branch 0 taken
7: branch 1 taken
135 10: if (AlignmentVal == 0)
136 3: AlignmentVal = 8;
137 10: Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
138 10: break;
139 :
140 : case Action::PPK_Push: // pack(push [, id] [, [n])
141 19: Context->push(Name);
142 : // Set the new alignment if specified.
14: branch 0 taken
5: branch 1 taken
143 19: if (Alignment)
144 14: Context->setAlignment(AlignmentVal);
145 19: 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"
1: branch 0 taken
12: branch 1 taken
0: branch 2 not taken
1: branch 3 taken
150 13: if (Alignment && Name)
151 0: Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
152 :
153 : // Do the pop.
1: branch 1 taken
12: branch 2 taken
154 13: if (!Context->pop(Name)) {
155 : // 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)
0: branch 0 not taken
1: branch 1 taken
159 1: << (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.
1: branch 0 taken
11: branch 1 taken
164 12: if (Alignment)
165 1: Context->setAlignment(AlignmentVal);
166 : }
167 13: break;
168 :
169 : default:
170 0: assert(0 && "Invalid #pragma pack kind.");
171 : }
172 : }
173 :
174 : void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
175 : Scope *curScope,
176 : SourceLocation PragmaLoc,
177 : SourceLocation LParenLoc,
178 11: SourceLocation RParenLoc) {
179 :
10: branch 1 taken
4: branch 2 taken
14: branch 3 taken
11: branch 4 taken
180 39: for (unsigned i = 0; i < NumIdentifiers; ++i) {
181 14: const Token &Tok = Identifiers[i];
182 14: IdentifierInfo *Name = Tok.getIdentifierInfo();
183 14: LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName);
184 14: LookupParsedName(Lookup, curScope, NULL, true);
185 :
3: branch 1 taken
11: branch 2 taken
186 14: if (Lookup.empty()) {
187 : Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
188 3: << Name << SourceRange(Tok.getLocation());
189 4: continue;
190 : }
191 :
192 11: VarDecl *VD = Lookup.getAsSingle<VarDecl>();
11: branch 0 taken
0: branch 1 not taken
1: branch 3 taken
10: branch 4 taken
1: branch 5 taken
10: branch 6 taken
193 11: if (!VD || !VD->hasLocalStorage()) {
194 : Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar)
195 1: << Name << SourceRange(Tok.getLocation());
196 : continue;
197 : }
198 :
10: branch 1 taken
0: branch 2 not taken
199 10: VD->addAttr(::new (Context) UnusedAttr());
200 : }
201 11: }
Generated: 2010-02-10 01:31 by zcov