1193326Sed//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements the language specific #pragma handlers. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#include "ParsePragma.h" 15252723Sdim#include "clang/Lex/Preprocessor.h" 16193326Sed#include "clang/Parse/ParseDiagnostic.h" 17212904Sdim#include "clang/Parse/Parser.h" 18252723Sdim#include "clang/Sema/Scope.h" 19252723Sdim#include "llvm/ADT/StringSwitch.h" 20193326Sedusing namespace clang; 21193326Sed 22218893Sdim/// \brief Handle the annotation token produced for #pragma unused(...) 23218893Sdim/// 24218893Sdim/// Each annot_pragma_unused is followed by the argument token so e.g. 25218893Sdim/// "#pragma unused(x,y)" becomes: 26218893Sdim/// annot_pragma_unused 'x' annot_pragma_unused 'y' 27218893Sdimvoid Parser::HandlePragmaUnused() { 28218893Sdim assert(Tok.is(tok::annot_pragma_unused)); 29218893Sdim SourceLocation UnusedLoc = ConsumeToken(); 30218893Sdim Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc); 31218893Sdim ConsumeToken(); // The argument token. 32218893Sdim} 33212904Sdim 34235633Sdimvoid Parser::HandlePragmaVisibility() { 35235633Sdim assert(Tok.is(tok::annot_pragma_vis)); 36235633Sdim const IdentifierInfo *VisType = 37235633Sdim static_cast<IdentifierInfo *>(Tok.getAnnotationValue()); 38235633Sdim SourceLocation VisLoc = ConsumeToken(); 39235633Sdim Actions.ActOnPragmaVisibility(VisType, VisLoc); 40235633Sdim} 41235633Sdim 42235633Sdimstruct PragmaPackInfo { 43235633Sdim Sema::PragmaPackKind Kind; 44235633Sdim IdentifierInfo *Name; 45245431Sdim Token Alignment; 46235633Sdim SourceLocation LParenLoc; 47235633Sdim SourceLocation RParenLoc; 48235633Sdim}; 49235633Sdim 50235633Sdimvoid Parser::HandlePragmaPack() { 51235633Sdim assert(Tok.is(tok::annot_pragma_pack)); 52235633Sdim PragmaPackInfo *Info = 53235633Sdim static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); 54235633Sdim SourceLocation PragmaLoc = ConsumeToken(); 55245431Sdim ExprResult Alignment; 56245431Sdim if (Info->Alignment.is(tok::numeric_constant)) { 57245431Sdim Alignment = Actions.ActOnNumericConstant(Info->Alignment); 58245431Sdim if (Alignment.isInvalid()) 59245431Sdim return; 60245431Sdim } 61245431Sdim Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, 62235633Sdim Info->LParenLoc, Info->RParenLoc); 63235633Sdim} 64235633Sdim 65245431Sdimvoid Parser::HandlePragmaMSStruct() { 66245431Sdim assert(Tok.is(tok::annot_pragma_msstruct)); 67245431Sdim Sema::PragmaMSStructKind Kind = 68245431Sdim static_cast<Sema::PragmaMSStructKind>( 69245431Sdim reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 70245431Sdim Actions.ActOnPragmaMSStruct(Kind); 71245431Sdim ConsumeToken(); // The annotation token. 72245431Sdim} 73245431Sdim 74245431Sdimvoid Parser::HandlePragmaAlign() { 75245431Sdim assert(Tok.is(tok::annot_pragma_align)); 76245431Sdim Sema::PragmaOptionsAlignKind Kind = 77245431Sdim static_cast<Sema::PragmaOptionsAlignKind>( 78245431Sdim reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 79245431Sdim SourceLocation PragmaLoc = ConsumeToken(); 80245431Sdim Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); 81245431Sdim} 82245431Sdim 83245431Sdimvoid Parser::HandlePragmaWeak() { 84245431Sdim assert(Tok.is(tok::annot_pragma_weak)); 85245431Sdim SourceLocation PragmaLoc = ConsumeToken(); 86245431Sdim Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, 87245431Sdim Tok.getLocation()); 88245431Sdim ConsumeToken(); // The weak name. 89245431Sdim} 90245431Sdim 91245431Sdimvoid Parser::HandlePragmaWeakAlias() { 92245431Sdim assert(Tok.is(tok::annot_pragma_weakalias)); 93245431Sdim SourceLocation PragmaLoc = ConsumeToken(); 94245431Sdim IdentifierInfo *WeakName = Tok.getIdentifierInfo(); 95245431Sdim SourceLocation WeakNameLoc = Tok.getLocation(); 96245431Sdim ConsumeToken(); 97245431Sdim IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 98245431Sdim SourceLocation AliasNameLoc = Tok.getLocation(); 99245431Sdim ConsumeToken(); 100245431Sdim Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc, 101245431Sdim WeakNameLoc, AliasNameLoc); 102245431Sdim 103245431Sdim} 104245431Sdim 105245431Sdimvoid Parser::HandlePragmaRedefineExtname() { 106245431Sdim assert(Tok.is(tok::annot_pragma_redefine_extname)); 107245431Sdim SourceLocation RedefLoc = ConsumeToken(); 108245431Sdim IdentifierInfo *RedefName = Tok.getIdentifierInfo(); 109245431Sdim SourceLocation RedefNameLoc = Tok.getLocation(); 110245431Sdim ConsumeToken(); 111245431Sdim IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 112245431Sdim SourceLocation AliasNameLoc = Tok.getLocation(); 113245431Sdim ConsumeToken(); 114245431Sdim Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, 115245431Sdim RedefNameLoc, AliasNameLoc); 116245431Sdim} 117245431Sdim 118245431Sdimvoid Parser::HandlePragmaFPContract() { 119245431Sdim assert(Tok.is(tok::annot_pragma_fp_contract)); 120245431Sdim tok::OnOffSwitch OOS = 121245431Sdim static_cast<tok::OnOffSwitch>( 122245431Sdim reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 123245431Sdim Actions.ActOnPragmaFPContract(OOS); 124245431Sdim ConsumeToken(); // The annotation token. 125245431Sdim} 126245431Sdim 127252723SdimStmtResult Parser::HandlePragmaCaptured() 128252723Sdim{ 129252723Sdim assert(Tok.is(tok::annot_pragma_captured)); 130252723Sdim ConsumeToken(); 131252723Sdim 132252723Sdim if (Tok.isNot(tok::l_brace)) { 133252723Sdim PP.Diag(Tok, diag::err_expected_lbrace); 134252723Sdim return StmtError(); 135252723Sdim } 136252723Sdim 137252723Sdim SourceLocation Loc = Tok.getLocation(); 138252723Sdim 139252723Sdim ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope); 140252723Sdim Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 141252723Sdim /*NumParams=*/1); 142252723Sdim 143252723Sdim StmtResult R = ParseCompoundStatement(); 144252723Sdim CapturedRegionScope.Exit(); 145252723Sdim 146252723Sdim if (R.isInvalid()) { 147252723Sdim Actions.ActOnCapturedRegionError(); 148252723Sdim return StmtError(); 149252723Sdim } 150252723Sdim 151252723Sdim return Actions.ActOnCapturedRegionEnd(R.get()); 152252723Sdim} 153252723Sdim 154245431Sdimnamespace { 155245431Sdim typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData; 156245431Sdim} 157245431Sdim 158245431Sdimvoid Parser::HandlePragmaOpenCLExtension() { 159245431Sdim assert(Tok.is(tok::annot_pragma_opencl_extension)); 160245431Sdim OpenCLExtData data = 161245431Sdim OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue()); 162245431Sdim unsigned state = data.getInt(); 163245431Sdim IdentifierInfo *ename = data.getPointer(); 164245431Sdim SourceLocation NameLoc = Tok.getLocation(); 165245431Sdim ConsumeToken(); // The annotation token. 166245431Sdim 167245431Sdim OpenCLOptions &f = Actions.getOpenCLOptions(); 168245431Sdim // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, 169245431Sdim // overriding all previously issued extension directives, but only if the 170245431Sdim // behavior is set to disable." 171245431Sdim if (state == 0 && ename->isStr("all")) { 172245431Sdim#define OPENCLEXT(nm) f.nm = 0; 173245431Sdim#include "clang/Basic/OpenCLExtensions.def" 174245431Sdim } 175245431Sdim#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; } 176245431Sdim#include "clang/Basic/OpenCLExtensions.def" 177245431Sdim else { 178245431Sdim PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename; 179245431Sdim return; 180245431Sdim } 181245431Sdim} 182245431Sdim 183252723Sdim 184252723Sdim 185212904Sdim// #pragma GCC visibility comes in two variants: 186212904Sdim// 'push' '(' [visibility] ')' 187212904Sdim// 'pop' 188218893Sdimvoid PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, 189218893Sdim PragmaIntroducerKind Introducer, 190218893Sdim Token &VisTok) { 191212904Sdim SourceLocation VisLoc = VisTok.getLocation(); 192212904Sdim 193212904Sdim Token Tok; 194226890Sdim PP.LexUnexpandedToken(Tok); 195212904Sdim 196212904Sdim const IdentifierInfo *PushPop = Tok.getIdentifierInfo(); 197212904Sdim 198212904Sdim const IdentifierInfo *VisType; 199212904Sdim if (PushPop && PushPop->isStr("pop")) { 200212904Sdim VisType = 0; 201212904Sdim } else if (PushPop && PushPop->isStr("push")) { 202226890Sdim PP.LexUnexpandedToken(Tok); 203212904Sdim if (Tok.isNot(tok::l_paren)) { 204212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) 205212904Sdim << "visibility"; 206212904Sdim return; 207212904Sdim } 208226890Sdim PP.LexUnexpandedToken(Tok); 209212904Sdim VisType = Tok.getIdentifierInfo(); 210212904Sdim if (!VisType) { 211212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 212212904Sdim << "visibility"; 213212904Sdim return; 214212904Sdim } 215226890Sdim PP.LexUnexpandedToken(Tok); 216212904Sdim if (Tok.isNot(tok::r_paren)) { 217212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) 218212904Sdim << "visibility"; 219212904Sdim return; 220212904Sdim } 221212904Sdim } else { 222212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 223212904Sdim << "visibility"; 224212904Sdim return; 225212904Sdim } 226226890Sdim PP.LexUnexpandedToken(Tok); 227221345Sdim if (Tok.isNot(tok::eod)) { 228212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 229212904Sdim << "visibility"; 230212904Sdim return; 231212904Sdim } 232212904Sdim 233235633Sdim Token *Toks = new Token[1]; 234235633Sdim Toks[0].startToken(); 235235633Sdim Toks[0].setKind(tok::annot_pragma_vis); 236235633Sdim Toks[0].setLocation(VisLoc); 237235633Sdim Toks[0].setAnnotationValue( 238235633Sdim const_cast<void*>(static_cast<const void*>(VisType))); 239235633Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 240235633Sdim /*OwnsTokens=*/true); 241212904Sdim} 242212904Sdim 243193326Sed// #pragma pack(...) comes in the following delicious flavors: 244193326Sed// pack '(' [integer] ')' 245193326Sed// pack '(' 'show' ')' 246193326Sed// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')' 247218893Sdimvoid PragmaPackHandler::HandlePragma(Preprocessor &PP, 248218893Sdim PragmaIntroducerKind Introducer, 249218893Sdim Token &PackTok) { 250193326Sed SourceLocation PackLoc = PackTok.getLocation(); 251193326Sed 252193326Sed Token Tok; 253193326Sed PP.Lex(Tok); 254193326Sed if (Tok.isNot(tok::l_paren)) { 255193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack"; 256193326Sed return; 257193326Sed } 258193326Sed 259212904Sdim Sema::PragmaPackKind Kind = Sema::PPK_Default; 260193326Sed IdentifierInfo *Name = 0; 261245431Sdim Token Alignment; 262245431Sdim Alignment.startToken(); 263193326Sed SourceLocation LParenLoc = Tok.getLocation(); 264198092Srdivacky PP.Lex(Tok); 265193326Sed if (Tok.is(tok::numeric_constant)) { 266245431Sdim Alignment = Tok; 267193326Sed 268193326Sed PP.Lex(Tok); 269235633Sdim 270235633Sdim // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting 271235633Sdim // the push/pop stack. 272235633Sdim // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4) 273235633Sdim if (PP.getLangOpts().ApplePragmaPack) 274235633Sdim Kind = Sema::PPK_Push; 275193326Sed } else if (Tok.is(tok::identifier)) { 276193326Sed const IdentifierInfo *II = Tok.getIdentifierInfo(); 277193326Sed if (II->isStr("show")) { 278212904Sdim Kind = Sema::PPK_Show; 279193326Sed PP.Lex(Tok); 280193326Sed } else { 281193326Sed if (II->isStr("push")) { 282212904Sdim Kind = Sema::PPK_Push; 283193326Sed } else if (II->isStr("pop")) { 284212904Sdim Kind = Sema::PPK_Pop; 285193326Sed } else { 286193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action); 287193326Sed return; 288198092Srdivacky } 289193326Sed PP.Lex(Tok); 290198092Srdivacky 291193326Sed if (Tok.is(tok::comma)) { 292193326Sed PP.Lex(Tok); 293198092Srdivacky 294193326Sed if (Tok.is(tok::numeric_constant)) { 295245431Sdim Alignment = Tok; 296193326Sed 297193326Sed PP.Lex(Tok); 298193326Sed } else if (Tok.is(tok::identifier)) { 299193326Sed Name = Tok.getIdentifierInfo(); 300193326Sed PP.Lex(Tok); 301198092Srdivacky 302193326Sed if (Tok.is(tok::comma)) { 303193326Sed PP.Lex(Tok); 304198092Srdivacky 305193326Sed if (Tok.isNot(tok::numeric_constant)) { 306193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 307193326Sed return; 308193326Sed } 309198092Srdivacky 310245431Sdim Alignment = Tok; 311193326Sed 312193326Sed PP.Lex(Tok); 313193326Sed } 314193326Sed } else { 315193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed); 316193326Sed return; 317193326Sed } 318193326Sed } 319193326Sed } 320235633Sdim } else if (PP.getLangOpts().ApplePragmaPack) { 321235633Sdim // In MSVC/gcc, #pragma pack() resets the alignment without affecting 322235633Sdim // the push/pop stack. 323235633Sdim // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop). 324235633Sdim Kind = Sema::PPK_Pop; 325193326Sed } 326193326Sed 327193326Sed if (Tok.isNot(tok::r_paren)) { 328193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack"; 329193326Sed return; 330193326Sed } 331193326Sed 332208600Srdivacky SourceLocation RParenLoc = Tok.getLocation(); 333193576Sed PP.Lex(Tok); 334221345Sdim if (Tok.isNot(tok::eod)) { 335193576Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack"; 336193576Sed return; 337193576Sed } 338193576Sed 339235633Sdim PragmaPackInfo *Info = 340235633Sdim (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate( 341235633Sdim sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>()); 342235633Sdim new (Info) PragmaPackInfo(); 343235633Sdim Info->Kind = Kind; 344235633Sdim Info->Name = Name; 345245431Sdim Info->Alignment = Alignment; 346235633Sdim Info->LParenLoc = LParenLoc; 347235633Sdim Info->RParenLoc = RParenLoc; 348235633Sdim 349235633Sdim Token *Toks = 350235633Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 351235633Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 352235633Sdim new (Toks) Token(); 353235633Sdim Toks[0].startToken(); 354235633Sdim Toks[0].setKind(tok::annot_pragma_pack); 355235633Sdim Toks[0].setLocation(PackLoc); 356235633Sdim Toks[0].setAnnotationValue(static_cast<void*>(Info)); 357235633Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 358235633Sdim /*OwnsTokens=*/false); 359193326Sed} 360193326Sed 361221345Sdim// #pragma ms_struct on 362221345Sdim// #pragma ms_struct off 363221345Sdimvoid PragmaMSStructHandler::HandlePragma(Preprocessor &PP, 364221345Sdim PragmaIntroducerKind Introducer, 365221345Sdim Token &MSStructTok) { 366221345Sdim Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF; 367221345Sdim 368221345Sdim Token Tok; 369221345Sdim PP.Lex(Tok); 370221345Sdim if (Tok.isNot(tok::identifier)) { 371221345Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 372221345Sdim return; 373221345Sdim } 374221345Sdim const IdentifierInfo *II = Tok.getIdentifierInfo(); 375221345Sdim if (II->isStr("on")) { 376221345Sdim Kind = Sema::PMSST_ON; 377221345Sdim PP.Lex(Tok); 378221345Sdim } 379221345Sdim else if (II->isStr("off") || II->isStr("reset")) 380221345Sdim PP.Lex(Tok); 381221345Sdim else { 382221345Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct); 383221345Sdim return; 384221345Sdim } 385221345Sdim 386221345Sdim if (Tok.isNot(tok::eod)) { 387235633Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 388235633Sdim << "ms_struct"; 389221345Sdim return; 390221345Sdim } 391245431Sdim 392245431Sdim Token *Toks = 393245431Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 394245431Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 395245431Sdim new (Toks) Token(); 396245431Sdim Toks[0].startToken(); 397245431Sdim Toks[0].setKind(tok::annot_pragma_msstruct); 398245431Sdim Toks[0].setLocation(MSStructTok.getLocation()); 399245431Sdim Toks[0].setAnnotationValue(reinterpret_cast<void*>( 400245431Sdim static_cast<uintptr_t>(Kind))); 401245431Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 402245431Sdim /*OwnsTokens=*/false); 403221345Sdim} 404221345Sdim 405212904Sdim// #pragma 'align' '=' {'native','natural','mac68k','power','reset'} 406212904Sdim// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} 407245431Sdimstatic void ParseAlignPragma(Preprocessor &PP, Token &FirstTok, 408212904Sdim bool IsOptions) { 409212904Sdim Token Tok; 410208600Srdivacky 411212904Sdim if (IsOptions) { 412212904Sdim PP.Lex(Tok); 413212904Sdim if (Tok.isNot(tok::identifier) || 414212904Sdim !Tok.getIdentifierInfo()->isStr("align")) { 415212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align); 416212904Sdim return; 417212904Sdim } 418208600Srdivacky } 419210299Sed 420208600Srdivacky PP.Lex(Tok); 421208600Srdivacky if (Tok.isNot(tok::equal)) { 422212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal) 423212904Sdim << IsOptions; 424208600Srdivacky return; 425208600Srdivacky } 426208600Srdivacky 427208600Srdivacky PP.Lex(Tok); 428208600Srdivacky if (Tok.isNot(tok::identifier)) { 429208600Srdivacky PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 430212904Sdim << (IsOptions ? "options" : "align"); 431208600Srdivacky return; 432208600Srdivacky } 433208600Srdivacky 434212904Sdim Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural; 435208600Srdivacky const IdentifierInfo *II = Tok.getIdentifierInfo(); 436210299Sed if (II->isStr("native")) 437212904Sdim Kind = Sema::POAK_Native; 438210299Sed else if (II->isStr("natural")) 439212904Sdim Kind = Sema::POAK_Natural; 440210299Sed else if (II->isStr("packed")) 441212904Sdim Kind = Sema::POAK_Packed; 442208600Srdivacky else if (II->isStr("power")) 443212904Sdim Kind = Sema::POAK_Power; 444208600Srdivacky else if (II->isStr("mac68k")) 445212904Sdim Kind = Sema::POAK_Mac68k; 446208600Srdivacky else if (II->isStr("reset")) 447212904Sdim Kind = Sema::POAK_Reset; 448208600Srdivacky else { 449212904Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option) 450212904Sdim << IsOptions; 451208600Srdivacky return; 452208600Srdivacky } 453208600Srdivacky 454208600Srdivacky PP.Lex(Tok); 455221345Sdim if (Tok.isNot(tok::eod)) { 456208600Srdivacky PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 457212904Sdim << (IsOptions ? "options" : "align"); 458208600Srdivacky return; 459208600Srdivacky } 460208600Srdivacky 461245431Sdim Token *Toks = 462245431Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 463245431Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 464245431Sdim new (Toks) Token(); 465245431Sdim Toks[0].startToken(); 466245431Sdim Toks[0].setKind(tok::annot_pragma_align); 467245431Sdim Toks[0].setLocation(FirstTok.getLocation()); 468245431Sdim Toks[0].setAnnotationValue(reinterpret_cast<void*>( 469245431Sdim static_cast<uintptr_t>(Kind))); 470245431Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 471245431Sdim /*OwnsTokens=*/false); 472208600Srdivacky} 473208600Srdivacky 474218893Sdimvoid PragmaAlignHandler::HandlePragma(Preprocessor &PP, 475218893Sdim PragmaIntroducerKind Introducer, 476218893Sdim Token &AlignTok) { 477245431Sdim ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false); 478212904Sdim} 479212904Sdim 480218893Sdimvoid PragmaOptionsHandler::HandlePragma(Preprocessor &PP, 481218893Sdim PragmaIntroducerKind Introducer, 482218893Sdim Token &OptionsTok) { 483245431Sdim ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true); 484212904Sdim} 485212904Sdim 486193326Sed// #pragma unused(identifier) 487218893Sdimvoid PragmaUnusedHandler::HandlePragma(Preprocessor &PP, 488218893Sdim PragmaIntroducerKind Introducer, 489218893Sdim Token &UnusedTok) { 490193326Sed // FIXME: Should we be expanding macros here? My guess is no. 491193326Sed SourceLocation UnusedLoc = UnusedTok.getLocation(); 492198092Srdivacky 493193326Sed // Lex the left '('. 494193326Sed Token Tok; 495193326Sed PP.Lex(Tok); 496193326Sed if (Tok.isNot(tok::l_paren)) { 497193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused"; 498193326Sed return; 499193326Sed } 500198092Srdivacky 501193326Sed // Lex the declaration reference(s). 502226890Sdim SmallVector<Token, 5> Identifiers; 503193326Sed SourceLocation RParenLoc; 504193326Sed bool LexID = true; 505198092Srdivacky 506193326Sed while (true) { 507193326Sed PP.Lex(Tok); 508198092Srdivacky 509193326Sed if (LexID) { 510198092Srdivacky if (Tok.is(tok::identifier)) { 511198092Srdivacky Identifiers.push_back(Tok); 512193326Sed LexID = false; 513193326Sed continue; 514193326Sed } 515193326Sed 516198092Srdivacky // Illegal token! 517193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var); 518193326Sed return; 519193326Sed } 520198092Srdivacky 521193326Sed // We are execting a ')' or a ','. 522193326Sed if (Tok.is(tok::comma)) { 523193326Sed LexID = true; 524193326Sed continue; 525193326Sed } 526198092Srdivacky 527193326Sed if (Tok.is(tok::r_paren)) { 528193326Sed RParenLoc = Tok.getLocation(); 529193326Sed break; 530193326Sed } 531198092Srdivacky 532198092Srdivacky // Illegal token! 533193326Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc); 534193326Sed return; 535193326Sed } 536193576Sed 537193576Sed PP.Lex(Tok); 538221345Sdim if (Tok.isNot(tok::eod)) { 539193576Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 540193576Sed "unused"; 541193576Sed return; 542193576Sed } 543193576Sed 544193326Sed // Verify that we have a location for the right parenthesis. 545193326Sed assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'"); 546198092Srdivacky assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments"); 547193326Sed 548218893Sdim // For each identifier token, insert into the token stream a 549218893Sdim // annot_pragma_unused token followed by the identifier token. 550218893Sdim // This allows us to cache a "#pragma unused" that occurs inside an inline 551218893Sdim // C++ member function. 552218893Sdim 553235633Sdim Token *Toks = 554235633Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 555235633Sdim sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>()); 556218893Sdim for (unsigned i=0; i != Identifiers.size(); i++) { 557218893Sdim Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1]; 558218893Sdim pragmaUnusedTok.startToken(); 559218893Sdim pragmaUnusedTok.setKind(tok::annot_pragma_unused); 560218893Sdim pragmaUnusedTok.setLocation(UnusedLoc); 561218893Sdim idTok = Identifiers[i]; 562218893Sdim } 563235633Sdim PP.EnterTokenStream(Toks, 2*Identifiers.size(), 564235633Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 565193326Sed} 566193576Sed 567193576Sed// #pragma weak identifier 568193576Sed// #pragma weak identifier '=' identifier 569218893Sdimvoid PragmaWeakHandler::HandlePragma(Preprocessor &PP, 570218893Sdim PragmaIntroducerKind Introducer, 571218893Sdim Token &WeakTok) { 572193576Sed SourceLocation WeakLoc = WeakTok.getLocation(); 573193576Sed 574193576Sed Token Tok; 575193576Sed PP.Lex(Tok); 576193576Sed if (Tok.isNot(tok::identifier)) { 577193576Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak"; 578193576Sed return; 579193576Sed } 580193576Sed 581245431Sdim Token WeakName = Tok; 582245431Sdim bool HasAlias = false; 583245431Sdim Token AliasName; 584193576Sed 585193576Sed PP.Lex(Tok); 586193576Sed if (Tok.is(tok::equal)) { 587245431Sdim HasAlias = true; 588193576Sed PP.Lex(Tok); 589193576Sed if (Tok.isNot(tok::identifier)) { 590198092Srdivacky PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 591193576Sed << "weak"; 592193576Sed return; 593193576Sed } 594245431Sdim AliasName = Tok; 595193576Sed PP.Lex(Tok); 596193576Sed } 597193576Sed 598221345Sdim if (Tok.isNot(tok::eod)) { 599193576Sed PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak"; 600193576Sed return; 601193576Sed } 602193576Sed 603245431Sdim if (HasAlias) { 604245431Sdim Token *Toks = 605245431Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 606245431Sdim sizeof(Token) * 3, llvm::alignOf<Token>()); 607245431Sdim Token &pragmaUnusedTok = Toks[0]; 608245431Sdim pragmaUnusedTok.startToken(); 609245431Sdim pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); 610245431Sdim pragmaUnusedTok.setLocation(WeakLoc); 611245431Sdim Toks[1] = WeakName; 612245431Sdim Toks[2] = AliasName; 613245431Sdim PP.EnterTokenStream(Toks, 3, 614245431Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 615193576Sed } else { 616245431Sdim Token *Toks = 617245431Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 618245431Sdim sizeof(Token) * 2, llvm::alignOf<Token>()); 619245431Sdim Token &pragmaUnusedTok = Toks[0]; 620245431Sdim pragmaUnusedTok.startToken(); 621245431Sdim pragmaUnusedTok.setKind(tok::annot_pragma_weak); 622245431Sdim pragmaUnusedTok.setLocation(WeakLoc); 623245431Sdim Toks[1] = WeakName; 624245431Sdim PP.EnterTokenStream(Toks, 2, 625245431Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 626193576Sed } 627193576Sed} 628218893Sdim 629235633Sdim// #pragma redefine_extname identifier identifier 630235633Sdimvoid PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, 631235633Sdim PragmaIntroducerKind Introducer, 632235633Sdim Token &RedefToken) { 633235633Sdim SourceLocation RedefLoc = RedefToken.getLocation(); 634235633Sdim 635235633Sdim Token Tok; 636235633Sdim PP.Lex(Tok); 637235633Sdim if (Tok.isNot(tok::identifier)) { 638235633Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 639235633Sdim "redefine_extname"; 640235633Sdim return; 641235633Sdim } 642235633Sdim 643245431Sdim Token RedefName = Tok; 644245431Sdim PP.Lex(Tok); 645235633Sdim 646235633Sdim if (Tok.isNot(tok::identifier)) { 647235633Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 648235633Sdim << "redefine_extname"; 649235633Sdim return; 650235633Sdim } 651245431Sdim 652245431Sdim Token AliasName = Tok; 653235633Sdim PP.Lex(Tok); 654235633Sdim 655235633Sdim if (Tok.isNot(tok::eod)) { 656235633Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 657235633Sdim "redefine_extname"; 658235633Sdim return; 659235633Sdim } 660235633Sdim 661245431Sdim Token *Toks = 662245431Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 663245431Sdim sizeof(Token) * 3, llvm::alignOf<Token>()); 664245431Sdim Token &pragmaRedefTok = Toks[0]; 665245431Sdim pragmaRedefTok.startToken(); 666245431Sdim pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); 667245431Sdim pragmaRedefTok.setLocation(RedefLoc); 668245431Sdim Toks[1] = RedefName; 669245431Sdim Toks[2] = AliasName; 670245431Sdim PP.EnterTokenStream(Toks, 3, 671245431Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 672235633Sdim} 673235633Sdim 674235633Sdim 675218893Sdimvoid 676218893SdimPragmaFPContractHandler::HandlePragma(Preprocessor &PP, 677218893Sdim PragmaIntroducerKind Introducer, 678218893Sdim Token &Tok) { 679218893Sdim tok::OnOffSwitch OOS; 680218893Sdim if (PP.LexOnOffSwitch(OOS)) 681218893Sdim return; 682218893Sdim 683245431Sdim Token *Toks = 684245431Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 685245431Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 686245431Sdim new (Toks) Token(); 687245431Sdim Toks[0].startToken(); 688245431Sdim Toks[0].setKind(tok::annot_pragma_fp_contract); 689245431Sdim Toks[0].setLocation(Tok.getLocation()); 690245431Sdim Toks[0].setAnnotationValue(reinterpret_cast<void*>( 691245431Sdim static_cast<uintptr_t>(OOS))); 692245431Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 693245431Sdim /*OwnsTokens=*/false); 694218893Sdim} 695218893Sdim 696218893Sdimvoid 697218893SdimPragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, 698218893Sdim PragmaIntroducerKind Introducer, 699218893Sdim Token &Tok) { 700221345Sdim PP.LexUnexpandedToken(Tok); 701218893Sdim if (Tok.isNot(tok::identifier)) { 702218893Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 703218893Sdim "OPENCL"; 704218893Sdim return; 705218893Sdim } 706218893Sdim IdentifierInfo *ename = Tok.getIdentifierInfo(); 707218893Sdim SourceLocation NameLoc = Tok.getLocation(); 708218893Sdim 709218893Sdim PP.Lex(Tok); 710218893Sdim if (Tok.isNot(tok::colon)) { 711218893Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename; 712218893Sdim return; 713218893Sdim } 714218893Sdim 715218893Sdim PP.Lex(Tok); 716218893Sdim if (Tok.isNot(tok::identifier)) { 717218893Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); 718218893Sdim return; 719218893Sdim } 720218893Sdim IdentifierInfo *op = Tok.getIdentifierInfo(); 721218893Sdim 722218893Sdim unsigned state; 723218893Sdim if (op->isStr("enable")) { 724218893Sdim state = 1; 725218893Sdim } else if (op->isStr("disable")) { 726218893Sdim state = 0; 727218893Sdim } else { 728218893Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); 729218893Sdim return; 730218893Sdim } 731263509Sdim SourceLocation StateLoc = Tok.getLocation(); 732218893Sdim 733245431Sdim PP.Lex(Tok); 734245431Sdim if (Tok.isNot(tok::eod)) { 735245431Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 736245431Sdim "OPENCL EXTENSION"; 737218893Sdim return; 738218893Sdim } 739245431Sdim 740245431Sdim OpenCLExtData data(ename, state); 741245431Sdim Token *Toks = 742245431Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 743245431Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 744245431Sdim new (Toks) Token(); 745245431Sdim Toks[0].startToken(); 746245431Sdim Toks[0].setKind(tok::annot_pragma_opencl_extension); 747245431Sdim Toks[0].setLocation(NameLoc); 748245431Sdim Toks[0].setAnnotationValue(data.getOpaqueValue()); 749245431Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 750245431Sdim /*OwnsTokens=*/false); 751263509Sdim 752263509Sdim if (PP.getPPCallbacks()) 753263509Sdim PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename, 754263509Sdim StateLoc, state); 755218893Sdim} 756218893Sdim 757252723Sdim/// \brief Handle '#pragma omp ...' when OpenMP is disabled. 758252723Sdim/// 759252723Sdimvoid 760252723SdimPragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, 761252723Sdim PragmaIntroducerKind Introducer, 762252723Sdim Token &FirstTok) { 763252723Sdim if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored, 764252723Sdim FirstTok.getLocation()) != 765252723Sdim DiagnosticsEngine::Ignored) { 766252723Sdim PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); 767252723Sdim PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored, 768252723Sdim diag::MAP_IGNORE, 769252723Sdim SourceLocation()); 770252723Sdim } 771252723Sdim PP.DiscardUntilEndOfDirective(); 772252723Sdim} 773252723Sdim 774252723Sdim/// \brief Handle '#pragma omp ...' when OpenMP is enabled. 775252723Sdim/// 776252723Sdimvoid 777252723SdimPragmaOpenMPHandler::HandlePragma(Preprocessor &PP, 778252723Sdim PragmaIntroducerKind Introducer, 779252723Sdim Token &FirstTok) { 780252723Sdim SmallVector<Token, 16> Pragma; 781252723Sdim Token Tok; 782252723Sdim Tok.startToken(); 783252723Sdim Tok.setKind(tok::annot_pragma_openmp); 784252723Sdim Tok.setLocation(FirstTok.getLocation()); 785252723Sdim 786252723Sdim while (Tok.isNot(tok::eod)) { 787252723Sdim Pragma.push_back(Tok); 788252723Sdim PP.Lex(Tok); 789252723Sdim } 790252723Sdim SourceLocation EodLoc = Tok.getLocation(); 791252723Sdim Tok.startToken(); 792252723Sdim Tok.setKind(tok::annot_pragma_openmp_end); 793252723Sdim Tok.setLocation(EodLoc); 794252723Sdim Pragma.push_back(Tok); 795252723Sdim 796252723Sdim Token *Toks = new Token[Pragma.size()]; 797252723Sdim std::copy(Pragma.begin(), Pragma.end(), Toks); 798252723Sdim PP.EnterTokenStream(Toks, Pragma.size(), 799252723Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); 800252723Sdim} 801252723Sdim 802263509Sdim/// \brief Handle the Microsoft \#pragma detect_mismatch extension. 803263509Sdim/// 804263509Sdim/// The syntax is: 805263509Sdim/// \code 806263509Sdim/// #pragma detect_mismatch("name", "value") 807263509Sdim/// \endcode 808263509Sdim/// Where 'name' and 'value' are quoted strings. The values are embedded in 809263509Sdim/// the object file and passed along to the linker. If the linker detects a 810263509Sdim/// mismatch in the object file's values for the given name, a LNK2038 error 811263509Sdim/// is emitted. See MSDN for more details. 812263509Sdimvoid PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, 813263509Sdim PragmaIntroducerKind Introducer, 814263509Sdim Token &Tok) { 815263509Sdim SourceLocation CommentLoc = Tok.getLocation(); 816263509Sdim PP.Lex(Tok); 817263509Sdim if (Tok.isNot(tok::l_paren)) { 818263509Sdim PP.Diag(CommentLoc, diag::err_expected_lparen); 819263509Sdim return; 820263509Sdim } 821263509Sdim 822263509Sdim // Read the name to embed, which must be a string literal. 823263509Sdim std::string NameString; 824263509Sdim if (!PP.LexStringLiteral(Tok, NameString, 825263509Sdim "pragma detect_mismatch", 826263509Sdim /*MacroExpansion=*/true)) 827263509Sdim return; 828263509Sdim 829263509Sdim // Read the comma followed by a second string literal. 830263509Sdim std::string ValueString; 831263509Sdim if (Tok.isNot(tok::comma)) { 832263509Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 833263509Sdim return; 834263509Sdim } 835263509Sdim 836263509Sdim if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", 837263509Sdim /*MacroExpansion=*/true)) 838263509Sdim return; 839263509Sdim 840263509Sdim if (Tok.isNot(tok::r_paren)) { 841263509Sdim PP.Diag(Tok.getLocation(), diag::err_expected_rparen); 842263509Sdim return; 843263509Sdim } 844263509Sdim PP.Lex(Tok); // Eat the r_paren. 845263509Sdim 846263509Sdim if (Tok.isNot(tok::eod)) { 847263509Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 848263509Sdim return; 849263509Sdim } 850263509Sdim 851263509Sdim // If the pragma is lexically sound, notify any interested PPCallbacks. 852263509Sdim if (PP.getPPCallbacks()) 853263509Sdim PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString, 854263509Sdim ValueString); 855263509Sdim 856263509Sdim Actions.ActOnPragmaDetectMismatch(NameString, ValueString); 857263509Sdim} 858263509Sdim 859252723Sdim/// \brief Handle the microsoft \#pragma comment extension. 860252723Sdim/// 861252723Sdim/// The syntax is: 862252723Sdim/// \code 863252723Sdim/// #pragma comment(linker, "foo") 864252723Sdim/// \endcode 865252723Sdim/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. 866252723Sdim/// "foo" is a string, which is fully macro expanded, and permits string 867252723Sdim/// concatenation, embedded escape characters etc. See MSDN for more details. 868252723Sdimvoid PragmaCommentHandler::HandlePragma(Preprocessor &PP, 869252723Sdim PragmaIntroducerKind Introducer, 870252723Sdim Token &Tok) { 871252723Sdim SourceLocation CommentLoc = Tok.getLocation(); 872252723Sdim PP.Lex(Tok); 873252723Sdim if (Tok.isNot(tok::l_paren)) { 874252723Sdim PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 875252723Sdim return; 876252723Sdim } 877252723Sdim 878252723Sdim // Read the identifier. 879252723Sdim PP.Lex(Tok); 880252723Sdim if (Tok.isNot(tok::identifier)) { 881252723Sdim PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 882252723Sdim return; 883252723Sdim } 884252723Sdim 885252723Sdim // Verify that this is one of the 5 whitelisted options. 886263509Sdim IdentifierInfo *II = Tok.getIdentifierInfo(); 887263509Sdim Sema::PragmaMSCommentKind Kind = 888263509Sdim llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName()) 889263509Sdim .Case("linker", Sema::PCK_Linker) 890263509Sdim .Case("lib", Sema::PCK_Lib) 891263509Sdim .Case("compiler", Sema::PCK_Compiler) 892263509Sdim .Case("exestr", Sema::PCK_ExeStr) 893263509Sdim .Case("user", Sema::PCK_User) 894263509Sdim .Default(Sema::PCK_Unknown); 895263509Sdim if (Kind == Sema::PCK_Unknown) { 896252723Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); 897252723Sdim return; 898252723Sdim } 899252723Sdim 900252723Sdim // Read the optional string if present. 901252723Sdim PP.Lex(Tok); 902252723Sdim std::string ArgumentString; 903252723Sdim if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, 904252723Sdim "pragma comment", 905252723Sdim /*MacroExpansion=*/true)) 906252723Sdim return; 907252723Sdim 908263509Sdim // FIXME: warn that 'exestr' is deprecated. 909252723Sdim // FIXME: If the kind is "compiler" warn if the string is present (it is 910252723Sdim // ignored). 911263509Sdim // The MSDN docs say that "lib" and "linker" require a string and have a short 912263509Sdim // whitelist of linker options they support, but in practice MSVC doesn't 913263509Sdim // issue a diagnostic. Therefore neither does clang. 914252723Sdim 915252723Sdim if (Tok.isNot(tok::r_paren)) { 916252723Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 917252723Sdim return; 918252723Sdim } 919252723Sdim PP.Lex(Tok); // eat the r_paren. 920252723Sdim 921252723Sdim if (Tok.isNot(tok::eod)) { 922252723Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 923252723Sdim return; 924252723Sdim } 925252723Sdim 926252723Sdim // If the pragma is lexically sound, notify any interested PPCallbacks. 927252723Sdim if (PP.getPPCallbacks()) 928252723Sdim PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); 929263509Sdim 930263509Sdim Actions.ActOnPragmaMSComment(Kind, ArgumentString); 931252723Sdim} 932