continue;
}
+ // Find out if there is a paste (##) operator before or after the token.
+ bool NonEmptyPasteBefore =
+ !ResultToks.empty() && ResultToks.back().is(tok::hashhash);
+ bool PasteBefore = i != 0 && Tokens[i-1].is(tok::hashhash);
+ bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash);
+ assert(!NonEmptyPasteBefore || PasteBefore);
+
// Otherwise, if this is not an argument token, just add the token to the
// output buffer.
IdentifierInfo *II = CurTok.getIdentifierInfo();
if (NextTokGetsSpace) {
ResultToks.back().setFlag(Token::LeadingSpace);
NextTokGetsSpace = false;
- }
+ } else if (PasteBefore && !NonEmptyPasteBefore)
+ ResultToks.back().clearFlag(Token::LeadingSpace);
+
continue;
}
// input.
MadeChange = true;
- // Otherwise, this is a use of the argument. Find out if there is a paste
- // (##) operator before or after the argument.
- bool NonEmptyPasteBefore =
- !ResultToks.empty() && ResultToks.back().is(tok::hashhash);
- bool PasteBefore = i != 0 && Tokens[i-1].is(tok::hashhash);
- bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash);
- assert(!NonEmptyPasteBefore || PasteBefore);
+ // Otherwise, this is a use of the argument.
// In Microsoft mode, remove the comma before __VA_ARGS__ to ensure there
// are no trailing commas if __VA_ARGS__ is empty.
// assembler-with-cpp mode, invalid pastes are allowed through: in this
// case, we do not want the extra whitespace to be added. For example,
// we want ". ## foo" -> ".foo" not ". foo".
- if ((CurTok.hasLeadingSpace() || NextTokGetsSpace) &&
- !NonEmptyPasteBefore)
+ if ((CurTok.hasLeadingSpace() && !PasteBefore) ||
+ (NextTokGetsSpace && !NonEmptyPasteBefore))
ResultToks[ResultToks.size()-NumToks].setFlag(Token::LeadingSpace);
NextTokGetsSpace = false;
// 6.10.3.3p2,3) calls for a bunch of placemarker stuff to occur. We
// implement this by eating ## operators when a LHS or RHS expands to
// empty.
- NextTokGetsSpace |= CurTok.hasLeadingSpace();
+ if (!PasteBefore)
+ NextTokGetsSpace |= i != 0 && CurTok.hasLeadingSpace();
if (PasteAfter) {
// Discard the argument token and skip (don't copy to the expansion
// buffer) the paste operator after it.
- NextTokGetsSpace |= Tokens[i+1].hasLeadingSpace();
++i;
continue;
}
assert(PasteBefore);
if (NonEmptyPasteBefore) {
assert(ResultToks.back().is(tok::hashhash));
- NextTokGetsSpace |= ResultToks.pop_back_val().hasLeadingSpace();
+ ResultToks.pop_back();
}
// If this is the __VA_ARGS__ token, and if the argument wasn't provided,
// RUN: %clang_cc1 %s -E | grep 'V);'
// RUN: %clang_cc1 %s -E | grep 'W, 1, 2);'
// RUN: %clang_cc1 %s -E | grep 'X, 1, 2);'
-// RUN: %clang_cc1 %s -E | grep 'Y, );'
-// RUN: %clang_cc1 %s -E | grep 'Z, );'
+// RUN: %clang_cc1 %s -E | grep 'Y,);'
+// RUN: %clang_cc1 %s -E | grep 'Z,);'
#define debug(format, ...) format, ## __VA_ARGS__)
debug(V);
-// RUN: %clang_cc1 %s -E | grep "^xy$"
+// RUN: %clang_cc1 -E %s | FileCheck --strict-whitespace %s
#define A x ## y
blah
A
+// CHECK: {{^}}xy{{$}}
+#define B(x, y) [v ## w] [ v##w] [v##w ] [w ## x] [ w##x] [w##x ] [x ## y] [ x##y] [x##y ] [y ## z] [ y##z] [y##z ]
+B(x,y)
+// CHECK: [vw] [ vw] [vw ] [wx] [ wx] [wx ] [xy] [ xy] [xy ] [yz] [ yz] [yz ]
+B(x,)
+// CHECK: [vw] [ vw] [vw ] [wx] [ wx] [wx ] [x] [ x] [x ] [z] [ z] [z ]
+B(,y)
+// CHECK: [vw] [ vw] [vw ] [w] [ w] [w ] [y] [ y] [y ] [yz] [ yz] [yz ]
+B(,)
+// CHECK: [vw] [ vw] [vw ] [w] [ w] [w ] [] [ ] [ ] [z] [ z] [z ]
+
+#define C(x, y, z) [x ## y ## z]
+C(,,) C(a,,) C(,b,) C(,,c) C(a,b,) C(a,,c) C(,b,c) C(a,b,c)
+// CHECK: [] [a] [b] [c] [ab] [ac] [bc] [abc]