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" 15249423Sdim#include "clang/Lex/Preprocessor.h" 16193326Sed#include "clang/Parse/ParseDiagnostic.h" 17212904Sdim#include "clang/Parse/Parser.h" 18251662Sdim#include "clang/Sema/Scope.h" 19251662Sdim#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 34234353Sdimvoid Parser::HandlePragmaVisibility() { 35234353Sdim assert(Tok.is(tok::annot_pragma_vis)); 36234353Sdim const IdentifierInfo *VisType = 37234353Sdim static_cast<IdentifierInfo *>(Tok.getAnnotationValue()); 38234353Sdim SourceLocation VisLoc = ConsumeToken(); 39234353Sdim Actions.ActOnPragmaVisibility(VisType, VisLoc); 40234353Sdim} 41234353Sdim 42234353Sdimstruct PragmaPackInfo { 43234353Sdim Sema::PragmaPackKind Kind; 44234353Sdim IdentifierInfo *Name; 45243830Sdim Token Alignment; 46234353Sdim SourceLocation LParenLoc; 47234353Sdim SourceLocation RParenLoc; 48234353Sdim}; 49234353Sdim 50234353Sdimvoid Parser::HandlePragmaPack() { 51234353Sdim assert(Tok.is(tok::annot_pragma_pack)); 52234353Sdim PragmaPackInfo *Info = 53234353Sdim static_cast<PragmaPackInfo *>(Tok.getAnnotationValue()); 54234353Sdim SourceLocation PragmaLoc = ConsumeToken(); 55243830Sdim ExprResult Alignment; 56243830Sdim if (Info->Alignment.is(tok::numeric_constant)) { 57243830Sdim Alignment = Actions.ActOnNumericConstant(Info->Alignment); 58243830Sdim if (Alignment.isInvalid()) 59243830Sdim return; 60243830Sdim } 61243830Sdim Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc, 62234353Sdim Info->LParenLoc, Info->RParenLoc); 63234353Sdim} 64234353Sdim 65243830Sdimvoid Parser::HandlePragmaMSStruct() { 66243830Sdim assert(Tok.is(tok::annot_pragma_msstruct)); 67243830Sdim Sema::PragmaMSStructKind Kind = 68243830Sdim static_cast<Sema::PragmaMSStructKind>( 69243830Sdim reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 70243830Sdim Actions.ActOnPragmaMSStruct(Kind); 71243830Sdim ConsumeToken(); // The annotation token. 72243830Sdim} 73243830Sdim 74243830Sdimvoid Parser::HandlePragmaAlign() { 75243830Sdim assert(Tok.is(tok::annot_pragma_align)); 76243830Sdim Sema::PragmaOptionsAlignKind Kind = 77243830Sdim static_cast<Sema::PragmaOptionsAlignKind>( 78243830Sdim reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 79243830Sdim SourceLocation PragmaLoc = ConsumeToken(); 80243830Sdim Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); 81243830Sdim} 82243830Sdim 83243830Sdimvoid Parser::HandlePragmaWeak() { 84243830Sdim assert(Tok.is(tok::annot_pragma_weak)); 85243830Sdim SourceLocation PragmaLoc = ConsumeToken(); 86243830Sdim Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc, 87243830Sdim Tok.getLocation()); 88243830Sdim ConsumeToken(); // The weak name. 89243830Sdim} 90243830Sdim 91243830Sdimvoid Parser::HandlePragmaWeakAlias() { 92243830Sdim assert(Tok.is(tok::annot_pragma_weakalias)); 93243830Sdim SourceLocation PragmaLoc = ConsumeToken(); 94243830Sdim IdentifierInfo *WeakName = Tok.getIdentifierInfo(); 95243830Sdim SourceLocation WeakNameLoc = Tok.getLocation(); 96243830Sdim ConsumeToken(); 97243830Sdim IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 98243830Sdim SourceLocation AliasNameLoc = Tok.getLocation(); 99243830Sdim ConsumeToken(); 100243830Sdim Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc, 101243830Sdim WeakNameLoc, AliasNameLoc); 102243830Sdim 103243830Sdim} 104243830Sdim 105243830Sdimvoid Parser::HandlePragmaRedefineExtname() { 106243830Sdim assert(Tok.is(tok::annot_pragma_redefine_extname)); 107243830Sdim SourceLocation RedefLoc = ConsumeToken(); 108243830Sdim IdentifierInfo *RedefName = Tok.getIdentifierInfo(); 109243830Sdim SourceLocation RedefNameLoc = Tok.getLocation(); 110243830Sdim ConsumeToken(); 111243830Sdim IdentifierInfo *AliasName = Tok.getIdentifierInfo(); 112243830Sdim SourceLocation AliasNameLoc = Tok.getLocation(); 113243830Sdim ConsumeToken(); 114243830Sdim Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc, 115243830Sdim RedefNameLoc, AliasNameLoc); 116243830Sdim} 117243830Sdim 118243830Sdimvoid Parser::HandlePragmaFPContract() { 119243830Sdim assert(Tok.is(tok::annot_pragma_fp_contract)); 120243830Sdim tok::OnOffSwitch OOS = 121243830Sdim static_cast<tok::OnOffSwitch>( 122243830Sdim reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); 123243830Sdim Actions.ActOnPragmaFPContract(OOS); 124243830Sdim ConsumeToken(); // The annotation token. 125243830Sdim} 126243830Sdim 127251662SdimStmtResult Parser::HandlePragmaCaptured() 128251662Sdim{ 129251662Sdim assert(Tok.is(tok::annot_pragma_captured)); 130251662Sdim ConsumeToken(); 131251662Sdim 132251662Sdim if (Tok.isNot(tok::l_brace)) { 133251662Sdim PP.Diag(Tok, diag::err_expected_lbrace); 134251662Sdim return StmtError(); 135251662Sdim } 136251662Sdim 137251662Sdim SourceLocation Loc = Tok.getLocation(); 138251662Sdim 139251662Sdim ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope); 140251662Sdim Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 141251662Sdim /*NumParams=*/1); 142251662Sdim 143251662Sdim StmtResult R = ParseCompoundStatement(); 144251662Sdim CapturedRegionScope.Exit(); 145251662Sdim 146251662Sdim if (R.isInvalid()) { 147251662Sdim Actions.ActOnCapturedRegionError(); 148251662Sdim return StmtError(); 149251662Sdim } 150251662Sdim 151251662Sdim return Actions.ActOnCapturedRegionEnd(R.get()); 152251662Sdim} 153251662Sdim 154243830Sdimnamespace { 155243830Sdim typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData; 156243830Sdim} 157243830Sdim 158243830Sdimvoid Parser::HandlePragmaOpenCLExtension() { 159243830Sdim assert(Tok.is(tok::annot_pragma_opencl_extension)); 160243830Sdim OpenCLExtData data = 161243830Sdim OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue()); 162243830Sdim unsigned state = data.getInt(); 163243830Sdim IdentifierInfo *ename = data.getPointer(); 164243830Sdim SourceLocation NameLoc = Tok.getLocation(); 165243830Sdim ConsumeToken(); // The annotation token. 166243830Sdim 167243830Sdim OpenCLOptions &f = Actions.getOpenCLOptions(); 168243830Sdim // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions, 169243830Sdim // overriding all previously issued extension directives, but only if the 170243830Sdim // behavior is set to disable." 171243830Sdim if (state == 0 && ename->isStr("all")) { 172243830Sdim#define OPENCLEXT(nm) f.nm = 0; 173243830Sdim#include "clang/Basic/OpenCLExtensions.def" 174243830Sdim } 175243830Sdim#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; } 176243830Sdim#include "clang/Basic/OpenCLExtensions.def" 177243830Sdim else { 178243830Sdim PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename; 179243830Sdim return; 180243830Sdim } 181243830Sdim} 182243830Sdim 183251662Sdim 184251662Sdim 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; 194226633Sdim 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")) { 202226633Sdim 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 } 208226633Sdim 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 } 215226633Sdim 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 } 226226633Sdim 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 233234353Sdim Token *Toks = new Token[1]; 234234353Sdim Toks[0].startToken(); 235234353Sdim Toks[0].setKind(tok::annot_pragma_vis); 236234353Sdim Toks[0].setLocation(VisLoc); 237234353Sdim Toks[0].setAnnotationValue( 238234353Sdim const_cast<void*>(static_cast<const void*>(VisType))); 239234353Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 240234353Sdim /*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; 261243830Sdim Token Alignment; 262243830Sdim Alignment.startToken(); 263193326Sed SourceLocation LParenLoc = Tok.getLocation(); 264198092Srdivacky PP.Lex(Tok); 265193326Sed if (Tok.is(tok::numeric_constant)) { 266243830Sdim Alignment = Tok; 267193326Sed 268193326Sed PP.Lex(Tok); 269234353Sdim 270234353Sdim // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting 271234353Sdim // the push/pop stack. 272234353Sdim // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4) 273234353Sdim if (PP.getLangOpts().ApplePragmaPack) 274234353Sdim 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)) { 295243830Sdim 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 310243830Sdim 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 } 320234353Sdim } else if (PP.getLangOpts().ApplePragmaPack) { 321234353Sdim // In MSVC/gcc, #pragma pack() resets the alignment without affecting 322234353Sdim // the push/pop stack. 323234353Sdim // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop). 324234353Sdim 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 339234353Sdim PragmaPackInfo *Info = 340234353Sdim (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate( 341234353Sdim sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>()); 342234353Sdim new (Info) PragmaPackInfo(); 343234353Sdim Info->Kind = Kind; 344234353Sdim Info->Name = Name; 345243830Sdim Info->Alignment = Alignment; 346234353Sdim Info->LParenLoc = LParenLoc; 347234353Sdim Info->RParenLoc = RParenLoc; 348234353Sdim 349234353Sdim Token *Toks = 350234353Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 351234353Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 352234353Sdim new (Toks) Token(); 353234353Sdim Toks[0].startToken(); 354234353Sdim Toks[0].setKind(tok::annot_pragma_pack); 355234353Sdim Toks[0].setLocation(PackLoc); 356234353Sdim Toks[0].setAnnotationValue(static_cast<void*>(Info)); 357234353Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 358234353Sdim /*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)) { 387234353Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) 388234353Sdim << "ms_struct"; 389221345Sdim return; 390221345Sdim } 391243830Sdim 392243830Sdim Token *Toks = 393243830Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 394243830Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 395243830Sdim new (Toks) Token(); 396243830Sdim Toks[0].startToken(); 397243830Sdim Toks[0].setKind(tok::annot_pragma_msstruct); 398243830Sdim Toks[0].setLocation(MSStructTok.getLocation()); 399243830Sdim Toks[0].setAnnotationValue(reinterpret_cast<void*>( 400243830Sdim static_cast<uintptr_t>(Kind))); 401243830Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 402243830Sdim /*OwnsTokens=*/false); 403221345Sdim} 404221345Sdim 405212904Sdim// #pragma 'align' '=' {'native','natural','mac68k','power','reset'} 406212904Sdim// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'} 407243830Sdimstatic 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 461243830Sdim Token *Toks = 462243830Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 463243830Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 464243830Sdim new (Toks) Token(); 465243830Sdim Toks[0].startToken(); 466243830Sdim Toks[0].setKind(tok::annot_pragma_align); 467243830Sdim Toks[0].setLocation(FirstTok.getLocation()); 468243830Sdim Toks[0].setAnnotationValue(reinterpret_cast<void*>( 469243830Sdim static_cast<uintptr_t>(Kind))); 470243830Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 471243830Sdim /*OwnsTokens=*/false); 472208600Srdivacky} 473208600Srdivacky 474218893Sdimvoid PragmaAlignHandler::HandlePragma(Preprocessor &PP, 475218893Sdim PragmaIntroducerKind Introducer, 476218893Sdim Token &AlignTok) { 477243830Sdim ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false); 478212904Sdim} 479212904Sdim 480218893Sdimvoid PragmaOptionsHandler::HandlePragma(Preprocessor &PP, 481218893Sdim PragmaIntroducerKind Introducer, 482218893Sdim Token &OptionsTok) { 483243830Sdim 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). 502226633Sdim 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 553234353Sdim Token *Toks = 554234353Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 555234353Sdim 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 } 563234353Sdim PP.EnterTokenStream(Toks, 2*Identifiers.size(), 564234353Sdim /*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 581243830Sdim Token WeakName = Tok; 582243830Sdim bool HasAlias = false; 583243830Sdim Token AliasName; 584193576Sed 585193576Sed PP.Lex(Tok); 586193576Sed if (Tok.is(tok::equal)) { 587243830Sdim 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 } 594243830Sdim 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 603243830Sdim if (HasAlias) { 604243830Sdim Token *Toks = 605243830Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 606243830Sdim sizeof(Token) * 3, llvm::alignOf<Token>()); 607243830Sdim Token &pragmaUnusedTok = Toks[0]; 608243830Sdim pragmaUnusedTok.startToken(); 609243830Sdim pragmaUnusedTok.setKind(tok::annot_pragma_weakalias); 610243830Sdim pragmaUnusedTok.setLocation(WeakLoc); 611243830Sdim Toks[1] = WeakName; 612243830Sdim Toks[2] = AliasName; 613243830Sdim PP.EnterTokenStream(Toks, 3, 614243830Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 615193576Sed } else { 616243830Sdim Token *Toks = 617243830Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 618243830Sdim sizeof(Token) * 2, llvm::alignOf<Token>()); 619243830Sdim Token &pragmaUnusedTok = Toks[0]; 620243830Sdim pragmaUnusedTok.startToken(); 621243830Sdim pragmaUnusedTok.setKind(tok::annot_pragma_weak); 622243830Sdim pragmaUnusedTok.setLocation(WeakLoc); 623243830Sdim Toks[1] = WeakName; 624243830Sdim PP.EnterTokenStream(Toks, 2, 625243830Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 626193576Sed } 627193576Sed} 628218893Sdim 629234353Sdim// #pragma redefine_extname identifier identifier 630234353Sdimvoid PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP, 631234353Sdim PragmaIntroducerKind Introducer, 632234353Sdim Token &RedefToken) { 633234353Sdim SourceLocation RedefLoc = RedefToken.getLocation(); 634234353Sdim 635234353Sdim Token Tok; 636234353Sdim PP.Lex(Tok); 637234353Sdim if (Tok.isNot(tok::identifier)) { 638234353Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << 639234353Sdim "redefine_extname"; 640234353Sdim return; 641234353Sdim } 642234353Sdim 643243830Sdim Token RedefName = Tok; 644243830Sdim PP.Lex(Tok); 645234353Sdim 646234353Sdim if (Tok.isNot(tok::identifier)) { 647234353Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) 648234353Sdim << "redefine_extname"; 649234353Sdim return; 650234353Sdim } 651243830Sdim 652243830Sdim Token AliasName = Tok; 653234353Sdim PP.Lex(Tok); 654234353Sdim 655234353Sdim if (Tok.isNot(tok::eod)) { 656234353Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 657234353Sdim "redefine_extname"; 658234353Sdim return; 659234353Sdim } 660234353Sdim 661243830Sdim Token *Toks = 662243830Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 663243830Sdim sizeof(Token) * 3, llvm::alignOf<Token>()); 664243830Sdim Token &pragmaRedefTok = Toks[0]; 665243830Sdim pragmaRedefTok.startToken(); 666243830Sdim pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname); 667243830Sdim pragmaRedefTok.setLocation(RedefLoc); 668243830Sdim Toks[1] = RedefName; 669243830Sdim Toks[2] = AliasName; 670243830Sdim PP.EnterTokenStream(Toks, 3, 671243830Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false); 672234353Sdim} 673234353Sdim 674234353Sdim 675218893Sdimvoid 676218893SdimPragmaFPContractHandler::HandlePragma(Preprocessor &PP, 677218893Sdim PragmaIntroducerKind Introducer, 678218893Sdim Token &Tok) { 679218893Sdim tok::OnOffSwitch OOS; 680218893Sdim if (PP.LexOnOffSwitch(OOS)) 681218893Sdim return; 682218893Sdim 683243830Sdim Token *Toks = 684243830Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 685243830Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 686243830Sdim new (Toks) Token(); 687243830Sdim Toks[0].startToken(); 688243830Sdim Toks[0].setKind(tok::annot_pragma_fp_contract); 689243830Sdim Toks[0].setLocation(Tok.getLocation()); 690243830Sdim Toks[0].setAnnotationValue(reinterpret_cast<void*>( 691243830Sdim static_cast<uintptr_t>(OOS))); 692243830Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 693243830Sdim /*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 } 731263508Sdim SourceLocation StateLoc = Tok.getLocation(); 732218893Sdim 733243830Sdim PP.Lex(Tok); 734243830Sdim if (Tok.isNot(tok::eod)) { 735243830Sdim PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << 736243830Sdim "OPENCL EXTENSION"; 737218893Sdim return; 738218893Sdim } 739243830Sdim 740243830Sdim OpenCLExtData data(ename, state); 741243830Sdim Token *Toks = 742243830Sdim (Token*) PP.getPreprocessorAllocator().Allocate( 743243830Sdim sizeof(Token) * 1, llvm::alignOf<Token>()); 744243830Sdim new (Toks) Token(); 745243830Sdim Toks[0].startToken(); 746243830Sdim Toks[0].setKind(tok::annot_pragma_opencl_extension); 747243830Sdim Toks[0].setLocation(NameLoc); 748243830Sdim Toks[0].setAnnotationValue(data.getOpaqueValue()); 749243830Sdim PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, 750243830Sdim /*OwnsTokens=*/false); 751263508Sdim 752263508Sdim if (PP.getPPCallbacks()) 753263508Sdim PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename, 754263508Sdim StateLoc, state); 755218893Sdim} 756218893Sdim 757249423Sdim/// \brief Handle '#pragma omp ...' when OpenMP is disabled. 758249423Sdim/// 759249423Sdimvoid 760249423SdimPragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, 761249423Sdim PragmaIntroducerKind Introducer, 762249423Sdim Token &FirstTok) { 763249423Sdim if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored, 764249423Sdim FirstTok.getLocation()) != 765249423Sdim DiagnosticsEngine::Ignored) { 766249423Sdim PP.Diag(FirstTok, diag::warn_pragma_omp_ignored); 767249423Sdim PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored, 768249423Sdim diag::MAP_IGNORE, 769249423Sdim SourceLocation()); 770249423Sdim } 771249423Sdim PP.DiscardUntilEndOfDirective(); 772249423Sdim} 773249423Sdim 774249423Sdim/// \brief Handle '#pragma omp ...' when OpenMP is enabled. 775249423Sdim/// 776249423Sdimvoid 777249423SdimPragmaOpenMPHandler::HandlePragma(Preprocessor &PP, 778249423Sdim PragmaIntroducerKind Introducer, 779249423Sdim Token &FirstTok) { 780249423Sdim SmallVector<Token, 16> Pragma; 781249423Sdim Token Tok; 782249423Sdim Tok.startToken(); 783249423Sdim Tok.setKind(tok::annot_pragma_openmp); 784249423Sdim Tok.setLocation(FirstTok.getLocation()); 785249423Sdim 786249423Sdim while (Tok.isNot(tok::eod)) { 787249423Sdim Pragma.push_back(Tok); 788249423Sdim PP.Lex(Tok); 789249423Sdim } 790249423Sdim SourceLocation EodLoc = Tok.getLocation(); 791249423Sdim Tok.startToken(); 792249423Sdim Tok.setKind(tok::annot_pragma_openmp_end); 793249423Sdim Tok.setLocation(EodLoc); 794249423Sdim Pragma.push_back(Tok); 795249423Sdim 796249423Sdim Token *Toks = new Token[Pragma.size()]; 797249423Sdim std::copy(Pragma.begin(), Pragma.end(), Toks); 798249423Sdim PP.EnterTokenStream(Toks, Pragma.size(), 799249423Sdim /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true); 800249423Sdim} 801251662Sdim 802263508Sdim/// \brief Handle the Microsoft \#pragma detect_mismatch extension. 803263508Sdim/// 804263508Sdim/// The syntax is: 805263508Sdim/// \code 806263508Sdim/// #pragma detect_mismatch("name", "value") 807263508Sdim/// \endcode 808263508Sdim/// Where 'name' and 'value' are quoted strings. The values are embedded in 809263508Sdim/// the object file and passed along to the linker. If the linker detects a 810263508Sdim/// mismatch in the object file's values for the given name, a LNK2038 error 811263508Sdim/// is emitted. See MSDN for more details. 812263508Sdimvoid PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, 813263508Sdim PragmaIntroducerKind Introducer, 814263508Sdim Token &Tok) { 815263508Sdim SourceLocation CommentLoc = Tok.getLocation(); 816263508Sdim PP.Lex(Tok); 817263508Sdim if (Tok.isNot(tok::l_paren)) { 818263508Sdim PP.Diag(CommentLoc, diag::err_expected_lparen); 819263508Sdim return; 820263508Sdim } 821263508Sdim 822263508Sdim // Read the name to embed, which must be a string literal. 823263508Sdim std::string NameString; 824263508Sdim if (!PP.LexStringLiteral(Tok, NameString, 825263508Sdim "pragma detect_mismatch", 826263508Sdim /*MacroExpansion=*/true)) 827263508Sdim return; 828263508Sdim 829263508Sdim // Read the comma followed by a second string literal. 830263508Sdim std::string ValueString; 831263508Sdim if (Tok.isNot(tok::comma)) { 832263508Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 833263508Sdim return; 834263508Sdim } 835263508Sdim 836263508Sdim if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", 837263508Sdim /*MacroExpansion=*/true)) 838263508Sdim return; 839263508Sdim 840263508Sdim if (Tok.isNot(tok::r_paren)) { 841263508Sdim PP.Diag(Tok.getLocation(), diag::err_expected_rparen); 842263508Sdim return; 843263508Sdim } 844263508Sdim PP.Lex(Tok); // Eat the r_paren. 845263508Sdim 846263508Sdim if (Tok.isNot(tok::eod)) { 847263508Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed); 848263508Sdim return; 849263508Sdim } 850263508Sdim 851263508Sdim // If the pragma is lexically sound, notify any interested PPCallbacks. 852263508Sdim if (PP.getPPCallbacks()) 853263508Sdim PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString, 854263508Sdim ValueString); 855263508Sdim 856263508Sdim Actions.ActOnPragmaDetectMismatch(NameString, ValueString); 857263508Sdim} 858263508Sdim 859251662Sdim/// \brief Handle the microsoft \#pragma comment extension. 860251662Sdim/// 861251662Sdim/// The syntax is: 862251662Sdim/// \code 863251662Sdim/// #pragma comment(linker, "foo") 864251662Sdim/// \endcode 865251662Sdim/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user. 866251662Sdim/// "foo" is a string, which is fully macro expanded, and permits string 867251662Sdim/// concatenation, embedded escape characters etc. See MSDN for more details. 868251662Sdimvoid PragmaCommentHandler::HandlePragma(Preprocessor &PP, 869251662Sdim PragmaIntroducerKind Introducer, 870251662Sdim Token &Tok) { 871251662Sdim SourceLocation CommentLoc = Tok.getLocation(); 872251662Sdim PP.Lex(Tok); 873251662Sdim if (Tok.isNot(tok::l_paren)) { 874251662Sdim PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 875251662Sdim return; 876251662Sdim } 877251662Sdim 878251662Sdim // Read the identifier. 879251662Sdim PP.Lex(Tok); 880251662Sdim if (Tok.isNot(tok::identifier)) { 881251662Sdim PP.Diag(CommentLoc, diag::err_pragma_comment_malformed); 882251662Sdim return; 883251662Sdim } 884251662Sdim 885251662Sdim // Verify that this is one of the 5 whitelisted options. 886263508Sdim IdentifierInfo *II = Tok.getIdentifierInfo(); 887263508Sdim Sema::PragmaMSCommentKind Kind = 888263508Sdim llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName()) 889263508Sdim .Case("linker", Sema::PCK_Linker) 890263508Sdim .Case("lib", Sema::PCK_Lib) 891263508Sdim .Case("compiler", Sema::PCK_Compiler) 892263508Sdim .Case("exestr", Sema::PCK_ExeStr) 893263508Sdim .Case("user", Sema::PCK_User) 894263508Sdim .Default(Sema::PCK_Unknown); 895263508Sdim if (Kind == Sema::PCK_Unknown) { 896251662Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind); 897251662Sdim return; 898251662Sdim } 899251662Sdim 900251662Sdim // Read the optional string if present. 901251662Sdim PP.Lex(Tok); 902251662Sdim std::string ArgumentString; 903251662Sdim if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, 904251662Sdim "pragma comment", 905251662Sdim /*MacroExpansion=*/true)) 906251662Sdim return; 907251662Sdim 908263508Sdim // FIXME: warn that 'exestr' is deprecated. 909251662Sdim // FIXME: If the kind is "compiler" warn if the string is present (it is 910251662Sdim // ignored). 911263508Sdim // The MSDN docs say that "lib" and "linker" require a string and have a short 912263508Sdim // whitelist of linker options they support, but in practice MSVC doesn't 913263508Sdim // issue a diagnostic. Therefore neither does clang. 914251662Sdim 915251662Sdim if (Tok.isNot(tok::r_paren)) { 916251662Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 917251662Sdim return; 918251662Sdim } 919251662Sdim PP.Lex(Tok); // eat the r_paren. 920251662Sdim 921251662Sdim if (Tok.isNot(tok::eod)) { 922251662Sdim PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed); 923251662Sdim return; 924251662Sdim } 925251662Sdim 926251662Sdim // If the pragma is lexically sound, notify any interested PPCallbacks. 927251662Sdim if (PP.getPPCallbacks()) 928251662Sdim PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString); 929263508Sdim 930263508Sdim Actions.ActOnPragmaMSComment(Kind, ArgumentString); 931251662Sdim} 932