PP: Faithfully track white-space through macro record/use, fixing bugs:

This fixes the comparison in macro body redefinitions, where initial
white-space differences do not matter, but internal white-space differences
do matter.
This commit is contained in:
John Kessenich 2019-02-19 03:12:02 -07:00
Родитель 5cdf3c5a23
Коммит 6225dd4ba1
2 изменённых файлов: 28 добавлений и 11 удалений

Просмотреть файл

@ -166,29 +166,43 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
if (existing != nullptr) {
if (! existing->undef) {
// Already defined -- need to make sure they are identical:
// "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
// ordering, spelling, and white-space separation, where all white-space separations are considered identical."
if (existing->functionLike != mac.functionLike)
parseContext.ppError(defineLoc, "Macro redefined; function-like versus object-like:", "#define", atomStrings.getString(defAtom));
else if (existing->args.size() != mac.args.size())
parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom));
else {
if (existing->args != mac.args)
parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define", atomStrings.getString(defAtom));
// "Two replacement lists are identical if and only if the
// preprocessing tokens in both have the same number,
// ordering, spelling, and white-space separation, where all
// white-space separations are considered identical."
if (existing->functionLike != mac.functionLike) {
parseContext.ppError(defineLoc, "Macro redefined; function-like versus object-like:", "#define",
atomStrings.getString(defAtom));
} else if (existing->args.size() != mac.args.size()) {
parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define",
atomStrings.getString(defAtom));
} else {
if (existing->args != mac.args) {
parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define",
atomStrings.getString(defAtom));
}
// set up to compare the two
existing->body.reset();
mac.body.reset();
int newToken;
bool firstToken = true;
do {
int oldToken;
TPpToken oldPpToken;
TPpToken newPpToken;
oldToken = existing->body.getToken(parseContext, &oldPpToken);
newToken = mac.body.getToken(parseContext, &newPpToken);
// for the first token, preceding spaces don't matter
if (firstToken) {
newPpToken.space = oldPpToken.space;
firstToken = false;
}
if (oldToken != newToken || oldPpToken != newPpToken) {
parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define", atomStrings.getString(defAtom));
parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define",
atomStrings.getString(defAtom));
break;
}
} while (newToken > 0);
} while (newToken != EndOfInput);
}
}
*existing = mac;

Просмотреть файл

@ -252,11 +252,13 @@ public:
public:
Token(int atom, const TPpToken& ppToken) :
atom(atom),
space(ppToken.space),
i64val(ppToken.i64val),
name(ppToken.name) { }
int get(TPpToken& ppToken)
{
ppToken.clear();
ppToken.space = space;
ppToken.i64val = i64val;
snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str());
return atom;
@ -265,6 +267,7 @@ public:
protected:
Token() {}
int atom;
bool space; // did a space precede the token?
long long i64val;
TString name;
};