https://github.com/kelbon updated https://github.com/llvm/llvm-project/pull/65851
>From d10ce5dd9e49fe85eac2e1f93a65cb27b511a71f Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sat, 9 Sep 2023 17:51:15 +0400 Subject: [PATCH 01/15] add define2 pp directive --- clang/include/clang/Basic/TokenKinds.def | 1 + clang/include/clang/Lex/MacroInfo.h | 19 +++++++++---------- clang/include/clang/Lex/Preprocessor.h | 2 +- clang/lib/Basic/IdentifierTable.cpp | 2 ++ clang/lib/Format/WhitespaceManager.cpp | 2 +- clang/lib/Lex/MacroInfo.cpp | 3 ++- clang/lib/Lex/PPDirectives.cpp | 16 +++++++++++----- 7 files changed, 27 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 72e8df8c793a7b6..b227a6a5632f496 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -115,6 +115,7 @@ PPKEYWORD(__include_macros) // C99 6.10.3 - Macro Replacement. PPKEYWORD(define) +PPKEYWORD(define2) PPKEYWORD(undef) // C99 6.10.4 - Line Control. diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index 00c1c3866bbd9ca..4f0c8e987610e50 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -102,6 +102,10 @@ class MacroInfo { /// like \#define A A. bool IsDisabled : 1; + // True if 'define2' used, + // ignores 'IsDisabled' and enables expansion anyway + bool AllowRecurse : 1; + /// True if this macro is either defined in the main file and has /// been used, or if it is not defined in the main file. /// @@ -278,18 +282,13 @@ class MacroInfo { /// Return true if this macro is enabled. /// /// In other words, that we are not currently in an expansion of this macro. - bool isEnabled() const { return !IsDisabled; } - - void EnableMacro() { - assert(IsDisabled && "Cannot enable an already-enabled macro!"); - IsDisabled = false; - } + bool isEnabled() const { return AllowRecurse || !IsDisabled; } + void setAllowRecursive(bool Allow) { AllowRecurse = Allow; } + bool isAllowRecurse() const { return AllowRecurse; } - void DisableMacro() { - assert(!IsDisabled && "Cannot disable an already-disabled macro!"); - IsDisabled = true; - } + void EnableMacro() { IsDisabled = false; } + void DisableMacro() { IsDisabled = true; } /// Determine whether this macro was used for a header guard. bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; } diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 575d08b83fd3a02..01eac0939fe9e21 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2754,7 +2754,7 @@ class Preprocessor { void replayPreambleConditionalStack(); // Macro handling. - void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterHeaderGuard); + void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterHeaderGuard, bool AllowRecurse); void HandleUndefDirective(); // Conditional Inclusion. diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index e5599d545541085..7300825ff6b826a 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -431,6 +431,8 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { unsigned Len = getLength(); if (Len < 2) return tok::pp_not_keyword; const char *Name = getNameStart(); + if (std::string_view(Name, Len) == "define2") + return tok::pp_define2; switch (HASH(Len, Name[0], Name[2])) { default: return tok::pp_not_keyword; CASE( 2, 'i', '\0', if); diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index b7bd8d27dc976b1..d8ab76d6761553e 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -743,7 +743,7 @@ void WhitespaceManager::alignConsecutiveMacros() { if (!Current || Current->isNot(tok::identifier)) return false; - if (!Current->Previous || Current->Previous->isNot(tok::pp_define)) + if (!Current->Previous || !Current->Previous->isOneOf(tok::pp_define, tok::pp_define2)) return false; // For a macro function, 0 spaces are required between the diff --git a/clang/lib/Lex/MacroInfo.cpp b/clang/lib/Lex/MacroInfo.cpp index 39bb0f44eff25ba..9c3619c7c909304 100644 --- a/clang/lib/Lex/MacroInfo.cpp +++ b/clang/lib/Lex/MacroInfo.cpp @@ -50,7 +50,7 @@ static_assert(MacroInfoSizeChecker<sizeof(void *)>::AsExpected, MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc), IsDefinitionLengthCached(false), IsFunctionLike(false), IsC99Varargs(false), IsGNUVarargs(false), IsBuiltinMacro(false), - HasCommaPasting(false), IsDisabled(false), IsUsed(false), + HasCommaPasting(false), IsDisabled(false), AllowRecurse(false), IsUsed(false), IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false), UsedForHeaderGuard(false) {} @@ -157,6 +157,7 @@ LLVM_DUMP_METHOD void MacroInfo::dump() const { if (IsBuiltinMacro) Out << " builtin"; if (IsDisabled) Out << " disabled"; if (IsUsed) Out << " used"; + if (AllowRecurse) Out << " allow_recurse"; if (IsAllowRedefinitionsWithoutWarning) Out << " allow_redefinitions_without_warning"; if (IsWarnIfUnused) Out << " warn_if_unused"; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 7edcb0577c2b25a..01b77a39437a30d 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1111,7 +1111,11 @@ void Preprocessor::HandleSkippedDirectiveWhileUsingPCH(Token &Result, if (const IdentifierInfo *II = Result.getIdentifierInfo()) { if (II->getPPKeywordID() == tok::pp_define) { return HandleDefineDirective(Result, - /*ImmediatelyAfterHeaderGuard=*/false); + /*ImmediatelyAfterHeaderGuard=*/false, /*AllowRecurse=*/false); + } + if (II->getPPKeywordID() == tok::pp_define2) { + return HandleDefineDirective(Result, + /*ImmediatelyAfterHeaderGuard=*/false, /*AllowRecurse=*/true); } if (SkippingUntilPCHThroughHeader && II->getPPKeywordID() == tok::pp_include) { @@ -1250,7 +1254,9 @@ void Preprocessor::HandleDirective(Token &Result) { // C99 6.10.3 - Macro Replacement. case tok::pp_define: - return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef); + return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef, false); + case tok::pp_define2: + return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef, true); case tok::pp_undef: return HandleUndefDirective(); @@ -3036,10 +3042,10 @@ static bool isObjCProtectedMacro(const IdentifierInfo *II) { II->isStr("__unsafe_unretained") || II->isStr("__autoreleasing"); } -/// HandleDefineDirective - Implements \#define. This consumes the entire macro +/// HandleDefineDirective - Implements \#define and define2. This consumes the entire macro /// line then lets the caller lex the next real token. void Preprocessor::HandleDefineDirective( - Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) { + Token &DefineTok, const bool ImmediatelyAfterHeaderGuard, bool AllowRecurse) { ++NumDefined; Token MacroNameTok; @@ -3064,7 +3070,7 @@ void Preprocessor::HandleDefineDirective( MacroNameTok, ImmediatelyAfterHeaderGuard); if (!MI) return; - + MI->setAllowRecursive(AllowRecurse); if (MacroShadowsKeyword && !isConfigurationPattern(MacroNameTok, MI, getLangOpts())) { Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword); >From 4e175402aa82403ee5281c5cd60250cb3c1536fc Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 10 Sep 2023 16:00:45 +0400 Subject: [PATCH 02/15] add recursion depth limit and tests --- .../include/clang/Basic/DiagnosticLexKinds.td | 2 ++ clang/include/clang/Lex/MacroInfo.h | 33 ++++++++++++------- clang/lib/Lex/MacroInfo.cpp | 4 +-- clang/lib/Lex/TokenLexer.cpp | 3 +- .../test/Preprocessor/macro_vaopt_expand.cpp | 20 +++++++++++ clang/test/Preprocessor/recursive_macro.cpp | 13 ++++++++ 6 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 clang/test/Preprocessor/recursive_macro.cpp diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 940cca67368492f..f940fa01a3d2f38 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -440,6 +440,8 @@ def err_pp_missing_lparen_in_vaopt_use : Error< def err_pp_vaopt_nested_use : Error< "__VA_OPT__ cannot be nested within its own replacement tokens">; +def err_pp_macro_recursion_depth_limit_exceeded : Error< + "macro recursion depth limit exceeded">; def err_vaopt_paste_at_start : Error< "'##' cannot appear at start of __VA_OPT__ argument">; diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index 4f0c8e987610e50..267292083058645 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -65,6 +65,12 @@ class MacroInfo { /// Length in characters of the macro definition. mutable unsigned DefinitionLength; + + enum : uint16_t { recursion_depth_limit = 16'000 }; + /// recursion depth, + /// > 0 if we have started an expansion of this macro already. + /// for 'define' max is 1, for 'define2' max is depth limit + uint16_t Depth = 0; mutable bool IsDefinitionLengthCached : 1; /// True if this macro is function-like, false if it is object-like. @@ -96,14 +102,7 @@ class MacroInfo { //===--------------------------------------------------------------------===// // State that changes as the macro is used. - /// True if we have started an expansion of this macro already. - /// - /// This disables recursive expansion, which would be quite bad for things - /// like \#define A A. - bool IsDisabled : 1; - - // True if 'define2' used, - // ignores 'IsDisabled' and enables expansion anyway + // True if 'define2' used, enables expansion anyway bool AllowRecurse : 1; /// True if this macro is either defined in the main file and has @@ -282,13 +281,23 @@ class MacroInfo { /// Return true if this macro is enabled. /// /// In other words, that we are not currently in an expansion of this macro. - bool isEnabled() const { return AllowRecurse || !IsDisabled; } + bool isEnabled() const { + // macro disabled if depth exceeds and stops infinite recursion + if (AllowRecurse) + return Depth < recursion_depth_limit; + return Depth == 0; + } void setAllowRecursive(bool Allow) { AllowRecurse = Allow; } bool isAllowRecurse() const { return AllowRecurse; } - void EnableMacro() { IsDisabled = false; } - - void DisableMacro() { IsDisabled = true; } + void EnableMacro() { + assert(Depth != 0 && "Cannot enable not disabled macro"); + --Depth; + } + // returns false if max recursion depth exceeded + [[nodiscard]] bool TryDisableMacro() { + return ++Depth < recursion_depth_limit; + } /// Determine whether this macro was used for a header guard. bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; } diff --git a/clang/lib/Lex/MacroInfo.cpp b/clang/lib/Lex/MacroInfo.cpp index 9c3619c7c909304..110e3232b66dc14 100644 --- a/clang/lib/Lex/MacroInfo.cpp +++ b/clang/lib/Lex/MacroInfo.cpp @@ -50,7 +50,7 @@ static_assert(MacroInfoSizeChecker<sizeof(void *)>::AsExpected, MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc), IsDefinitionLengthCached(false), IsFunctionLike(false), IsC99Varargs(false), IsGNUVarargs(false), IsBuiltinMacro(false), - HasCommaPasting(false), IsDisabled(false), AllowRecurse(false), IsUsed(false), + HasCommaPasting(false), AllowRecurse(false), IsUsed(false), IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false), UsedForHeaderGuard(false) {} @@ -155,7 +155,7 @@ LLVM_DUMP_METHOD void MacroInfo::dump() const { // FIXME: Dump locations. Out << "MacroInfo " << this; if (IsBuiltinMacro) Out << " builtin"; - if (IsDisabled) Out << " disabled"; + if (!isEnabled()) Out << " disabled"; if (IsUsed) Out << " used"; if (AllowRecurse) Out << " allow_recurse"; if (IsAllowRedefinitionsWithoutWarning) diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index 856d5682727fe3d..c51aec4fc17110d 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -88,7 +88,8 @@ void TokenLexer::Init(Token &Tok, SourceLocation ELEnd, MacroInfo *MI, // Mark the macro as currently disabled, so that it is not recursively // expanded. The macro must be disabled only after argument pre-expansion of // function-like macro arguments occurs. - Macro->DisableMacro(); + if (!Macro->TryDisableMacro()) + PP.Diag(Tok, diag::err_pp_macro_recursion_depth_limit_exceeded); } /// Create a TokenLexer for the specified token stream. This does not diff --git a/clang/test/Preprocessor/macro_vaopt_expand.cpp b/clang/test/Preprocessor/macro_vaopt_expand.cpp index 5eb0facb83f7364..9766b081516fd09 100644 --- a/clang/test/Preprocessor/macro_vaopt_expand.cpp +++ b/clang/test/Preprocessor/macro_vaopt_expand.cpp @@ -148,3 +148,23 @@ #undef F #undef G + +#define merge_all_expand2(a, b) a ## b +#define merge_all_expand(a, b) merge_all_expand2(a, b) +#define2 concat_all(head, ...) merge_all_expand(head, __VA_OPT__(concat_all(__VA_ARGS__))) +29: concat_all(aa, bb, cc) +30: [concat_all()] +// CHECK: 29: aabbcc +// CHECK: 30: [] + +#undef merge_all_expand +#undef merge_all_expand2 +#undef concat_all + +#define2 reverse(head, ...) __VA_OPT__(reverse(__VA_ARGS__) , ) head + +31: reverse(1, 2, 3) + +// CHECK: 31: 3, 2, 1 + +#undef reverse diff --git a/clang/test/Preprocessor/recursive_macro.cpp b/clang/test/Preprocessor/recursive_macro.cpp new file mode 100644 index 000000000000000..0fee436bf4d9ce0 --- /dev/null +++ b/clang/test/Preprocessor/recursive_macro.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 %s -Eonly -std=c++11 -pedantic -verify + +#define2 A A + +A //expected-error {{macro recursion depth limit exceeded}} + +#undef A + +#define2 boom(x) boom(x) + +boom(5) //expected-error {{macro recursion depth limit exceeded}} + +#undef boom >From 6ab7f4eba17c8174e09a50fedfcd3e1a22d44d80 Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Mon, 11 Sep 2023 12:03:36 +0400 Subject: [PATCH 03/15] rewrite Lexer recursion to loop --- clang/lib/Lex/Lexer.cpp | 32 +++++++++---------- clang/lib/Lex/PPMacroExpansion.cpp | 2 ++ .../test/Preprocessor/macro_vaopt_expand.cpp | 4 +-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 37c3e4175d4736e..178bcc08a72e208 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -847,26 +847,26 @@ bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd) { - assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc"); + for(SourceLocation expansionLoc; true;loc = expansionLoc) { + assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc"); - SourceLocation spellLoc = SM.getSpellingLoc(loc); - unsigned tokLen = MeasureTokenLength(spellLoc, SM, LangOpts); - if (tokLen == 0) - return false; + SourceLocation spellLoc = SM.getSpellingLoc(loc); + unsigned tokLen = MeasureTokenLength(spellLoc, SM, LangOpts); + if (tokLen == 0) + return false; - SourceLocation afterLoc = loc.getLocWithOffset(tokLen); - SourceLocation expansionLoc; - if (!SM.isAtEndOfImmediateMacroExpansion(afterLoc, &expansionLoc)) - return false; + SourceLocation afterLoc = loc.getLocWithOffset(tokLen); + if (!SM.isAtEndOfImmediateMacroExpansion(afterLoc, &expansionLoc)) + return false; - if (expansionLoc.isFileID()) { - // No other macro expansions. - if (MacroEnd) - *MacroEnd = expansionLoc; - return true; + if (expansionLoc.isFileID()) { + // No other macro expansions. + if (MacroEnd) + *MacroEnd = expansionLoc; + return true; + } } - - return isAtEndOfMacroExpansion(expansionLoc, SM, LangOpts, MacroEnd); + llvm_unreachable(""); } static CharSourceRange makeRangeFromFileLocs(CharSourceRange Range, diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index ec6a084f228f32d..313475cfd0e113c 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -614,6 +614,8 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, if (IdentifierInfo *NewII = Identifier.getIdentifierInfo()) { if (MacroInfo *NewMI = getMacroInfo(NewII)) if (!NewMI->isEnabled() || NewMI == MI) { + if (NewMI->isAllowRecurse() && NewMI == MI) + Diag(Identifier, diag::err_pp_macro_recursion_depth_limit_exceeded); Identifier.setFlag(Token::DisableExpand); // Don't warn for "#define X X" like "#define bool bool" from // stdbool.h. diff --git a/clang/test/Preprocessor/macro_vaopt_expand.cpp b/clang/test/Preprocessor/macro_vaopt_expand.cpp index 9766b081516fd09..17be324fdd71392 100644 --- a/clang/test/Preprocessor/macro_vaopt_expand.cpp +++ b/clang/test/Preprocessor/macro_vaopt_expand.cpp @@ -163,8 +163,8 @@ #define2 reverse(head, ...) __VA_OPT__(reverse(__VA_ARGS__) , ) head -31: reverse(1, 2, 3) +31: reverse(1,2,3) -// CHECK: 31: 3, 2, 1 +// CHECK: 31: 3,2,1 #undef reverse >From 6c126e8d6cb1fc97059d57b86e908465a2128873 Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Mon, 11 Sep 2023 13:54:55 +0400 Subject: [PATCH 04/15] more tests --- .../test/Preprocessor/macro_vaopt_expand.cpp | 20 ------------------- clang/test/Preprocessor/recursive_macro.cpp | 13 ------------ 2 files changed, 33 deletions(-) delete mode 100644 clang/test/Preprocessor/recursive_macro.cpp diff --git a/clang/test/Preprocessor/macro_vaopt_expand.cpp b/clang/test/Preprocessor/macro_vaopt_expand.cpp index 17be324fdd71392..5eb0facb83f7364 100644 --- a/clang/test/Preprocessor/macro_vaopt_expand.cpp +++ b/clang/test/Preprocessor/macro_vaopt_expand.cpp @@ -148,23 +148,3 @@ #undef F #undef G - -#define merge_all_expand2(a, b) a ## b -#define merge_all_expand(a, b) merge_all_expand2(a, b) -#define2 concat_all(head, ...) merge_all_expand(head, __VA_OPT__(concat_all(__VA_ARGS__))) -29: concat_all(aa, bb, cc) -30: [concat_all()] -// CHECK: 29: aabbcc -// CHECK: 30: [] - -#undef merge_all_expand -#undef merge_all_expand2 -#undef concat_all - -#define2 reverse(head, ...) __VA_OPT__(reverse(__VA_ARGS__) , ) head - -31: reverse(1,2,3) - -// CHECK: 31: 3,2,1 - -#undef reverse diff --git a/clang/test/Preprocessor/recursive_macro.cpp b/clang/test/Preprocessor/recursive_macro.cpp deleted file mode 100644 index 0fee436bf4d9ce0..000000000000000 --- a/clang/test/Preprocessor/recursive_macro.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: %clang_cc1 %s -Eonly -std=c++11 -pedantic -verify - -#define2 A A - -A //expected-error {{macro recursion depth limit exceeded}} - -#undef A - -#define2 boom(x) boom(x) - -boom(5) //expected-error {{macro recursion depth limit exceeded}} - -#undef boom >From fe01de795a9db1ff3c6bfde827b893e4059e24d5 Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Mon, 11 Sep 2023 13:55:51 +0400 Subject: [PATCH 05/15] test files --- .../Preprocessor/macro_infinite_recursion.cpp | 13 +++++++++ clang/test/Preprocessor/macro_recursion.cpp | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 clang/test/Preprocessor/macro_infinite_recursion.cpp create mode 100644 clang/test/Preprocessor/macro_recursion.cpp diff --git a/clang/test/Preprocessor/macro_infinite_recursion.cpp b/clang/test/Preprocessor/macro_infinite_recursion.cpp new file mode 100644 index 000000000000000..cac8e7abbec5af3 --- /dev/null +++ b/clang/test/Preprocessor/macro_infinite_recursion.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 %s -Eonly -std=c++11 -pedantic -verify + +#define2 A A + +A //expected-error {{macro recursion depth limit exceeded}} + +#undef A + +#define2 A(x) A(x) + +A(5) //expected-error {{macro recursion depth limit exceeded}} + +#undef A diff --git a/clang/test/Preprocessor/macro_recursion.cpp b/clang/test/Preprocessor/macro_recursion.cpp new file mode 100644 index 000000000000000..da3e6157efc0f60 --- /dev/null +++ b/clang/test/Preprocessor/macro_recursion.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -E %s -std=c++20 | FileCheck %s + +#define merge_all_expand2(a, b) a ## b +#define merge_all_expand(a, b) merge_all_expand2(a, b) +#define2 concat_all(head, ...) merge_all_expand(head, __VA_OPT__(concat_all(__VA_ARGS__))) +0: concat_all(aa, bb, cc) +1: [concat_all()] +// CHECK: 0: aabbcc +// CHECK: 1: [] + +#undef merge_all_expand +#undef merge_all_expand2 +#undef concat_all + +#define2 reverse(head, ...) __VA_OPT__(reverse(__VA_ARGS__) , ) head + +2: reverse(1,2,3) + +// CHECK: 2: 3,2,1 + +#undef reverse + +#define2 fold_left(op, head, ...) ( __VA_OPT__(fold_left(op, __VA_ARGS__) op) head ) + +3: fold_left(+, 1, 2, 3, 4) +// CHECK: 3: ((((4) + 3) + 2) + 1) + +#undef fold_left >From abe0bd0489f6dce25431dccdeafac8063a239f8f Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Mon, 11 Sep 2023 14:23:17 +0400 Subject: [PATCH 06/15] whitespaces --- clang/test/Preprocessor/macro_recursion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Preprocessor/macro_recursion.cpp b/clang/test/Preprocessor/macro_recursion.cpp index da3e6157efc0f60..a7a69e4ba08b146 100644 --- a/clang/test/Preprocessor/macro_recursion.cpp +++ b/clang/test/Preprocessor/macro_recursion.cpp @@ -16,7 +16,7 @@ 2: reverse(1,2,3) -// CHECK: 2: 3,2,1 +// CHECK: 2: 3 , 2 , 1 #undef reverse >From a28be970bf5c440bbecf7146d27e51dca42ba4cd Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Mon, 11 Sep 2023 16:10:20 +0400 Subject: [PATCH 07/15] whitespaces in tests --- clang/test/Preprocessor/macro_recursion.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/test/Preprocessor/macro_recursion.cpp b/clang/test/Preprocessor/macro_recursion.cpp index a7a69e4ba08b146..cd415ce1a95e463 100644 --- a/clang/test/Preprocessor/macro_recursion.cpp +++ b/clang/test/Preprocessor/macro_recursion.cpp @@ -2,7 +2,7 @@ #define merge_all_expand2(a, b) a ## b #define merge_all_expand(a, b) merge_all_expand2(a, b) -#define2 concat_all(head, ...) merge_all_expand(head, __VA_OPT__(concat_all(__VA_ARGS__))) +#define2 concat_all(head, ...)merge_all_expand(head,__VA_OPT__(concat_all(__VA_ARGS__))) 0: concat_all(aa, bb, cc) 1: [concat_all()] // CHECK: 0: aabbcc @@ -12,17 +12,17 @@ #undef merge_all_expand2 #undef concat_all -#define2 reverse(head, ...) __VA_OPT__(reverse(__VA_ARGS__) , ) head +#define2 reverse(head, ...)__VA_OPT__(reverse(__VA_ARGS__),)head 2: reverse(1,2,3) -// CHECK: 2: 3 , 2 , 1 +// CHECK: 2: 3,2,1 #undef reverse -#define2 fold_left(op, head, ...) ( __VA_OPT__(fold_left(op, __VA_ARGS__) op) head ) +#define2 fold_left(op, head, ...)(__VA_OPT__(fold_left(op,__VA_ARGS__)op)head) 3: fold_left(+, 1, 2, 3, 4) -// CHECK: 3: ((((4) + 3) + 2) + 1) +// CHECK: 3: ((((4)+3)+2)+1) #undef fold_left >From 8555660c576eac3f34537bf0233aefbfcb6828a2 Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Tue, 12 Sep 2023 01:53:45 +0400 Subject: [PATCH 08/15] remove redundant HandleDefineDirective argument --- clang/include/clang/Lex/MacroInfo.h | 23 ++++++++++++----------- clang/include/clang/Lex/Preprocessor.h | 2 +- clang/lib/Lex/PPDirectives.cpp | 15 +++++---------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index 267292083058645..54b1d7193dbe613 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -66,11 +66,9 @@ class MacroInfo { /// Length in characters of the macro definition. mutable unsigned DefinitionLength; - enum : uint16_t { recursion_depth_limit = 16'000 }; - /// recursion depth, - /// > 0 if we have started an expansion of this macro already. - /// for 'define' max is 1, for 'define2' max is depth limit - uint16_t Depth = 0; + /// True if 'define2' used, enables expansion anyway + bool AllowRecurse : 1; + mutable bool IsDefinitionLengthCached : 1; /// True if this macro is function-like, false if it is object-like. @@ -102,9 +100,6 @@ class MacroInfo { //===--------------------------------------------------------------------===// // State that changes as the macro is used. - // True if 'define2' used, enables expansion anyway - bool AllowRecurse : 1; - /// True if this macro is either defined in the main file and has /// been used, or if it is not defined in the main file. /// @@ -120,6 +115,12 @@ class MacroInfo { /// Whether this macro was used as header guard. bool UsedForHeaderGuard : 1; + enum : uint16_t { recursion_depth_limit = 16'000 }; + /// recursion depth, + /// > 0 if we have started an expansion of this macro already. + /// for 'define' max is 1, for 'define2' max is depth limit + uint16_t Depth = 0; + // Only the Preprocessor gets to create these. MacroInfo(SourceLocation DefLoc); @@ -283,9 +284,7 @@ class MacroInfo { /// In other words, that we are not currently in an expansion of this macro. bool isEnabled() const { // macro disabled if depth exceeds and stops infinite recursion - if (AllowRecurse) - return Depth < recursion_depth_limit; - return Depth == 0; + return AllowRecurse ? Depth < recursion_depth_limit : Depth == 0; } void setAllowRecursive(bool Allow) { AllowRecurse = Allow; } bool isAllowRecurse() const { return AllowRecurse; } @@ -296,8 +295,10 @@ class MacroInfo { } // returns false if max recursion depth exceeded [[nodiscard]] bool TryDisableMacro() { + assert((AllowRecurse || Depth == 0) && "Cannot disable an already-disabled macro!"); return ++Depth < recursion_depth_limit; } + /// Determine whether this macro was used for a header guard. bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; } diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 01eac0939fe9e21..575d08b83fd3a02 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2754,7 +2754,7 @@ class Preprocessor { void replayPreambleConditionalStack(); // Macro handling. - void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterHeaderGuard, bool AllowRecurse); + void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterHeaderGuard); void HandleUndefDirective(); // Conditional Inclusion. diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 01b77a39437a30d..06b81985749aa25 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1109,13 +1109,9 @@ class Preprocessor::ResetMacroExpansionHelper { void Preprocessor::HandleSkippedDirectiveWhileUsingPCH(Token &Result, SourceLocation HashLoc) { if (const IdentifierInfo *II = Result.getIdentifierInfo()) { - if (II->getPPKeywordID() == tok::pp_define) { + if (II->getPPKeywordID() == tok::pp_define || II->getPPKeywordID() == tok::pp_define2) { return HandleDefineDirective(Result, - /*ImmediatelyAfterHeaderGuard=*/false, /*AllowRecurse=*/false); - } - if (II->getPPKeywordID() == tok::pp_define2) { - return HandleDefineDirective(Result, - /*ImmediatelyAfterHeaderGuard=*/false, /*AllowRecurse=*/true); + /*ImmediatelyAfterHeaderGuard=*/false); } if (SkippingUntilPCHThroughHeader && II->getPPKeywordID() == tok::pp_include) { @@ -1254,9 +1250,8 @@ void Preprocessor::HandleDirective(Token &Result) { // C99 6.10.3 - Macro Replacement. case tok::pp_define: - return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef, false); case tok::pp_define2: - return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef, true); + return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef); case tok::pp_undef: return HandleUndefDirective(); @@ -3045,7 +3040,7 @@ static bool isObjCProtectedMacro(const IdentifierInfo *II) { /// HandleDefineDirective - Implements \#define and define2. This consumes the entire macro /// line then lets the caller lex the next real token. void Preprocessor::HandleDefineDirective( - Token &DefineTok, const bool ImmediatelyAfterHeaderGuard, bool AllowRecurse) { + Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) { ++NumDefined; Token MacroNameTok; @@ -3070,7 +3065,7 @@ void Preprocessor::HandleDefineDirective( MacroNameTok, ImmediatelyAfterHeaderGuard); if (!MI) return; - MI->setAllowRecursive(AllowRecurse); + MI->setAllowRecursive(DefineTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_define2); if (MacroShadowsKeyword && !isConfigurationPattern(MacroNameTok, MI, getLangOpts())) { Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword); >From 49d7fa2e638f3903375f6f1de8443c63ff909a5d Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 24 Sep 2023 13:42:56 +0400 Subject: [PATCH 09/15] __THIS_MACRO__ --- clang/include/clang/Lex/MacroInfo.h | 18 ++++++++---- clang/include/clang/Lex/Preprocessor.h | 6 ++++ clang/lib/Lex/PPMacroExpansion.cpp | 29 +++++++++++++++++++ clang/lib/Lex/Preprocessor.cpp | 1 + .../Preprocessor/macro_infinite_recursion.cpp | 6 ++-- clang/test/Preprocessor/macro_recursion.cpp | 6 ++-- 6 files changed, 55 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index 54b1d7193dbe613..8b91d33e971b752 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -55,7 +55,7 @@ class MacroInfo { IdentifierInfo **ParameterList = nullptr; /// This is the list of tokens that the macro is defined to. - const Token *ReplacementTokens = nullptr; + Token *ReplacementTokens = nullptr; /// \see ParameterList unsigned NumParameters = 0; @@ -186,8 +186,11 @@ class MacroInfo { param_iterator param_begin() const { return ParameterList; } param_iterator param_end() const { return ParameterList + NumParameters; } unsigned getNumParams() const { return NumParameters; } + ArrayRef<IdentifierInfo *> params() { + return ArrayRef<IdentifierInfo *>(ParameterList, NumParameters); + } ArrayRef<const IdentifierInfo *> params() const { - return ArrayRef<const IdentifierInfo *>(ParameterList, NumParameters); + return const_cast<MacroInfo*>(this)->params(); } /// Return the parameter number of the specified identifier, @@ -250,6 +253,9 @@ class MacroInfo { return ReplacementTokens + NumReplacementTokens; } bool tokens_empty() const { return NumReplacementTokens == 0; } + MutableArrayRef<Token> tokens() { + return llvm::MutableArrayRef(ReplacementTokens, NumReplacementTokens); + } ArrayRef<Token> tokens() const { return llvm::ArrayRef(ReplacementTokens, NumReplacementTokens); } @@ -293,10 +299,12 @@ class MacroInfo { assert(Depth != 0 && "Cannot enable not disabled macro"); --Depth; } - // returns false if max recursion depth exceeded - [[nodiscard]] bool TryDisableMacro() { + enum : uint16_t { macro_recursion_depth_limit = 16'000 }; + + [[nodiscard("infinite recursion check ignored")]] + bool TryDisableMacro() { assert((AllowRecurse || Depth == 0) && "Cannot disable an already-disabled macro!"); - return ++Depth < recursion_depth_limit; + return ++Depth < macro_recursion_depth_limit; } /// Determine whether this macro was used for a header guard. diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 575d08b83fd3a02..356be1d3b45cac9 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -160,6 +160,7 @@ class Preprocessor { IdentifierInfo *Ident__identifier; // __identifier IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__ IdentifierInfo *Ident__VA_OPT__; // __VA_OPT__ + IdentifierInfo *Ident__THIS_MACRO__; // __THIS_MACRO__ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin @@ -2425,6 +2426,11 @@ class Preprocessor { private: friend void TokenLexer::ExpandFunctionArguments(); + /// If macro definition containts __THIS_MACRO__ creates impl-only recursive + /// version of macro, and replaces all __THIS_MACRO__ tokens + /// with new created recusive version + void appendRecursiveVersionIfRequired(IdentifierInfo*, MacroInfo*); + void PushIncludeMacroStack() { assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer"); IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule, diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 313475cfd0e113c..ca1f78280bfcb24 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -59,6 +59,34 @@ using namespace clang; +void Preprocessor::appendRecursiveVersionIfRequired(IdentifierInfo* II, MacroInfo* MI) { + if (!MI->isFunctionLike()) + return; + auto is_this_macro_tok = [&] (const Token& t) { + return t.getKind() == tok::identifier && t.getIdentifierInfo() == Ident__THIS_MACRO__; + }; + if (llvm::none_of(MI->tokens(), is_this_macro_tok)) + return; + IdentifierInfo* ImplMacroII = [&] { + std::string ImplMacroName = "__THIS_MACRO__"; + ImplMacroName += II->getName(); + return getIdentifierInfo(ImplMacroName); + }(); + MacroInfo* NewMI = AllocateMacroInfo(MI->getDefinitionLoc()); + NewMI->setIsFunctionLike(); + NewMI->setParameterList(MI->params(), getPreprocessorAllocator()); + NewMI->setDefinitionEndLoc(MI->getDefinitionEndLoc()); + if (MI->isC99Varargs()) NewMI->setIsC99Varargs(); + if (MI->isGNUVarargs()) NewMI->setIsGNUVarargs(); + for (auto& t : MI->tokens()) { + if (is_this_macro_tok(t)) + t.setIdentifierInfo(ImplMacroII); + } + NewMI->setTokens(MI->tokens(), getPreprocessorAllocator()); + NewMI->setAllowRecursive(true); + appendDefMacroDirective(ImplMacroII, NewMI); +} + MacroDirective * Preprocessor::getLocalMacroDirectiveHistory(const IdentifierInfo *II) const { if (!II->hadMacroDefinition()) @@ -91,6 +119,7 @@ void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){ II->setHasMacroDefinition(false); if (II->isFromAST()) II->setChangedSinceDeserialization(); + appendRecursiveVersionIfRequired(II, MD->getMacroInfo()); } void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II, diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index f0381c18a8b6f77..4e6c0ce112d488e 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -121,6 +121,7 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts, SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); + Ident__THIS_MACRO__ = getIdentifierInfo("__THIS_MACRO__"); // Initialize the pragma handlers. RegisterBuiltinPragmas(); diff --git a/clang/test/Preprocessor/macro_infinite_recursion.cpp b/clang/test/Preprocessor/macro_infinite_recursion.cpp index cac8e7abbec5af3..3306f468543bcb9 100644 --- a/clang/test/Preprocessor/macro_infinite_recursion.cpp +++ b/clang/test/Preprocessor/macro_infinite_recursion.cpp @@ -1,12 +1,12 @@ // RUN: %clang_cc1 %s -Eonly -std=c++11 -pedantic -verify -#define2 A A +#define A() __THIS_MACRO__() -A //expected-error {{macro recursion depth limit exceeded}} +A() //expected-error {{macro recursion depth limit exceeded}} #undef A -#define2 A(x) A(x) +#define A(x) __THIS_MACRO__(x) A(5) //expected-error {{macro recursion depth limit exceeded}} diff --git a/clang/test/Preprocessor/macro_recursion.cpp b/clang/test/Preprocessor/macro_recursion.cpp index cd415ce1a95e463..fc2c2ffd21eadd6 100644 --- a/clang/test/Preprocessor/macro_recursion.cpp +++ b/clang/test/Preprocessor/macro_recursion.cpp @@ -2,7 +2,7 @@ #define merge_all_expand2(a, b) a ## b #define merge_all_expand(a, b) merge_all_expand2(a, b) -#define2 concat_all(head, ...)merge_all_expand(head,__VA_OPT__(concat_all(__VA_ARGS__))) +#define concat_all(head, ...)merge_all_expand(head,__VA_OPT__(__THIS_MACRO__(__VA_ARGS__))) 0: concat_all(aa, bb, cc) 1: [concat_all()] // CHECK: 0: aabbcc @@ -12,7 +12,7 @@ #undef merge_all_expand2 #undef concat_all -#define2 reverse(head, ...)__VA_OPT__(reverse(__VA_ARGS__),)head +#define reverse(head, ...)__VA_OPT__(__THIS_MACRO__(__VA_ARGS__),)head 2: reverse(1,2,3) @@ -20,7 +20,7 @@ #undef reverse -#define2 fold_left(op, head, ...)(__VA_OPT__(fold_left(op,__VA_ARGS__)op)head) +#define fold_left(op, head, ...)(__VA_OPT__(__THIS_MACRO__(op,__VA_ARGS__)op)head) 3: fold_left(+, 1, 2, 3, 4) // CHECK: 3: ((((4)+3)+2)+1) >From 1add34ebecc2fa45ed48c7a2156d8d080afcd8bf Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 24 Sep 2023 14:49:26 +0400 Subject: [PATCH 10/15] rm define2 --- clang/include/clang/Basic/TokenKinds.def | 1 - clang/include/clang/Lex/MacroInfo.h | 4 ++-- clang/lib/Basic/IdentifierTable.cpp | 2 -- clang/lib/Format/WhitespaceManager.cpp | 2 +- clang/lib/Lex/PPDirectives.cpp | 7 +++---- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index b227a6a5632f496..72e8df8c793a7b6 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -115,7 +115,6 @@ PPKEYWORD(__include_macros) // C99 6.10.3 - Macro Replacement. PPKEYWORD(define) -PPKEYWORD(define2) PPKEYWORD(undef) // C99 6.10.4 - Line Control. diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index 8b91d33e971b752..49cbacf6df1acda 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -66,7 +66,7 @@ class MacroInfo { /// Length in characters of the macro definition. mutable unsigned DefinitionLength; - /// True if 'define2' used, enables expansion anyway + /// True only for inner-impl '__THIS_MACRO__', enables expansion anyway bool AllowRecurse : 1; mutable bool IsDefinitionLengthCached : 1; @@ -118,7 +118,7 @@ class MacroInfo { enum : uint16_t { recursion_depth_limit = 16'000 }; /// recursion depth, /// > 0 if we have started an expansion of this macro already. - /// for 'define' max is 1, for 'define2' max is depth limit + /// if !AllowRecurse max is 1, else max is recursion depth limit uint16_t Depth = 0; // Only the Preprocessor gets to create these. diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index 7300825ff6b826a..e5599d545541085 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -431,8 +431,6 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { unsigned Len = getLength(); if (Len < 2) return tok::pp_not_keyword; const char *Name = getNameStart(); - if (std::string_view(Name, Len) == "define2") - return tok::pp_define2; switch (HASH(Len, Name[0], Name[2])) { default: return tok::pp_not_keyword; CASE( 2, 'i', '\0', if); diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index d8ab76d6761553e..b7bd8d27dc976b1 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -743,7 +743,7 @@ void WhitespaceManager::alignConsecutiveMacros() { if (!Current || Current->isNot(tok::identifier)) return false; - if (!Current->Previous || !Current->Previous->isOneOf(tok::pp_define, tok::pp_define2)) + if (!Current->Previous || Current->Previous->isNot(tok::pp_define)) return false; // For a macro function, 0 spaces are required between the diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 06b81985749aa25..9e4ce13bb9c32a9 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1109,7 +1109,7 @@ class Preprocessor::ResetMacroExpansionHelper { void Preprocessor::HandleSkippedDirectiveWhileUsingPCH(Token &Result, SourceLocation HashLoc) { if (const IdentifierInfo *II = Result.getIdentifierInfo()) { - if (II->getPPKeywordID() == tok::pp_define || II->getPPKeywordID() == tok::pp_define2) { + if (II->getPPKeywordID() == tok::pp_define) { return HandleDefineDirective(Result, /*ImmediatelyAfterHeaderGuard=*/false); } @@ -1250,7 +1250,6 @@ void Preprocessor::HandleDirective(Token &Result) { // C99 6.10.3 - Macro Replacement. case tok::pp_define: - case tok::pp_define2: return HandleDefineDirective(Result, ImmediatelyAfterTopLevelIfndef); case tok::pp_undef: return HandleUndefDirective(); @@ -3037,7 +3036,7 @@ static bool isObjCProtectedMacro(const IdentifierInfo *II) { II->isStr("__unsafe_unretained") || II->isStr("__autoreleasing"); } -/// HandleDefineDirective - Implements \#define and define2. This consumes the entire macro +/// HandleDefineDirective - Implements \#define. This consumes the entire macro /// line then lets the caller lex the next real token. void Preprocessor::HandleDefineDirective( Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) { @@ -3065,7 +3064,7 @@ void Preprocessor::HandleDefineDirective( MacroNameTok, ImmediatelyAfterHeaderGuard); if (!MI) return; - MI->setAllowRecursive(DefineTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_define2); + if (MacroShadowsKeyword && !isConfigurationPattern(MacroNameTok, MI, getLangOpts())) { Diag(MacroNameTok, diag::warn_pp_macro_hides_keyword); >From c879ca056bf9eb16fad28ad1d324bad829bfb7ca Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 24 Sep 2023 14:52:58 +0400 Subject: [PATCH 11/15] rm enum --- clang/include/clang/Lex/MacroInfo.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index 49cbacf6df1acda..e5b996115a96c2b 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -115,7 +115,7 @@ class MacroInfo { /// Whether this macro was used as header guard. bool UsedForHeaderGuard : 1; - enum : uint16_t { recursion_depth_limit = 16'000 }; + enum : uint16_t { macro_recursion_depth_limit = 16'000 }; /// recursion depth, /// > 0 if we have started an expansion of this macro already. /// if !AllowRecurse max is 1, else max is recursion depth limit @@ -290,7 +290,7 @@ class MacroInfo { /// In other words, that we are not currently in an expansion of this macro. bool isEnabled() const { // macro disabled if depth exceeds and stops infinite recursion - return AllowRecurse ? Depth < recursion_depth_limit : Depth == 0; + return AllowRecurse ? Depth < macro_recursion_depth_limit : Depth == 0; } void setAllowRecursive(bool Allow) { AllowRecurse = Allow; } bool isAllowRecurse() const { return AllowRecurse; } @@ -299,7 +299,6 @@ class MacroInfo { assert(Depth != 0 && "Cannot enable not disabled macro"); --Depth; } - enum : uint16_t { macro_recursion_depth_limit = 16'000 }; [[nodiscard("infinite recursion check ignored")]] bool TryDisableMacro() { >From 998bf1306c0cc9c1f76a3e3eb6370036de2f7c18 Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 24 Sep 2023 15:08:31 +0400 Subject: [PATCH 12/15] comment fixes --- clang/include/clang/Lex/Preprocessor.h | 2 +- clang/lib/Lex/PPDirectives.cpp | 2 +- clang/lib/Lex/PPMacroExpansion.cpp | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 356be1d3b45cac9..3a5bcac1de77427 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2426,7 +2426,7 @@ class Preprocessor { private: friend void TokenLexer::ExpandFunctionArguments(); - /// If macro definition containts __THIS_MACRO__ creates impl-only recursive + /// If macro definition contains __THIS_MACRO__ creates impl-only recursive /// version of macro, and replaces all __THIS_MACRO__ tokens /// with new created recusive version void appendRecursiveVersionIfRequired(IdentifierInfo*, MacroInfo*); diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 9e4ce13bb9c32a9..7edcb0577c2b25a 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -3036,7 +3036,7 @@ static bool isObjCProtectedMacro(const IdentifierInfo *II) { II->isStr("__unsafe_unretained") || II->isStr("__autoreleasing"); } -/// HandleDefineDirective - Implements \#define. This consumes the entire macro +/// HandleDefineDirective - Implements \#define. This consumes the entire macro /// line then lets the caller lex the next real token. void Preprocessor::HandleDefineDirective( Token &DefineTok, const bool ImmediatelyAfterHeaderGuard) { diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index ca1f78280bfcb24..6fbe08e3baa569a 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -643,8 +643,6 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, if (IdentifierInfo *NewII = Identifier.getIdentifierInfo()) { if (MacroInfo *NewMI = getMacroInfo(NewII)) if (!NewMI->isEnabled() || NewMI == MI) { - if (NewMI->isAllowRecurse() && NewMI == MI) - Diag(Identifier, diag::err_pp_macro_recursion_depth_limit_exceeded); Identifier.setFlag(Token::DisableExpand); // Don't warn for "#define X X" like "#define bool bool" from // stdbool.h. >From cab7a4a019af133cc84c465cc8edbed2205880ca Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 24 Sep 2023 15:16:55 +0400 Subject: [PATCH 13/15] format --- clang/include/clang/Lex/MacroInfo.h | 8 ++++---- clang/include/clang/Lex/Preprocessor.h | 2 +- clang/lib/Lex/Lexer.cpp | 2 +- clang/lib/Lex/MacroInfo.cpp | 6 ++++-- clang/lib/Lex/PPMacroExpansion.cpp | 18 +++++++++++------- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index e5b996115a96c2b..b1df66961dd853d 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -190,7 +190,7 @@ class MacroInfo { return ArrayRef<IdentifierInfo *>(ParameterList, NumParameters); } ArrayRef<const IdentifierInfo *> params() const { - return const_cast<MacroInfo*>(this)->params(); + return const_cast<MacroInfo *>(this)->params(); } /// Return the parameter number of the specified identifier, @@ -300,9 +300,9 @@ class MacroInfo { --Depth; } - [[nodiscard("infinite recursion check ignored")]] - bool TryDisableMacro() { - assert((AllowRecurse || Depth == 0) && "Cannot disable an already-disabled macro!"); + [[nodiscard("infinite recursion check ignored")]] bool TryDisableMacro() { + assert((AllowRecurse || Depth == 0) && + "Cannot disable an already-disabled macro!"); return ++Depth < macro_recursion_depth_limit; } diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 3a5bcac1de77427..fb128d8c0e77334 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2429,7 +2429,7 @@ class Preprocessor { /// If macro definition contains __THIS_MACRO__ creates impl-only recursive /// version of macro, and replaces all __THIS_MACRO__ tokens /// with new created recusive version - void appendRecursiveVersionIfRequired(IdentifierInfo*, MacroInfo*); + void appendRecursiveVersionIfRequired(IdentifierInfo *, MacroInfo *); void PushIncludeMacroStack() { assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer"); diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index 178bcc08a72e208..70ba8f4f9c84fd6 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -847,7 +847,7 @@ bool Lexer::isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd) { - for(SourceLocation expansionLoc; true;loc = expansionLoc) { + for (SourceLocation expansionLoc; true; loc = expansionLoc) { assert(loc.isValid() && loc.isMacroID() && "Expected a valid macro loc"); SourceLocation spellLoc = SM.getSpellingLoc(loc); diff --git a/clang/lib/Lex/MacroInfo.cpp b/clang/lib/Lex/MacroInfo.cpp index 110e3232b66dc14..e042dd38a026311 100644 --- a/clang/lib/Lex/MacroInfo.cpp +++ b/clang/lib/Lex/MacroInfo.cpp @@ -155,9 +155,11 @@ LLVM_DUMP_METHOD void MacroInfo::dump() const { // FIXME: Dump locations. Out << "MacroInfo " << this; if (IsBuiltinMacro) Out << " builtin"; - if (!isEnabled()) Out << " disabled"; + if (!isEnabled()) + Out << " disabled"; if (IsUsed) Out << " used"; - if (AllowRecurse) Out << " allow_recurse"; + if (AllowRecurse) + Out << " allow_recurse"; if (IsAllowRedefinitionsWithoutWarning) Out << " allow_redefinitions_without_warning"; if (IsWarnIfUnused) Out << " warn_if_unused"; diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 6fbe08e3baa569a..b02eedea137e800 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -59,26 +59,30 @@ using namespace clang; -void Preprocessor::appendRecursiveVersionIfRequired(IdentifierInfo* II, MacroInfo* MI) { +void Preprocessor::appendRecursiveVersionIfRequired(IdentifierInfo *II, + MacroInfo *MI) { if (!MI->isFunctionLike()) return; auto is_this_macro_tok = [&] (const Token& t) { - return t.getKind() == tok::identifier && t.getIdentifierInfo() == Ident__THIS_MACRO__; + return t.getKind() == tok::identifier && + t.getIdentifierInfo() == Ident__THIS_MACRO__; }; if (llvm::none_of(MI->tokens(), is_this_macro_tok)) return; - IdentifierInfo* ImplMacroII = [&] { + IdentifierInfo *ImplMacroII = [&] { std::string ImplMacroName = "__THIS_MACRO__"; ImplMacroName += II->getName(); return getIdentifierInfo(ImplMacroName); }(); - MacroInfo* NewMI = AllocateMacroInfo(MI->getDefinitionLoc()); + MacroInfo *NewMI = AllocateMacroInfo(MI->getDefinitionLoc()); NewMI->setIsFunctionLike(); NewMI->setParameterList(MI->params(), getPreprocessorAllocator()); NewMI->setDefinitionEndLoc(MI->getDefinitionEndLoc()); - if (MI->isC99Varargs()) NewMI->setIsC99Varargs(); - if (MI->isGNUVarargs()) NewMI->setIsGNUVarargs(); - for (auto& t : MI->tokens()) { + if (MI->isC99Varargs()) + NewMI->setIsC99Varargs(); + if (MI->isGNUVarargs()) + NewMI->setIsGNUVarargs(); + for (auto &t : MI->tokens()) { if (is_this_macro_tok(t)) t.setIdentifierInfo(ImplMacroII); } >From 49b60855eed5657f386bc058c31457aa9bd78466 Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 24 Sep 2023 15:37:30 +0400 Subject: [PATCH 14/15] format again --- clang/include/clang/Lex/MacroInfo.h | 4 ++-- clang/lib/Lex/PPMacroExpansion.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index b1df66961dd853d..904efe83ca12fe5 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -299,10 +299,10 @@ class MacroInfo { assert(Depth != 0 && "Cannot enable not disabled macro"); --Depth; } - + [[nodiscard("infinite recursion check ignored")]] bool TryDisableMacro() { assert((AllowRecurse || Depth == 0) && - "Cannot disable an already-disabled macro!"); + "Cannot disable an already-disabled macro!"); return ++Depth < macro_recursion_depth_limit; } diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index b02eedea137e800..fbd26a60adb53c4 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -63,7 +63,7 @@ void Preprocessor::appendRecursiveVersionIfRequired(IdentifierInfo *II, MacroInfo *MI) { if (!MI->isFunctionLike()) return; - auto is_this_macro_tok = [&] (const Token& t) { + auto is_this_macro_tok = [&](const Token& t) { return t.getKind() == tok::identifier && t.getIdentifierInfo() == Ident__THIS_MACRO__; }; >From de5a85225b695a444f9ff938902ad3abd36ed39b Mon Sep 17 00:00:00 2001 From: Kelbon Nik <kelbon...@gmail.com> Date: Sun, 24 Sep 2023 15:58:21 +0400 Subject: [PATCH 15/15] format 3 --- clang/include/clang/Lex/MacroInfo.h | 2 +- clang/lib/Lex/PPMacroExpansion.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Lex/MacroInfo.h b/clang/include/clang/Lex/MacroInfo.h index 904efe83ca12fe5..81fd1574747127a 100644 --- a/clang/include/clang/Lex/MacroInfo.h +++ b/clang/include/clang/Lex/MacroInfo.h @@ -302,7 +302,7 @@ class MacroInfo { [[nodiscard("infinite recursion check ignored")]] bool TryDisableMacro() { assert((AllowRecurse || Depth == 0) && - "Cannot disable an already-disabled macro!"); + "Cannot disable an already-disabled macro!"); return ++Depth < macro_recursion_depth_limit; } diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index fbd26a60adb53c4..d78476349855d7a 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -63,7 +63,7 @@ void Preprocessor::appendRecursiveVersionIfRequired(IdentifierInfo *II, MacroInfo *MI) { if (!MI->isFunctionLike()) return; - auto is_this_macro_tok = [&](const Token& t) { + auto is_this_macro_tok = [&](const Token &t) { return t.getKind() == tok::identifier && t.getIdentifierInfo() == Ident__THIS_MACRO__; }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits