Author: Richard Dzenis Date: 2023-09-04T16:54:42+02:00 New Revision: e6d305e64fd39f0199b79d19dbc0d012efd83259
URL: https://github.com/llvm/llvm-project/commit/e6d305e64fd39f0199b79d19dbc0d012efd83259 DIFF: https://github.com/llvm/llvm-project/commit/e6d305e64fd39f0199b79d19dbc0d012efd83259.diff LOG: Add support of Windows Trace Logging macros Consider the following code: #include <windows.h> #include <TraceLoggingActivity.h> #include <TraceLoggingProvider.h> #include <winmeta.h> TRACELOGGING_DEFINE_PROVIDER( g_hMyComponentProvider, "SimpleTraceLoggingProvider", // {0205c616-cf97-5c11-9756-56a2cee02ca7} (0x0205c616,0xcf97,0x5c11,0x97,0x56,0x56,0xa2,0xce,0xe0,0x2c,0xa7)); void test() { TraceLoggingFunction(g_hMyComponentProvider); } int main() { TraceLoggingRegister(g_hMyComponentProvider); test(); TraceLoggingUnregister(g_hMyComponentProvider); } It compiles with MSVC, but clang-cl reports an error: C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared/TraceLoggingActivity.h(377,30): note: expanded from macro '_tlgThisFunctionName' #define _tlgThisFunctionName __FUNCTION__ ^ .\tl.cpp(14,5): error: cannot initialize an array element of type 'char' with an lvalue of type 'const char[5]' TraceLoggingFunction(g_hMyComponentProvider); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The second commit is not needed to support above code, however, during isolated tests in ms_predefined_expr.cpp I found that MSVC accepts code with constexpr, whereas clang-cl does not. I see that in most places PredefinedExpr is supported in constant evaluation, so I didn't wrap my code with ``if(MicrosoftExt)``. Reviewed By: cor3ntin Differential Revision: https://reviews.llvm.org/D158591 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Sema/Sema.h clang/lib/AST/ExprConstant.cpp clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaExpr.cpp clang/test/Sema/ms_predefined_expr.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c6d2c3466a09622..84681ec9554d212 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -211,6 +211,8 @@ Bug Fixes in This Version - Clang now reports ``-Wformat`` for bool value and char specifier confusion in scanf. Fixes (`#64987 <https://github.com/llvm/llvm-project/issues/64987>`_) +- Support MSVC predefined macro expressions in constant expressions and in + local structs. Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 35ee253831fc934..5fdca93c66ab5cd 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3620,10 +3620,6 @@ class Sema final { /// in a 'block', this returns the containing context. NamedDecl *getCurFunctionOrMethodDecl() const; - /// getCurLocalScopeDecl - Return the Decl for either of: - /// block, lambda, captured statement, function, or nullptr. - Decl *getCurLocalScopeDecl(); - /// Add this decl to the scope shadowed decl chains. void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 630fb02d0531e9d..0f37bcf0d5c8524 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -7528,6 +7528,9 @@ class ExprEvaluatorBase return Error(E); } + bool VisitPredefinedExpr(const PredefinedExpr *E) { + return StmtVisitorTy::Visit(E->getFunctionName()); + } bool VisitConstantExpr(const ConstantExpr *E) { if (E->hasAPValueResult()) return DerivedSuccess(E->getAPValueResult(), E); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 6220e3f9e6d6917..b8c2d4a95854975 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1491,18 +1491,6 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() const { return nullptr; } -Decl *Sema::getCurLocalScopeDecl() { - if (const BlockScopeInfo *BSI = getCurBlock()) - return BSI->TheDecl; - if (const LambdaScopeInfo *LSI = getCurLambda()) - return LSI->CallOperator; - if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion()) - return CSI->TheCapturedDecl; - if (NamedDecl *ND = getCurFunctionOrMethodDecl()) - return ND; - return nullptr; -} - LangAS Sema::getDefaultCXXMethodAddrSpace() const { if (getLangOpts().OpenCL) return getASTContext().getDefaultOpenCLPointeeAddrSpace(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1d457e116bb5b19..14a33e8688da2fa 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1904,6 +1904,15 @@ static PredefinedExpr::IdentKind getPredefinedExprKind(tok::TokenKind Kind) { } } +/// getPredefinedExprDecl - Returns Decl of a given DeclContext that can be used +/// to determine the value of a PredefinedExpr. This can be either a +/// block, lambda, captured statement, function, otherwise a nullptr. +static Decl *getPredefinedExprDecl(DeclContext *DC) { + while (DC && !isa<BlockDecl, CapturedDecl, FunctionDecl, ObjCMethodDecl>(DC)) + DC = DC->getParent(); + return cast_or_null<Decl>(DC); +} + /// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the /// location of the token and the offset of the ud-suffix within it. static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc, @@ -1984,7 +1993,7 @@ Sema::ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks) { // Note: Although function local macros are defined only inside functions, // we ensure a valid `CurrentDecl` even outside of a function. This allows // expansion of macros into empty string literals without additional checks. - Decl *CurrentDecl = getCurLocalScopeDecl(); + Decl *CurrentDecl = getPredefinedExprDecl(CurContext); if (!CurrentDecl) CurrentDecl = Context.getTranslationUnitDecl(); @@ -3705,7 +3714,7 @@ static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source, ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, PredefinedExpr::IdentKind IK) { - Decl *currentDecl = getCurLocalScopeDecl(); + Decl *currentDecl = getPredefinedExprDecl(CurContext); if (!currentDecl) { Diag(Loc, diag::ext_predef_outside_function); currentDecl = Context.getTranslationUnitDecl(); diff --git a/clang/test/Sema/ms_predefined_expr.cpp b/clang/test/Sema/ms_predefined_expr.cpp index 5919ee964ccab9b..9f4eb2763430dd1 100644 --- a/clang/test/Sema/ms_predefined_expr.cpp +++ b/clang/test/Sema/ms_predefined_expr.cpp @@ -168,3 +168,40 @@ void test_static_assert() { void test_char_injection(decltype(sizeof('"')), decltype(sizeof("()"))) { unused("" __FUNCSIG__); // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}} } + +void test_in_struct_init() { + struct { + char F[sizeof(__FUNCTION__)]; + } s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}} + + struct { + char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} + } s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} + + class C { + public: + struct { + char F[sizeof(__FUNCTION__)]; + } s; + } c1 = { { __FUNCTION__ } }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}} +} + +void test_in_constexpr_struct_init() { + struct { + char F[sizeof(__FUNCTION__)]; + } constexpr s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}} + ASSERT_EQ(__FUNCTION__, s1.F); + + struct { + char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} + } constexpr s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} + ASSERT_EQ("F:" __FUNCTION__, s2.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} + + class C { + public: + struct { + char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} + } s; + } constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} + ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits