[PATCH] D153914: [clang-cl] Enable concatenation of predefined identifiers
Tom Honermann via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 14 11:56:42 PDT 2023
tahonermann requested changes to this revision.
tahonermann added inline comments.
This revision now requires changes to proceed.
================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:118-120
+def ext_concat_predef_ms : ExtWarn<
+ "concatenation of predefined identifier '%0' is a Microsoft extension">,
+ InGroup<MicrosoftConcatPredefined>;
----------------
I think it makes since to be more explicit that the concatenation is with regard to string literals.
================
Comment at: clang/include/clang/Basic/TokenKinds.h:87-93
+/// Return true if this token is a predefined macro
+/// unexpandable by MSVC preprocessor.
+inline bool isUnexpandableMsMacro(TokenKind K) {
+ return K == tok::kw___FUNCTION__ || K == tok::kw___FUNCSIG__ ||
+ K == tok::kw_L__FUNCTION__ || K == tok::kw_L__FUNCSIG__ ||
+ K == tok::kw___FUNCDNAME__;
+}
----------------
================
Comment at: clang/include/clang/Parse/Parser.h:578-582
+ bool isTokenConcatenable() const {
+ return isTokenStringLiteral() ||
+ getLangOpts().MicrosoftExt &&
+ tok::isMSPredefinedMacro(Tok.getKind());
+ }
----------------
RIscRIpt wrote:
> cor3ntin wrote:
> > Unless you find a better name, I think it's preferable to keep `isTokenConcatenable` and `isTokenPredefinedMsMacro` as separate functions.
> > Also, this seems like a weird place to check for `getLangOpts().MicrosoftExt`
> Regarding `getLangOpts().MicrosoftExt`. If you are talking about it's presence in a function which name is meant to be used as a predicate, I agree. If you are talking about `class Parser`, then there're other places with references to `getLangOpts()`.
>
> Without such function `ParseStringLiteralExpression` implementation would be too verbose.
> Let's decide what we can do after I address other comments.
>
> Meanwhile, I renamed it to `isTokenLikeStringLiteral()`.
I suggest passing `getLangOpts()` to `isFunctionLocalPredefinedMacro` (`isUnexpandableMsMacro`) and letting it determine whether the token is or is not one of these special not-really-a-string-literal macro things. This will facilitate additional such macros controlled by different options while also colocating the option check with the related tokens.
================
Comment at: clang/include/clang/Sema/Sema.h:5681
+ std::vector<Token> ExpandUnexpandableMsMacros(ArrayRef<Token> Toks);
ExprResult BuildPredefinedExpr(SourceLocation Loc,
----------------
================
Comment at: clang/lib/Parse/ParseExpr.cpp:1300-1307
+ if (!getLangOpts().MicrosoftExt || !tok::isUnexpandableMsMacro(SavedKind) ||
+ !tok::isUnexpandableMsMacro(NextToken().getKind()) &&
+ !tok::isStringLiteral(NextToken().getKind())) {
+ Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
+ ConsumeToken();
+ break;
+ }
----------------
Since the conditional code is only relevant for some of the tokens here, I would prefer to see the other token kinds (`kw___func__`, `kw___PRETTY_FUNCTION__`) handled separately to avoid the conditional fallthrough. That means duplicating the calls to `Actions.ActOnPredefinedExpr()` and `ConsumeToken()` between the blocks, but that bothers me less than having to understand the complicated condition.
================
Comment at: clang/lib/Parse/ParseExpr.cpp:3277-3280
+ // String concatenation.
+ // Note that keywords like __func__ and __FUNCTION__
+ // are not considered to be strings for concatenation purposes,
+ // unless Microsoft extensions are enabled.
----------------
I think `__func__` is not considered a string literal in Microsoft mode, so I think this comment needs some adjusting.
================
Comment at: clang/lib/Parse/ParseExpr.cpp:3288-3291
+ assert(
+ (StringToks.size() != 1 ||
+ !tok::isUnexpandableMsMacro(StringToks[0].getKind())) &&
+ "single predefined identifiers shall be handled by ActOnPredefinedExpr");
----------------
What is the reason for requiring non-concatenated predefined function local macros to be handled by `ActOnPredefinedExpr()`?
================
Comment at: clang/lib/Sema/Sema.cpp:1494
+Decl *Sema::getCurScopeDecl() {
+ if (const BlockScopeInfo *BSI = getCurBlock())
----------------
`getCurScopeDecl` isn't a great name since this doesn't handle class or namespace scopes. How about `getCurLocalScopeDecl`? That name isn't quite right either since this can return a `TranslationUnitDecl`, but I think it matches the intent fairly well.
None of the callers need the actual `TranslationUnitDecl` that is returned. I think this function can return `nullptr` is the current scope isn't function local and callers can issue the relevant diagnostic in that case (thus avoiding the need to check that a translation unit decl was returned).
================
Comment at: clang/lib/Sema/SemaExpr.cpp:1971-1974
+ // MSVC treats some of predefined identifiers (e.g. __FUNCTION__) as
+ // expandable macros defined as string literals, which may be concatenated.
+ // Expand them here (in Sema), because StringLiteralParser (in Lex)
+ // doesn't have access to AST.
----------------
================
Comment at: clang/lib/Sema/SemaExpr.cpp:2001-2004
+ OS << '"'
+ << Lexer::Stringify(PredefinedExpr::ComputeName(
+ getPredefinedExprKind(Tok.getKind()), currentDecl))
+ << '"';
----------------
A diagnostic is issued if the call to `getCurScopeDecl()` returned a translation unit declaration (at least in Microsoft mode). Does it make sense to pass a pointer to a `TranslationUnitDecl` here?
================
Comment at: clang/lib/Sema/SemaExpr.cpp:3694
+ Decl *currentDecl = getCurScopeDecl();
+ if (isa<TranslationUnitDecl>(currentDecl)) {
Diag(Loc, diag::ext_predef_outside_function);
----------------
This can just be a `nullptr` check with my suggested change to `getCurScopeDecl()`.
================
Comment at: clang/test/Sema/ms_predefined_expr.cpp:62
+ static_assert(__FUNCTION__ ""_len == 14); // expected-warning{{concatenation of predefined identifier '__FUNCTION__' is a Microsoft extension}}
}
----------------
If we don't already have such tests, please add tests that exercise these macros at global, namespace, and class scope.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D153914/new/
https://reviews.llvm.org/D153914
More information about the cfe-commits
mailing list