SemaAttr.cpp revision 79cd11620c6f05dbf7bb706744eba354574e8b54
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 "clang/AST/Expr.h" 17using namespace clang; 18 19//===----------------------------------------------------------------------===// 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 96void 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; 105 106 // pack(0) is like pack(), which just works out since that is what 107 // we use 0 for in PackAttr. 108 if (!Alignment->isIntegerConstantExpr(Val, Context) || 109 !(Val == 0 || Val.isPowerOf2()) || 110 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 } 118 119 if (PackContext == 0) 120 PackContext = new PragmaPackStack(); 121 122 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 123 124 switch (Kind) { 125 case Action::PPK_Default: // pack([n]) 126 Context->setAlignment(AlignmentVal); 127 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. 132 AlignmentVal = Context->getAlignment(); 133 // 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]) 140 Context->push(Name); 141 // Set the new alignment if specified. 142 if (Alignment) 143 Context->setAlignment(AlignmentVal); 144 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. 153 if (!Context->pop(Name)) { 154 // 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) 164 Context->setAlignment(AlignmentVal); 165 } 166 break; 167 168 default: 169 assert(0 && "Invalid #pragma pack kind."); 170 } 171} 172 173