SemaAttr.cpp revision 210299
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 switch (Kind) { 139 // For all targets we support native and natural are the same. 140 // 141 // FIXME: This is not true on Darwin/PPC. 142 case POAK_Native: 143 case POAK_Power: 144 case POAK_Natural: 145 Context->push(0); 146 Context->setAlignment(0); 147 break; 148 149 // Note that '#pragma options align=packed' is not equivalent to attribute 150 // packed, it has a different precedence relative to attribute aligned. 151 case POAK_Packed: 152 Context->push(0); 153 Context->setAlignment(1); 154 break; 155 156 case POAK_Mac68k: 157 // Check if the target supports this. 158 if (!PP.getTargetInfo().hasAlignMac68kSupport()) { 159 Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); 160 return; 161 } 162 Context->push(0); 163 Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); 164 break; 165 166 default: 167 Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option) 168 << KindLoc; 169 break; 170 } 171} 172 173void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 174 ExprTy *alignment, SourceLocation PragmaLoc, 175 SourceLocation LParenLoc, SourceLocation RParenLoc) { 176 Expr *Alignment = static_cast<Expr *>(alignment); 177 178 // If specified then alignment must be a "small" power of two. 179 unsigned AlignmentVal = 0; 180 if (Alignment) { 181 llvm::APSInt Val; 182 183 // pack(0) is like pack(), which just works out since that is what 184 // we use 0 for in PackAttr. 185 if (Alignment->isTypeDependent() || 186 Alignment->isValueDependent() || 187 !Alignment->isIntegerConstantExpr(Val, Context) || 188 !(Val == 0 || Val.isPowerOf2()) || 189 Val.getZExtValue() > 16) { 190 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 191 Alignment->Destroy(Context); 192 return; // Ignore 193 } 194 195 AlignmentVal = (unsigned) Val.getZExtValue(); 196 } 197 198 if (PackContext == 0) 199 PackContext = new PragmaPackStack(); 200 201 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 202 203 switch (Kind) { 204 case Action::PPK_Default: // pack([n]) 205 Context->setAlignment(AlignmentVal); 206 break; 207 208 case Action::PPK_Show: // pack(show) 209 // Show the current alignment, making sure to show the right value 210 // for the default. 211 AlignmentVal = Context->getAlignment(); 212 // FIXME: This should come from the target. 213 if (AlignmentVal == 0) 214 AlignmentVal = 8; 215 if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) 216 Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 217 else 218 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 219 break; 220 221 case Action::PPK_Push: // pack(push [, id] [, [n]) 222 Context->push(Name); 223 // Set the new alignment if specified. 224 if (Alignment) 225 Context->setAlignment(AlignmentVal); 226 break; 227 228 case Action::PPK_Pop: // pack(pop [, id] [, n]) 229 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 230 // "#pragma pack(pop, identifier, n) is undefined" 231 if (Alignment && Name) 232 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 233 234 // Do the pop. 235 if (!Context->pop(Name)) { 236 // If a name was specified then failure indicates the name 237 // wasn't found. Otherwise failure indicates the stack was 238 // empty. 239 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 240 << (Name ? "no record matching name" : "stack empty"); 241 242 // FIXME: Warn about popping named records as MSVC does. 243 } else { 244 // Pop succeeded, set the new alignment if specified. 245 if (Alignment) 246 Context->setAlignment(AlignmentVal); 247 } 248 break; 249 250 default: 251 assert(0 && "Invalid #pragma pack kind."); 252 } 253} 254 255void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers, 256 Scope *curScope, 257 SourceLocation PragmaLoc, 258 SourceLocation LParenLoc, 259 SourceLocation RParenLoc) { 260 261 for (unsigned i = 0; i < NumIdentifiers; ++i) { 262 const Token &Tok = Identifiers[i]; 263 IdentifierInfo *Name = Tok.getIdentifierInfo(); 264 LookupResult Lookup(*this, Name, Tok.getLocation(), LookupOrdinaryName); 265 LookupParsedName(Lookup, curScope, NULL, true); 266 267 if (Lookup.empty()) { 268 Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 269 << Name << SourceRange(Tok.getLocation()); 270 continue; 271 } 272 273 VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 274 if (!VD || !VD->hasLocalStorage()) { 275 Diag(PragmaLoc, diag::warn_pragma_unused_expected_localvar) 276 << Name << SourceRange(Tok.getLocation()); 277 continue; 278 } 279 280 VD->addAttr(::new (Context) UnusedAttr()); 281 } 282} 283