SemaAttr.cpp revision 574aa40703ffb2fddad5b076cec1c2fc27f0b2d3
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 if (!Alignment->isIntegerConstantExpr(Val, Context) || 106 !Val.isPowerOf2() || 107 Val.getZExtValue() > 16) { 108 Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 109 Alignment->Destroy(Context); 110 return; // Ignore 111 } 112 113 AlignmentVal = (unsigned) Val.getZExtValue(); 114 } 115 116 if (PackContext == 0) 117 PackContext = new PragmaPackStack(); 118 119 120 PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 121 122 switch (Kind) { 123 case Action::PPK_Default: // pack([n]) 124 Context->setAlignment(AlignmentVal); 125 break; 126 127 case Action::PPK_Show: // pack(show) 128 // Show the current alignment, making sure to show the right value 129 // for the default. 130 AlignmentVal = Context->getAlignment(); 131 // FIXME: This should come from the target. 132 if (AlignmentVal == 0) 133 AlignmentVal = 8; 134 Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 135 break; 136 137 case Action::PPK_Push: // pack(push [, id] [, [n]) 138 Context->push(Name); 139 // Set the new alignment if specified. 140 if (Alignment) 141 Context->setAlignment(AlignmentVal); 142 break; 143 144 case Action::PPK_Pop: // pack(pop [, id] [, n]) 145 // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 146 // "#pragma pack(pop, identifier, n) is undefined" 147 if (Alignment && Name) 148 Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 149 150 // Do the pop. 151 if (!Context->pop(Name)) { 152 // If a name was specified then failure indicates the name 153 // wasn't found. Otherwise failure indicates the stack was 154 // empty. 155 Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 156 << (Name ? "no record matching name" : "stack empty"); 157 158 // FIXME: Warn about popping named records as MSVC does. 159 } else { 160 // Pop succeeded, set the new alignment if specified. 161 if (Alignment) 162 Context->setAlignment(AlignmentVal); 163 } 164 break; 165 166 default: 167 assert(0 && "Invalid #pragma pack kind."); 168 } 169} 170 171