summaryrefslogtreecommitdiffstats
path: root/clang/Lex/MacroExpander.cpp
blob: 26be1cb25c58f46f94193995025bbe85a624a061 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//===--- MacroExpander.cpp - Lex from a macro expansion -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the MacroExpander interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Lex/MacroExpander.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/SourceManager.h"
using namespace llvm;
using namespace clang;

//===----------------------------------------------------------------------===//
// MacroFormalArgs Implementation
//===----------------------------------------------------------------------===//

MacroFormalArgs::MacroFormalArgs(const MacroInfo *MI) {
  assert(MI->isFunctionLike() &&
         "Can't have formal args for an object-like macro!");
  // Reserve space for arguments to avoid reallocation.
  unsigned NumArgs = MI->getNumArgs();
  if (MI->isC99Varargs() || MI->isGNUVarargs())
    NumArgs += 3;    // Varargs can have more than this, just some guess.
  
  ArgTokens.reserve(NumArgs);
}

//===----------------------------------------------------------------------===//
// MacroExpander Implementation
//===----------------------------------------------------------------------===//

MacroExpander::MacroExpander(LexerToken &Tok, MacroFormalArgs *Formals,
                             Preprocessor &pp)
  : Macro(*Tok.getIdentifierInfo()->getMacroInfo()), FormalArgs(Formals),
    PP(pp), CurToken(0),
    InstantiateLoc(Tok.getLocation()),
    AtStartOfLine(Tok.isAtStartOfLine()),
    HasLeadingSpace(Tok.hasLeadingSpace()) {
}


/// Lex - Lex and return a token from this macro stream.
///
void MacroExpander::Lex(LexerToken &Tok) {
  // Lexing off the end of the macro, pop this macro off the expansion stack.
  if (CurToken == Macro.getNumTokens())
    return PP.HandleEndOfMacro(Tok);
  
  // Get the next token to return.
  Tok = Macro.getReplacementToken(CurToken++);

  // The token's current location indicate where the token was lexed from.  We
  // need this information to compute the spelling of the token, but any
  // diagnostics for the expanded token should appear as if they came from
  // InstantiationLoc.  Pull this information together into a new SourceLocation
  // that captures all of this.
  Tok.SetLocation(PP.getSourceManager().getInstantiationLoc(Tok.getLocation(),
                                                            InstantiateLoc));

  // If this is the first token, set the lexical properties of the token to
  // match the lexical properties of the macro identifier.
  if (CurToken == 1) {
    Tok.SetFlagValue(LexerToken::StartOfLine , AtStartOfLine);
    Tok.SetFlagValue(LexerToken::LeadingSpace, HasLeadingSpace);
  }
  
  // Handle recursive expansion!
  if (Tok.getIdentifierInfo())
    return PP.HandleIdentifier(Tok);

  // Otherwise, return a normal token.
}

/// isNextTokenLParen - If the next token lexed will pop this macro off the
/// expansion stack, return 2.  If the next unexpanded token is a '(', return
/// 1, otherwise return 0.
unsigned MacroExpander::isNextTokenLParen() const {
  // Out of tokens?
  if (CurToken == Macro.getNumTokens())
    return 2;

  return Macro.getReplacementToken(CurToken).getKind() == tok::l_paren;
}
OpenPOWER on IntegriCloud