diff options
author | Faisal Vali <faisalv@yahoo.com> | 2017-10-15 01:26:26 +0000 |
---|---|---|
committer | Faisal Vali <faisalv@yahoo.com> | 2017-10-15 01:26:26 +0000 |
commit | 1826842865f1a7db9417819dca1151705464b7f7 (patch) | |
tree | 23f9e4a513e7ec93d24df387f96a7d941633decd /clang/lib/Lex/Preprocessor.cpp | |
parent | 76067588dc7a9e98e2f481c380deceac3579eb65 (diff) | |
download | bcm5719-llvm-1826842865f1a7db9417819dca1151705464b7f7.tar.gz bcm5719-llvm-1826842865f1a7db9417819dca1151705464b7f7.zip |
[c++2a] Implement P0306 __VA_OPT__ (Comma omission and comma deletion)
This patch implements an extension to the preprocessor:
__VA_OPT__(contents) --> which expands into its contents if variadic arguments are supplied to the parent macro, or behaves as an empty token if none.
- Currently this feature is only enabled for C++2a (this could be enabled, with some careful tweaks, for other dialects with the appropriate extension or compatibility warnings)
- The patch was reviewed here: https://reviews.llvm.org/D35782 and asides from the above (and moving some of the definition and expansion recognition logic into the corresponding state machines), I believe I incorporated all of Richard's suggestions.
A few technicalities (most of which were clarified through private correspondence between rsmith, hubert and thomas) are worth mentioning. Given:
#define F(a,...) a #__VA_OPT__(a ## a) a ## __VA_OPT__(__VA_ARGS__)
- The call F(,) Does not supply any tokens for the variadic arguments and hence VA_OPT behaves as a placeholder.
- When expanding VA_OPT (for e.g. F(,1) token pasting occurs eagerly within its contents if the contents need to be stringified.
- A hash or a hashhash prior to VA_OPT does not inhibit expansion of arguments if they are the first token within VA_OPT.
- When a variadic argument is supplied, argument substitution occurs within the contents as does stringification - and these resulting tokens are inserted back into the macro expansions token stream just prior to the entire stream being rescanned and concatenated.
See wg21.link/P0306 for further details on the feature.
Acknowledgment: This patch would have been poorer if not for Richard Smith's usual thoughtful analysis and feedback.
llvm-svn: 315840
Diffstat (limited to 'clang/lib/Lex/Preprocessor.cpp')
-rw-r--r-- | clang/lib/Lex/Preprocessor.cpp | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 1f9a469bc59..65df6a57f1d 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -121,12 +121,18 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, // We haven't read anything from the external source. ReadMacrosFromExternalSource = false; - - // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. - // This gets unpoisoned where it is allowed. + + // "Poison" __VA_ARGS__, __VA_OPT__ which can only appear in the expansion of + // a macro. They get unpoisoned where it is allowed. (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); - + if (getLangOpts().CPlusPlus2a) { + (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); + } else { + Ident__VA_OPT__ = nullptr; + } + // Initialize the pragma handlers. RegisterBuiltinPragmas(); @@ -667,13 +673,15 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { // unpoisoned it if we're defining a C99 macro. if (II.isOutOfDate()) { bool CurrentIsPoisoned = false; - if (&II == Ident__VA_ARGS__) - CurrentIsPoisoned = Ident__VA_ARGS__->isPoisoned(); + const bool IsSpecialVariadicMacro = + &II == Ident__VA_ARGS__ || &II == Ident__VA_OPT__; + if (IsSpecialVariadicMacro) + CurrentIsPoisoned = II.isPoisoned(); updateOutOfDateIdentifier(II); Identifier.setKind(II.getTokenID()); - if (&II == Ident__VA_ARGS__) + if (IsSpecialVariadicMacro) II.setIsPoisoned(CurrentIsPoisoned); } |