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