SemaAttr.cpp revision c6082fe347a414a2e19f2ad8fe41720f10733296
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#include "clang/Basic/TargetInfo.h" 19#include "clang/Lex/Preprocessor.h" 20using namespace clang; 21 22//===----------------------------------------------------------------------===// 23// Pragma 'pack' and 'options align' 24//===----------------------------------------------------------------------===// 25 26namespace { 27 struct PackStackEntry { 28 // We just use a sentinel to represent when the stack is set to mac68k 29 // alignment. 30 static const unsigned kMac68kAlignmentSentinel = ~0U; 31 32 unsigned Alignment; 33 IdentifierInfo *Name; 34 }; 35 36 /// PragmaPackStack - Simple class to wrap the stack used by #pragma 37 /// pack. 38 class PragmaPackStack { 39 typedef std::vector<PackStackEntry> stack_ty; 40 41 /// Alignment - The current user specified alignment. 42 unsigned Alignment; 43 44 /// Stack - Entries in the #pragma pack stack, consisting of saved 45 /// alignments and optional names. 46 stack_ty Stack; 47 48 public: 49 PragmaPackStack() : Alignment(0) {} 50 51 void setAlignment(unsigned A) { Alignment = A; } 52 unsigned getAlignment() { return Alignment; } 53 54 /// push - Push the current alignment onto the stack, optionally 55 /// using the given \arg Name for the record, if non-zero. 56 void push(IdentifierInfo *Name) { 57 PackStackEntry PSE = { Alignment, Name }; 58 Stack.push_back(PSE); 59 } 60 61 /// pop - Pop a record from the stack and restore the current 62 /// alignment to the previous value. If \arg Name is non-zero then 63 /// the first such named record is popped, otherwise the top record 64 /// is popped. Returns true if the pop succeeded. 65 bool pop(IdentifierInfo *Name); 66 }; 67} // end anonymous namespace. 68 69bool PragmaPackStack::pop(IdentifierInfo *Name) { 70 if (Stack.empty()) 71 return false; 72 73 // If name is empty just pop top. 74 if (!Name) { 75 Alignment = Stack.back().Alignment; 76 Stack.pop_back(); 77 return true; 78 } 79 80 // Otherwise, find the named record. 81 for (unsigned i = Stack.size(); i != 0; ) { 82 --i; 83 if (Stack[i].Name == Name) { 84 // Found it, pop up to and including this record. 85 Alignment = Stack[i].Alignment; 86 Stack.erase(Stack.begin() + i, Stack.end()); 87 return true; 88 } 89 } 90 91 return false; 92} 93 94 95/// FreePackedContext - Deallocate and null out PackContext. 96void Sema::FreePackedContext() { 97 delete static_cast<PragmaPackStack*>(PackContext); 98 PackContext = 0; 99} 100 101void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { 102 // If there is no pack context, we don't need any attributes. 103 if (!PackContext) 104 return; 105 106 PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext); 107 108 // Otherwise, check to see if we need a max field alignment attribute. 109 if (unsigned Alignment = Stack->getAlignment()) { 110 if (Alignment == PackStackEntry::kMac68kAlignmentSentinel) 111 RD->addAttr(::new (Context) AlignMac68kAttr()); 112 else 113 RD->addAttr(::new (Context) MaxFieldAlignmentAttr(Alignment * 8)); 114 } 115} 116 117void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, 118 SourceLocation PragmaLoc, 119 SourceLocation KindLoc) { 120 if (PackContext == 0) 121 PackContext = new PragmaPackStack(); 122 123 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 124 125 // Reset just pops the top of the stack. 126 if (Kind == Action::POAK_Reset) { 127 // Do the pop. 128 if (!Context->pop(0)) { 129 // If a name was specified then failure indicates the name 130 // wasn't found. Otherwise failure indicates the stack was 131 // empty. 132 Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) 133 << "stack empty"; 134 } 135 return; 136 } 137 138 // We don't support #pragma options align=power. 139 switch (Kind) { 140 case POAK_Natural: 141 Context->push(0); 142 Context->setAlignment(0); 143 break; 144 145 case POAK_Mac68k: 146 // Check if the target supports this. 147 if (!PP.getTargetInfo().hasAlignMac68kSupport()) { 148 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); 149 return; 150 } 151 Context->push(0); 152 Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); 153 break; 154 155 default: 156 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option) 157 << KindLoc; 158 break; 159 } 160} 161 162void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 163 ExprTy *alignment, SourceLocation PragmaLoc, 164 SourceLocation LParenLoc, SourceLocation RParenLoc) { 165 Expr *Alignment = static_cast<Expr *>(alignment); 166 167 // If specified then alignment must be a "small" power of two. 168 unsigned AlignmentVal = 0; 169 if (Alignment) { 170 llvm::APSInt Val; 171 172 // pack(0) is like pack(), which just works out since that is what 173 // we use 0 for in PackAttr. 174 if (Alignment->isTypeDependent() || 175 Alignment->isValueDependent() || 176 !Alignment->isIntegerConstantExpr(Val, Context) || 177 !(Val == 0 || Val.isPowerOf2()) || 178 Val.getZExtValue() > 16) { 179 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 180 Alignment->Destroy(Context); 181 return; // Ignore 182 } 183 184 AlignmentVal = (unsigned) Val.getZExtValue(); 185 } 186 187 if (PackContext == 0) 188 PackContext = new PragmaPackStack(); 189 190 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 191 192 switch (Kind) { 193 case Action::PPK_Default: // pack([n]) 194 Context->setAlignment(AlignmentVal); 195 break; 196 197 case Action::PPK_Show: // pack(show) 198 // Show the current alignment, making sure to show the right value 199 // for the default. 200 AlignmentVal = Context->getAlignment(); 201 // FIXME: This should come from the target. 202 if (AlignmentVal == 0) 203 AlignmentVal = 8; 204 if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) 205 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 206 else 207 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 208 break; 209 210 case Action::PPK_Push: // pack(push [, id] [, [n]) 211 Context->push(Name); 212 // Set the new alignment if specified. 213 if (Alignment) 214 Context->setAlignment(AlignmentVal); 215 break; 216 217 case Action::PPK_Pop: // pack(pop [, id] [, n]) 218 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 219 // "#pragma pack(pop, identifier, n) is undefined" 220 if (Alignment && Name) 221 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 222 223 // Do the pop. 224 if (!Context->pop(Name)) { 225 // If a name was specified then failure indicates the name 226 // wasn't found. Otherwise failure indicates the stack was 227 // empty. 228 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 229 << (Name ? "no record matching name" : "stack empty"); 230 231 // FIXME: Warn about popping named records as MSVC does. 232 } else { 233 // Pop succeeded, set the new alignment if specified. 234 if (Alignment) 235 Context->setAlignment(AlignmentVal); 236 } 237 break; 238 239 default: 240 assert(0 && "Invalid #pragma pack kind."); 241 } 242} 243 244void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, 245 Scope *curScope, 246 SourceLocation PragmaLoc, 247 SourceLocation LParenLoc, 248 SourceLocation RParenLoc) { 249 250 for (unsigned i = 0; i < NumIdentifiers; ++i) { 251 const Token &Tok = Identifiers[i]; 252 IdentifierInfo *Name = Tok.getIdentifierInfo(); 253 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); 254 LookupParsedName(Lookup, curScope, NULL, true); 255 256 if (Lookup.empty()) { 257 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 258 << Name << SourceRange(Tok.getLocation()); 259 continue; 260 } 261 262 VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 263 if (!VD || !VD->hasLocalStorage()) { 264 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) 265 << Name << SourceRange(Tok.getLocation()); 266 continue; 267 } 268 269 VD->addAttr(::new (Context) UnusedAttr()); 270 } 271} 272