PP: Fix #1605: Paste tokens for ## through number->letter transitions.
This commit is contained in:
parent
a51d3d9f22
commit
a84079dcf3
5 changed files with 174 additions and 62 deletions
|
|
@ -84,6 +84,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sstream>
|
||||
|
||||
#include "../ParseHelper.h"
|
||||
#include "PpTokens.h"
|
||||
|
||||
/* windows only pragma */
|
||||
#ifdef _MSC_VER
|
||||
|
|
@ -212,7 +213,8 @@ public:
|
|||
virtual int scan(TPpToken*) = 0;
|
||||
virtual int getch() = 0;
|
||||
virtual void ungetch() = 0;
|
||||
virtual bool peekPasting() { return false; } // true when about to see ##
|
||||
virtual bool peekPasting() { return false; } // true when about to see ##
|
||||
virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste
|
||||
virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
|
||||
virtual bool isMacroInput() { return false; }
|
||||
|
||||
|
|
@ -263,7 +265,9 @@ public:
|
|||
snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str());
|
||||
return atom;
|
||||
}
|
||||
bool isAtom(int a) { return atom == a; }
|
||||
bool isAtom(int a) const { return atom == a; }
|
||||
int getAtom() const { return atom; }
|
||||
bool nonSpaced() const { return !space; }
|
||||
protected:
|
||||
Token() {}
|
||||
int atom;
|
||||
|
|
@ -276,6 +280,35 @@ public:
|
|||
|
||||
void putToken(int token, TPpToken* ppToken);
|
||||
bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); }
|
||||
bool peekContinuedPasting(int atom)
|
||||
{
|
||||
// This is basically necessary because, for example, the PP
|
||||
// tokenizer only accepts valid numeric-literals plus suffixes, so
|
||||
// separates numeric-literals plus bad suffix into two tokens, which
|
||||
// should get both pasted together as one token when token pasting.
|
||||
//
|
||||
// The following code is a bit more generalized than the above example.
|
||||
if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) {
|
||||
switch(stream[currentPos].getAtom()) {
|
||||
case PpAtomConstInt:
|
||||
case PpAtomConstUint:
|
||||
case PpAtomConstInt64:
|
||||
case PpAtomConstUint64:
|
||||
case PpAtomConstInt16:
|
||||
case PpAtomConstUint16:
|
||||
case PpAtomConstFloat:
|
||||
case PpAtomConstDouble:
|
||||
case PpAtomConstFloat16:
|
||||
case PpAtomConstString:
|
||||
case PpAtomIdentifier:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
int getToken(TParseContextBase&, TPpToken*);
|
||||
bool atEnd() { return currentPos >= stream.size(); }
|
||||
bool peekTokenizedPasting(bool lastTokenPastes);
|
||||
|
|
@ -344,6 +377,10 @@ protected:
|
|||
int getChar() { return inputStack.back()->getch(); }
|
||||
void ungetChar() { inputStack.back()->ungetch(); }
|
||||
bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
|
||||
bool peekContinuedPasting(int a)
|
||||
{
|
||||
return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a);
|
||||
}
|
||||
bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
|
||||
bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
|
||||
|
||||
|
|
@ -368,6 +405,7 @@ protected:
|
|||
virtual int getch() override { assert(0); return EndOfInput; }
|
||||
virtual void ungetch() override { assert(0); }
|
||||
bool peekPasting() override { return prepaste; }
|
||||
bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); }
|
||||
bool endOfReplacementList() override { return mac->body.atEnd(); }
|
||||
bool isMacroInput() override { return true; }
|
||||
|
||||
|
|
@ -442,14 +480,18 @@ protected:
|
|||
|
||||
class tTokenInput : public tInput {
|
||||
public:
|
||||
tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) : tInput(pp), tokens(t), lastTokenPastes(prepasting) { }
|
||||
tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) :
|
||||
tInput(pp),
|
||||
tokens(t),
|
||||
lastTokenPastes(prepasting) { }
|
||||
virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
|
||||
virtual int getch() override { assert(0); return EndOfInput; }
|
||||
virtual void ungetch() override { assert(0); }
|
||||
virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
|
||||
bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); }
|
||||
protected:
|
||||
TokenStream* tokens;
|
||||
bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token
|
||||
bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token
|
||||
};
|
||||
|
||||
class tUngotTokenInput : public tInput {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue