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