Author: faisalv Date: Mon Jul 24 20:15:36 2017 New Revision: 308948 URL: http://llvm.org/viewvc/llvm-project?rev=308948&view=rev Log: [NFC] Use RAII to un-poison and then re-poison __VA_ARGS__ - This will also be used for the forthcoming __VA_OPT__ feature approved for C++2a. - recommended by rsmith during his review of the __VA_OPT__ patch (https://reviews.llvm.org/D35782)
Added: cfe/trunk/include/clang/Lex/VariadicMacroSupport.h Modified: cfe/trunk/include/clang/Lex/Preprocessor.h cfe/trunk/lib/Lex/PPDirectives.cpp Modified: cfe/trunk/include/clang/Lex/Preprocessor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=308948&r1=308947&r2=308948&view=diff ============================================================================== --- cfe/trunk/include/clang/Lex/Preprocessor.h (original) +++ cfe/trunk/include/clang/Lex/Preprocessor.h Mon Jul 24 20:15:36 2017 @@ -96,6 +96,7 @@ enum MacroUse { /// know anything about preprocessor-level issues like the \#include stack, /// token expansion, etc. class Preprocessor { + friend class VariadicMacroScopeGuard; std::shared_ptr<PreprocessorOptions> PPOpts; DiagnosticsEngine *Diags; LangOptions &LangOpts; Added: cfe/trunk/include/clang/Lex/VariadicMacroSupport.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/VariadicMacroSupport.h?rev=308948&view=auto ============================================================================== --- cfe/trunk/include/clang/Lex/VariadicMacroSupport.h (added) +++ cfe/trunk/include/clang/Lex/VariadicMacroSupport.h Mon Jul 24 20:15:36 2017 @@ -0,0 +1,56 @@ +//===- VariadicMacroSupport.h - scope-guards etc. -*- C++ -*---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines support types to help with preprocessing variadic macro +// (i.e. macros that use: ellipses __VA_ARGS__ ) definitions and +// expansions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H +#define LLVM_CLANG_LEX_VARIADICMACROSUPPORT_H + +#include "clang/Lex/Preprocessor.h" + +namespace clang { + +/// An RAII class that tracks when the Preprocessor starts and stops lexing the +/// definition of a (ISO C/C++) variadic macro. As an example, this is useful +/// for unpoisoning and repoisoning certain identifiers (such as __VA_ARGS__) +/// that are only allowed in this context. Also, being a friend of the +/// Preprocessor class allows it to access PP's cached identifiers directly (as +/// opposed to performing a lookup each time). +class VariadicMacroScopeGuard { + const Preprocessor &PP; + IdentifierInfo &Ident__VA_ARGS__; + +public: + VariadicMacroScopeGuard(const Preprocessor &P) + : PP(P), Ident__VA_ARGS__(*PP.Ident__VA_ARGS__) { + assert(Ident__VA_ARGS__.isPoisoned() && "__VA_ARGS__ should be poisoned " + "outside an ISO C/C++ variadic " + "macro definition!"); + } + + /// Client code should call this function just before the Preprocessor is + /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro. + void enterScope() { Ident__VA_ARGS__.setIsPoisoned(false); } + + /// Client code should call this function as soon as the Preprocessor has + /// either completed lexing the macro's definition tokens, or an error occured + /// and the context is being exited. This function is idempotent (might be + /// explicitly called, and then reinvoked via the destructor). + void exitScope() { Ident__VA_ARGS__.setIsPoisoned(true); } + + ~VariadicMacroScopeGuard() { exitScope(); } +}; + +} // end namespace clang + +#endif Modified: cfe/trunk/lib/Lex/PPDirectives.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=308948&r1=308947&r2=308948&view=diff ============================================================================== --- cfe/trunk/lib/Lex/PPDirectives.cpp (original) +++ cfe/trunk/lib/Lex/PPDirectives.cpp Mon Jul 24 20:15:36 2017 @@ -33,6 +33,7 @@ #include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/PTHLexer.h" #include "clang/Lex/Token.h" +#include "clang/Lex/VariadicMacroSupport.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -2290,6 +2291,10 @@ MacroInfo *Preprocessor::ReadOptionalMac Token Tok; LexUnexpandedToken(Tok); + // Used to un-poison and then re-poison identifiers of the __VA_ARGS__ ilk + // within their appropriate context. + VariadicMacroScopeGuard VariadicMacroScopeGuard(*this); + // If this is a function-like macro definition, parse the argument list, // marking each of the identifiers as being used as macro arguments. Also, // check other constraints on the first token of the macro body. @@ -2314,14 +2319,14 @@ MacroInfo *Preprocessor::ReadOptionalMac return nullptr; } - // If this is a definition of a variadic C99 function-like macro, not using - // the GNU named varargs extension, enabled __VA_ARGS__. + // If this is a definition of an ISO C/C++ variadic function-like macro (not + // using the GNU named varargs extension) inform our variadic scope guard + // which un-poisons and re-poisons certain identifiers (e.g. __VA_ARGS__) + // allowed only within the definition of a variadic macro. - // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro. - // This gets unpoisoned where it is allowed. - assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned!"); - if (MI->isC99Varargs()) - Ident__VA_ARGS__->setIsPoisoned(false); + if (MI->isC99Varargs()) { + VariadicMacroScopeGuard.enterScope(); + } // Read the first token after the arg list for down below. LexUnexpandedToken(Tok); @@ -2431,9 +2436,6 @@ MacroInfo *Preprocessor::ReadOptionalMac } else { Diag(Tok, diag::err_pp_stringize_not_parameter) << LastTok.is(tok::hashat); - - // Disable __VA_ARGS__ again. - Ident__VA_ARGS__->setIsPoisoned(true); return nullptr; } } @@ -2448,9 +2450,6 @@ MacroInfo *Preprocessor::ReadOptionalMac } } MI->setDefinitionEndLoc(LastTok.getLocation()); - // Disable __VA_ARGS__ again. - Ident__VA_ARGS__->setIsPoisoned(true); - return MI; } /// HandleDefineDirective - Implements \#define. This consumes the entire macro _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits