1*f4a2713aSLionel Sambuc //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// 2*f4a2713aSLionel Sambuc // 3*f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4*f4a2713aSLionel Sambuc // 5*f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6*f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7*f4a2713aSLionel Sambuc // 8*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9*f4a2713aSLionel Sambuc // 10*f4a2713aSLionel Sambuc // This file implements semantic analysis for non-trivial attributes and 11*f4a2713aSLionel Sambuc // pragmas. 12*f4a2713aSLionel Sambuc // 13*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 14*f4a2713aSLionel Sambuc 15*f4a2713aSLionel Sambuc #include "clang/Sema/SemaInternal.h" 16*f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h" 17*f4a2713aSLionel Sambuc #include "clang/AST/Attr.h" 18*f4a2713aSLionel Sambuc #include "clang/AST/Expr.h" 19*f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h" 20*f4a2713aSLionel Sambuc #include "clang/Lex/Preprocessor.h" 21*f4a2713aSLionel Sambuc #include "clang/Sema/Lookup.h" 22*f4a2713aSLionel Sambuc using namespace clang; 23*f4a2713aSLionel Sambuc 24*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 25*f4a2713aSLionel Sambuc // Pragma 'pack' and 'options align' 26*f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 27*f4a2713aSLionel Sambuc 28*f4a2713aSLionel Sambuc namespace { 29*f4a2713aSLionel Sambuc struct PackStackEntry { 30*f4a2713aSLionel Sambuc // We just use a sentinel to represent when the stack is set to mac68k 31*f4a2713aSLionel Sambuc // alignment. 32*f4a2713aSLionel Sambuc static const unsigned kMac68kAlignmentSentinel = ~0U; 33*f4a2713aSLionel Sambuc 34*f4a2713aSLionel Sambuc unsigned Alignment; 35*f4a2713aSLionel Sambuc IdentifierInfo *Name; 36*f4a2713aSLionel Sambuc }; 37*f4a2713aSLionel Sambuc 38*f4a2713aSLionel Sambuc /// PragmaPackStack - Simple class to wrap the stack used by #pragma 39*f4a2713aSLionel Sambuc /// pack. 40*f4a2713aSLionel Sambuc class PragmaPackStack { 41*f4a2713aSLionel Sambuc typedef std::vector<PackStackEntry> stack_ty; 42*f4a2713aSLionel Sambuc 43*f4a2713aSLionel Sambuc /// Alignment - The current user specified alignment. 44*f4a2713aSLionel Sambuc unsigned Alignment; 45*f4a2713aSLionel Sambuc 46*f4a2713aSLionel Sambuc /// Stack - Entries in the #pragma pack stack, consisting of saved 47*f4a2713aSLionel Sambuc /// alignments and optional names. 48*f4a2713aSLionel Sambuc stack_ty Stack; 49*f4a2713aSLionel Sambuc 50*f4a2713aSLionel Sambuc public: 51*f4a2713aSLionel Sambuc PragmaPackStack() : Alignment(0) {} 52*f4a2713aSLionel Sambuc 53*f4a2713aSLionel Sambuc void setAlignment(unsigned A) { Alignment = A; } 54*f4a2713aSLionel Sambuc unsigned getAlignment() { return Alignment; } 55*f4a2713aSLionel Sambuc 56*f4a2713aSLionel Sambuc /// push - Push the current alignment onto the stack, optionally 57*f4a2713aSLionel Sambuc /// using the given \arg Name for the record, if non-zero. 58*f4a2713aSLionel Sambuc void push(IdentifierInfo *Name) { 59*f4a2713aSLionel Sambuc PackStackEntry PSE = { Alignment, Name }; 60*f4a2713aSLionel Sambuc Stack.push_back(PSE); 61*f4a2713aSLionel Sambuc } 62*f4a2713aSLionel Sambuc 63*f4a2713aSLionel Sambuc /// pop - Pop a record from the stack and restore the current 64*f4a2713aSLionel Sambuc /// alignment to the previous value. If \arg Name is non-zero then 65*f4a2713aSLionel Sambuc /// the first such named record is popped, otherwise the top record 66*f4a2713aSLionel Sambuc /// is popped. Returns true if the pop succeeded. 67*f4a2713aSLionel Sambuc bool pop(IdentifierInfo *Name, bool IsReset); 68*f4a2713aSLionel Sambuc }; 69*f4a2713aSLionel Sambuc } // end anonymous namespace. 70*f4a2713aSLionel Sambuc 71*f4a2713aSLionel Sambuc bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) { 72*f4a2713aSLionel Sambuc // If name is empty just pop top. 73*f4a2713aSLionel Sambuc if (!Name) { 74*f4a2713aSLionel Sambuc // An empty stack is a special case... 75*f4a2713aSLionel Sambuc if (Stack.empty()) { 76*f4a2713aSLionel Sambuc // If this isn't a reset, it is always an error. 77*f4a2713aSLionel Sambuc if (!IsReset) 78*f4a2713aSLionel Sambuc return false; 79*f4a2713aSLionel Sambuc 80*f4a2713aSLionel Sambuc // Otherwise, it is an error only if some alignment has been set. 81*f4a2713aSLionel Sambuc if (!Alignment) 82*f4a2713aSLionel Sambuc return false; 83*f4a2713aSLionel Sambuc 84*f4a2713aSLionel Sambuc // Otherwise, reset to the default alignment. 85*f4a2713aSLionel Sambuc Alignment = 0; 86*f4a2713aSLionel Sambuc } else { 87*f4a2713aSLionel Sambuc Alignment = Stack.back().Alignment; 88*f4a2713aSLionel Sambuc Stack.pop_back(); 89*f4a2713aSLionel Sambuc } 90*f4a2713aSLionel Sambuc 91*f4a2713aSLionel Sambuc return true; 92*f4a2713aSLionel Sambuc } 93*f4a2713aSLionel Sambuc 94*f4a2713aSLionel Sambuc // Otherwise, find the named record. 95*f4a2713aSLionel Sambuc for (unsigned i = Stack.size(); i != 0; ) { 96*f4a2713aSLionel Sambuc --i; 97*f4a2713aSLionel Sambuc if (Stack[i].Name == Name) { 98*f4a2713aSLionel Sambuc // Found it, pop up to and including this record. 99*f4a2713aSLionel Sambuc Alignment = Stack[i].Alignment; 100*f4a2713aSLionel Sambuc Stack.erase(Stack.begin() + i, Stack.end()); 101*f4a2713aSLionel Sambuc return true; 102*f4a2713aSLionel Sambuc } 103*f4a2713aSLionel Sambuc } 104*f4a2713aSLionel Sambuc 105*f4a2713aSLionel Sambuc return false; 106*f4a2713aSLionel Sambuc } 107*f4a2713aSLionel Sambuc 108*f4a2713aSLionel Sambuc 109*f4a2713aSLionel Sambuc /// FreePackedContext - Deallocate and null out PackContext. 110*f4a2713aSLionel Sambuc void Sema::FreePackedContext() { 111*f4a2713aSLionel Sambuc delete static_cast<PragmaPackStack*>(PackContext); 112*f4a2713aSLionel Sambuc PackContext = 0; 113*f4a2713aSLionel Sambuc } 114*f4a2713aSLionel Sambuc 115*f4a2713aSLionel Sambuc void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { 116*f4a2713aSLionel Sambuc // If there is no pack context, we don't need any attributes. 117*f4a2713aSLionel Sambuc if (!PackContext) 118*f4a2713aSLionel Sambuc return; 119*f4a2713aSLionel Sambuc 120*f4a2713aSLionel Sambuc PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext); 121*f4a2713aSLionel Sambuc 122*f4a2713aSLionel Sambuc // Otherwise, check to see if we need a max field alignment attribute. 123*f4a2713aSLionel Sambuc if (unsigned Alignment = Stack->getAlignment()) { 124*f4a2713aSLionel Sambuc if (Alignment == PackStackEntry::kMac68kAlignmentSentinel) 125*f4a2713aSLionel Sambuc RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context)); 126*f4a2713aSLionel Sambuc else 127*f4a2713aSLionel Sambuc RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(), 128*f4a2713aSLionel Sambuc Context, 129*f4a2713aSLionel Sambuc Alignment * 8)); 130*f4a2713aSLionel Sambuc } 131*f4a2713aSLionel Sambuc } 132*f4a2713aSLionel Sambuc 133*f4a2713aSLionel Sambuc void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { 134*f4a2713aSLionel Sambuc if (!MSStructPragmaOn) 135*f4a2713aSLionel Sambuc return; 136*f4a2713aSLionel Sambuc RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context)); 137*f4a2713aSLionel Sambuc } 138*f4a2713aSLionel Sambuc 139*f4a2713aSLionel Sambuc void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, 140*f4a2713aSLionel Sambuc SourceLocation PragmaLoc) { 141*f4a2713aSLionel Sambuc if (PackContext == 0) 142*f4a2713aSLionel Sambuc PackContext = new PragmaPackStack(); 143*f4a2713aSLionel Sambuc 144*f4a2713aSLionel Sambuc PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 145*f4a2713aSLionel Sambuc 146*f4a2713aSLionel Sambuc switch (Kind) { 147*f4a2713aSLionel Sambuc // For all targets we support native and natural are the same. 148*f4a2713aSLionel Sambuc // 149*f4a2713aSLionel Sambuc // FIXME: This is not true on Darwin/PPC. 150*f4a2713aSLionel Sambuc case POAK_Native: 151*f4a2713aSLionel Sambuc case POAK_Power: 152*f4a2713aSLionel Sambuc case POAK_Natural: 153*f4a2713aSLionel Sambuc Context->push(0); 154*f4a2713aSLionel Sambuc Context->setAlignment(0); 155*f4a2713aSLionel Sambuc break; 156*f4a2713aSLionel Sambuc 157*f4a2713aSLionel Sambuc // Note that '#pragma options align=packed' is not equivalent to attribute 158*f4a2713aSLionel Sambuc // packed, it has a different precedence relative to attribute aligned. 159*f4a2713aSLionel Sambuc case POAK_Packed: 160*f4a2713aSLionel Sambuc Context->push(0); 161*f4a2713aSLionel Sambuc Context->setAlignment(1); 162*f4a2713aSLionel Sambuc break; 163*f4a2713aSLionel Sambuc 164*f4a2713aSLionel Sambuc case POAK_Mac68k: 165*f4a2713aSLionel Sambuc // Check if the target supports this. 166*f4a2713aSLionel Sambuc if (!PP.getTargetInfo().hasAlignMac68kSupport()) { 167*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); 168*f4a2713aSLionel Sambuc return; 169*f4a2713aSLionel Sambuc } 170*f4a2713aSLionel Sambuc Context->push(0); 171*f4a2713aSLionel Sambuc Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); 172*f4a2713aSLionel Sambuc break; 173*f4a2713aSLionel Sambuc 174*f4a2713aSLionel Sambuc case POAK_Reset: 175*f4a2713aSLionel Sambuc // Reset just pops the top of the stack, or resets the current alignment to 176*f4a2713aSLionel Sambuc // default. 177*f4a2713aSLionel Sambuc if (!Context->pop(0, /*IsReset=*/true)) { 178*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) 179*f4a2713aSLionel Sambuc << "stack empty"; 180*f4a2713aSLionel Sambuc } 181*f4a2713aSLionel Sambuc break; 182*f4a2713aSLionel Sambuc } 183*f4a2713aSLionel Sambuc } 184*f4a2713aSLionel Sambuc 185*f4a2713aSLionel Sambuc void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 186*f4a2713aSLionel Sambuc Expr *alignment, SourceLocation PragmaLoc, 187*f4a2713aSLionel Sambuc SourceLocation LParenLoc, SourceLocation RParenLoc) { 188*f4a2713aSLionel Sambuc Expr *Alignment = static_cast<Expr *>(alignment); 189*f4a2713aSLionel Sambuc 190*f4a2713aSLionel Sambuc // If specified then alignment must be a "small" power of two. 191*f4a2713aSLionel Sambuc unsigned AlignmentVal = 0; 192*f4a2713aSLionel Sambuc if (Alignment) { 193*f4a2713aSLionel Sambuc llvm::APSInt Val; 194*f4a2713aSLionel Sambuc 195*f4a2713aSLionel Sambuc // pack(0) is like pack(), which just works out since that is what 196*f4a2713aSLionel Sambuc // we use 0 for in PackAttr. 197*f4a2713aSLionel Sambuc if (Alignment->isTypeDependent() || 198*f4a2713aSLionel Sambuc Alignment->isValueDependent() || 199*f4a2713aSLionel Sambuc !Alignment->isIntegerConstantExpr(Val, Context) || 200*f4a2713aSLionel Sambuc !(Val == 0 || Val.isPowerOf2()) || 201*f4a2713aSLionel Sambuc Val.getZExtValue() > 16) { 202*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); 203*f4a2713aSLionel Sambuc return; // Ignore 204*f4a2713aSLionel Sambuc } 205*f4a2713aSLionel Sambuc 206*f4a2713aSLionel Sambuc AlignmentVal = (unsigned) Val.getZExtValue(); 207*f4a2713aSLionel Sambuc } 208*f4a2713aSLionel Sambuc 209*f4a2713aSLionel Sambuc if (PackContext == 0) 210*f4a2713aSLionel Sambuc PackContext = new PragmaPackStack(); 211*f4a2713aSLionel Sambuc 212*f4a2713aSLionel Sambuc PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); 213*f4a2713aSLionel Sambuc 214*f4a2713aSLionel Sambuc switch (Kind) { 215*f4a2713aSLionel Sambuc case Sema::PPK_Default: // pack([n]) 216*f4a2713aSLionel Sambuc Context->setAlignment(AlignmentVal); 217*f4a2713aSLionel Sambuc break; 218*f4a2713aSLionel Sambuc 219*f4a2713aSLionel Sambuc case Sema::PPK_Show: // pack(show) 220*f4a2713aSLionel Sambuc // Show the current alignment, making sure to show the right value 221*f4a2713aSLionel Sambuc // for the default. 222*f4a2713aSLionel Sambuc AlignmentVal = Context->getAlignment(); 223*f4a2713aSLionel Sambuc // FIXME: This should come from the target. 224*f4a2713aSLionel Sambuc if (AlignmentVal == 0) 225*f4a2713aSLionel Sambuc AlignmentVal = 8; 226*f4a2713aSLionel Sambuc if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) 227*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; 228*f4a2713aSLionel Sambuc else 229*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; 230*f4a2713aSLionel Sambuc break; 231*f4a2713aSLionel Sambuc 232*f4a2713aSLionel Sambuc case Sema::PPK_Push: // pack(push [, id] [, [n]) 233*f4a2713aSLionel Sambuc Context->push(Name); 234*f4a2713aSLionel Sambuc // Set the new alignment if specified. 235*f4a2713aSLionel Sambuc if (Alignment) 236*f4a2713aSLionel Sambuc Context->setAlignment(AlignmentVal); 237*f4a2713aSLionel Sambuc break; 238*f4a2713aSLionel Sambuc 239*f4a2713aSLionel Sambuc case Sema::PPK_Pop: // pack(pop [, id] [, n]) 240*f4a2713aSLionel Sambuc // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: 241*f4a2713aSLionel Sambuc // "#pragma pack(pop, identifier, n) is undefined" 242*f4a2713aSLionel Sambuc if (Alignment && Name) 243*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); 244*f4a2713aSLionel Sambuc 245*f4a2713aSLionel Sambuc // Do the pop. 246*f4a2713aSLionel Sambuc if (!Context->pop(Name, /*IsReset=*/false)) { 247*f4a2713aSLionel Sambuc // If a name was specified then failure indicates the name 248*f4a2713aSLionel Sambuc // wasn't found. Otherwise failure indicates the stack was 249*f4a2713aSLionel Sambuc // empty. 250*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) 251*f4a2713aSLionel Sambuc << (Name ? "no record matching name" : "stack empty"); 252*f4a2713aSLionel Sambuc 253*f4a2713aSLionel Sambuc // FIXME: Warn about popping named records as MSVC does. 254*f4a2713aSLionel Sambuc } else { 255*f4a2713aSLionel Sambuc // Pop succeeded, set the new alignment if specified. 256*f4a2713aSLionel Sambuc if (Alignment) 257*f4a2713aSLionel Sambuc Context->setAlignment(AlignmentVal); 258*f4a2713aSLionel Sambuc } 259*f4a2713aSLionel Sambuc break; 260*f4a2713aSLionel Sambuc } 261*f4a2713aSLionel Sambuc } 262*f4a2713aSLionel Sambuc 263*f4a2713aSLionel Sambuc void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { 264*f4a2713aSLionel Sambuc MSStructPragmaOn = (Kind == PMSST_ON); 265*f4a2713aSLionel Sambuc } 266*f4a2713aSLionel Sambuc 267*f4a2713aSLionel Sambuc void Sema::ActOnPragmaMSComment(PragmaMSCommentKind Kind, StringRef Arg) { 268*f4a2713aSLionel Sambuc // FIXME: Serialize this. 269*f4a2713aSLionel Sambuc switch (Kind) { 270*f4a2713aSLionel Sambuc case PCK_Unknown: 271*f4a2713aSLionel Sambuc llvm_unreachable("unexpected pragma comment kind"); 272*f4a2713aSLionel Sambuc case PCK_Linker: 273*f4a2713aSLionel Sambuc Consumer.HandleLinkerOptionPragma(Arg); 274*f4a2713aSLionel Sambuc return; 275*f4a2713aSLionel Sambuc case PCK_Lib: 276*f4a2713aSLionel Sambuc Consumer.HandleDependentLibrary(Arg); 277*f4a2713aSLionel Sambuc return; 278*f4a2713aSLionel Sambuc case PCK_Compiler: 279*f4a2713aSLionel Sambuc case PCK_ExeStr: 280*f4a2713aSLionel Sambuc case PCK_User: 281*f4a2713aSLionel Sambuc return; // We ignore all of these. 282*f4a2713aSLionel Sambuc } 283*f4a2713aSLionel Sambuc llvm_unreachable("invalid pragma comment kind"); 284*f4a2713aSLionel Sambuc } 285*f4a2713aSLionel Sambuc 286*f4a2713aSLionel Sambuc void Sema::ActOnPragmaDetectMismatch(StringRef Name, StringRef Value) { 287*f4a2713aSLionel Sambuc // FIXME: Serialize this. 288*f4a2713aSLionel Sambuc Consumer.HandleDetectMismatch(Name, Value); 289*f4a2713aSLionel Sambuc } 290*f4a2713aSLionel Sambuc 291*f4a2713aSLionel Sambuc void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, 292*f4a2713aSLionel Sambuc SourceLocation PragmaLoc) { 293*f4a2713aSLionel Sambuc 294*f4a2713aSLionel Sambuc IdentifierInfo *Name = IdTok.getIdentifierInfo(); 295*f4a2713aSLionel Sambuc LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); 296*f4a2713aSLionel Sambuc LookupParsedName(Lookup, curScope, NULL, true); 297*f4a2713aSLionel Sambuc 298*f4a2713aSLionel Sambuc if (Lookup.empty()) { 299*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) 300*f4a2713aSLionel Sambuc << Name << SourceRange(IdTok.getLocation()); 301*f4a2713aSLionel Sambuc return; 302*f4a2713aSLionel Sambuc } 303*f4a2713aSLionel Sambuc 304*f4a2713aSLionel Sambuc VarDecl *VD = Lookup.getAsSingle<VarDecl>(); 305*f4a2713aSLionel Sambuc if (!VD) { 306*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg) 307*f4a2713aSLionel Sambuc << Name << SourceRange(IdTok.getLocation()); 308*f4a2713aSLionel Sambuc return; 309*f4a2713aSLionel Sambuc } 310*f4a2713aSLionel Sambuc 311*f4a2713aSLionel Sambuc // Warn if this was used before being marked unused. 312*f4a2713aSLionel Sambuc if (VD->isUsed()) 313*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; 314*f4a2713aSLionel Sambuc 315*f4a2713aSLionel Sambuc VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context)); 316*f4a2713aSLionel Sambuc } 317*f4a2713aSLionel Sambuc 318*f4a2713aSLionel Sambuc void Sema::AddCFAuditedAttribute(Decl *D) { 319*f4a2713aSLionel Sambuc SourceLocation Loc = PP.getPragmaARCCFCodeAuditedLoc(); 320*f4a2713aSLionel Sambuc if (!Loc.isValid()) return; 321*f4a2713aSLionel Sambuc 322*f4a2713aSLionel Sambuc // Don't add a redundant or conflicting attribute. 323*f4a2713aSLionel Sambuc if (D->hasAttr<CFAuditedTransferAttr>() || 324*f4a2713aSLionel Sambuc D->hasAttr<CFUnknownTransferAttr>()) 325*f4a2713aSLionel Sambuc return; 326*f4a2713aSLionel Sambuc 327*f4a2713aSLionel Sambuc D->addAttr(::new (Context) CFAuditedTransferAttr(Loc, Context)); 328*f4a2713aSLionel Sambuc } 329*f4a2713aSLionel Sambuc 330*f4a2713aSLionel Sambuc typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; 331*f4a2713aSLionel Sambuc enum { NoVisibility = (unsigned) -1 }; 332*f4a2713aSLionel Sambuc 333*f4a2713aSLionel Sambuc void Sema::AddPushedVisibilityAttribute(Decl *D) { 334*f4a2713aSLionel Sambuc if (!VisContext) 335*f4a2713aSLionel Sambuc return; 336*f4a2713aSLionel Sambuc 337*f4a2713aSLionel Sambuc NamedDecl *ND = dyn_cast<NamedDecl>(D); 338*f4a2713aSLionel Sambuc if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue)) 339*f4a2713aSLionel Sambuc return; 340*f4a2713aSLionel Sambuc 341*f4a2713aSLionel Sambuc VisStack *Stack = static_cast<VisStack*>(VisContext); 342*f4a2713aSLionel Sambuc unsigned rawType = Stack->back().first; 343*f4a2713aSLionel Sambuc if (rawType == NoVisibility) return; 344*f4a2713aSLionel Sambuc 345*f4a2713aSLionel Sambuc VisibilityAttr::VisibilityType type 346*f4a2713aSLionel Sambuc = (VisibilityAttr::VisibilityType) rawType; 347*f4a2713aSLionel Sambuc SourceLocation loc = Stack->back().second; 348*f4a2713aSLionel Sambuc 349*f4a2713aSLionel Sambuc D->addAttr(::new (Context) VisibilityAttr(loc, Context, type)); 350*f4a2713aSLionel Sambuc } 351*f4a2713aSLionel Sambuc 352*f4a2713aSLionel Sambuc /// FreeVisContext - Deallocate and null out VisContext. 353*f4a2713aSLionel Sambuc void Sema::FreeVisContext() { 354*f4a2713aSLionel Sambuc delete static_cast<VisStack*>(VisContext); 355*f4a2713aSLionel Sambuc VisContext = 0; 356*f4a2713aSLionel Sambuc } 357*f4a2713aSLionel Sambuc 358*f4a2713aSLionel Sambuc static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { 359*f4a2713aSLionel Sambuc // Put visibility on stack. 360*f4a2713aSLionel Sambuc if (!S.VisContext) 361*f4a2713aSLionel Sambuc S.VisContext = new VisStack; 362*f4a2713aSLionel Sambuc 363*f4a2713aSLionel Sambuc VisStack *Stack = static_cast<VisStack*>(S.VisContext); 364*f4a2713aSLionel Sambuc Stack->push_back(std::make_pair(type, loc)); 365*f4a2713aSLionel Sambuc } 366*f4a2713aSLionel Sambuc 367*f4a2713aSLionel Sambuc void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, 368*f4a2713aSLionel Sambuc SourceLocation PragmaLoc) { 369*f4a2713aSLionel Sambuc if (VisType) { 370*f4a2713aSLionel Sambuc // Compute visibility to use. 371*f4a2713aSLionel Sambuc VisibilityAttr::VisibilityType T; 372*f4a2713aSLionel Sambuc if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) { 373*f4a2713aSLionel Sambuc Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType; 374*f4a2713aSLionel Sambuc return; 375*f4a2713aSLionel Sambuc } 376*f4a2713aSLionel Sambuc PushPragmaVisibility(*this, T, PragmaLoc); 377*f4a2713aSLionel Sambuc } else { 378*f4a2713aSLionel Sambuc PopPragmaVisibility(false, PragmaLoc); 379*f4a2713aSLionel Sambuc } 380*f4a2713aSLionel Sambuc } 381*f4a2713aSLionel Sambuc 382*f4a2713aSLionel Sambuc void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) { 383*f4a2713aSLionel Sambuc switch (OOS) { 384*f4a2713aSLionel Sambuc case tok::OOS_ON: 385*f4a2713aSLionel Sambuc FPFeatures.fp_contract = 1; 386*f4a2713aSLionel Sambuc break; 387*f4a2713aSLionel Sambuc case tok::OOS_OFF: 388*f4a2713aSLionel Sambuc FPFeatures.fp_contract = 0; 389*f4a2713aSLionel Sambuc break; 390*f4a2713aSLionel Sambuc case tok::OOS_DEFAULT: 391*f4a2713aSLionel Sambuc FPFeatures.fp_contract = getLangOpts().DefaultFPContract; 392*f4a2713aSLionel Sambuc break; 393*f4a2713aSLionel Sambuc } 394*f4a2713aSLionel Sambuc } 395*f4a2713aSLionel Sambuc 396*f4a2713aSLionel Sambuc void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, 397*f4a2713aSLionel Sambuc SourceLocation Loc) { 398*f4a2713aSLionel Sambuc // Visibility calculations will consider the namespace's visibility. 399*f4a2713aSLionel Sambuc // Here we just want to note that we're in a visibility context 400*f4a2713aSLionel Sambuc // which overrides any enclosing #pragma context, but doesn't itself 401*f4a2713aSLionel Sambuc // contribute visibility. 402*f4a2713aSLionel Sambuc PushPragmaVisibility(*this, NoVisibility, Loc); 403*f4a2713aSLionel Sambuc } 404*f4a2713aSLionel Sambuc 405*f4a2713aSLionel Sambuc void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { 406*f4a2713aSLionel Sambuc if (!VisContext) { 407*f4a2713aSLionel Sambuc Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); 408*f4a2713aSLionel Sambuc return; 409*f4a2713aSLionel Sambuc } 410*f4a2713aSLionel Sambuc 411*f4a2713aSLionel Sambuc // Pop visibility from stack 412*f4a2713aSLionel Sambuc VisStack *Stack = static_cast<VisStack*>(VisContext); 413*f4a2713aSLionel Sambuc 414*f4a2713aSLionel Sambuc const std::pair<unsigned, SourceLocation> *Back = &Stack->back(); 415*f4a2713aSLionel Sambuc bool StartsWithPragma = Back->first != NoVisibility; 416*f4a2713aSLionel Sambuc if (StartsWithPragma && IsNamespaceEnd) { 417*f4a2713aSLionel Sambuc Diag(Back->second, diag::err_pragma_push_visibility_mismatch); 418*f4a2713aSLionel Sambuc Diag(EndLoc, diag::note_surrounding_namespace_ends_here); 419*f4a2713aSLionel Sambuc 420*f4a2713aSLionel Sambuc // For better error recovery, eat all pushes inside the namespace. 421*f4a2713aSLionel Sambuc do { 422*f4a2713aSLionel Sambuc Stack->pop_back(); 423*f4a2713aSLionel Sambuc Back = &Stack->back(); 424*f4a2713aSLionel Sambuc StartsWithPragma = Back->first != NoVisibility; 425*f4a2713aSLionel Sambuc } while (StartsWithPragma); 426*f4a2713aSLionel Sambuc } else if (!StartsWithPragma && !IsNamespaceEnd) { 427*f4a2713aSLionel Sambuc Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); 428*f4a2713aSLionel Sambuc Diag(Back->second, diag::note_surrounding_namespace_starts_here); 429*f4a2713aSLionel Sambuc return; 430*f4a2713aSLionel Sambuc } 431*f4a2713aSLionel Sambuc 432*f4a2713aSLionel Sambuc Stack->pop_back(); 433*f4a2713aSLionel Sambuc // To simplify the implementation, never keep around an empty stack. 434*f4a2713aSLionel Sambuc if (Stack->empty()) 435*f4a2713aSLionel Sambuc FreeVisContext(); 436*f4a2713aSLionel Sambuc } 437