Skip to content

Commit e6d305e

Browse files
RIscRIptcor3ntin
authored andcommitted
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
1 parent 4cef24a commit e6d305e

File tree

6 files changed

+53
-18
lines changed

6 files changed

+53
-18
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ Bug Fixes in This Version
211211
- Clang now reports ``-Wformat`` for bool value and char specifier confusion
212212
in scanf. Fixes
213213
(`#64987 <https://github.com/llvm/llvm-project/issues/64987>`_)
214+
- Support MSVC predefined macro expressions in constant expressions and in
215+
local structs.
214216

215217
Bug Fixes to Compiler Builtins
216218
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Sema/Sema.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3620,10 +3620,6 @@ class Sema final {
36203620
/// in a 'block', this returns the containing context.
36213621
NamedDecl *getCurFunctionOrMethodDecl() const;
36223622

3623-
/// getCurLocalScopeDecl - Return the Decl for either of:
3624-
/// block, lambda, captured statement, function, or nullptr.
3625-
Decl *getCurLocalScopeDecl();
3626-
36273623
/// Add this decl to the scope shadowed decl chains.
36283624
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
36293625

clang/lib/AST/ExprConstant.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7528,6 +7528,9 @@ class ExprEvaluatorBase
75287528
return Error(E);
75297529
}
75307530

7531+
bool VisitPredefinedExpr(const PredefinedExpr *E) {
7532+
return StmtVisitorTy::Visit(E->getFunctionName());
7533+
}
75317534
bool VisitConstantExpr(const ConstantExpr *E) {
75327535
if (E->hasAPValueResult())
75337536
return DerivedSuccess(E->getAPValueResult(), E);

clang/lib/Sema/Sema.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,18 +1491,6 @@ NamedDecl *Sema::getCurFunctionOrMethodDecl() const {
14911491
return nullptr;
14921492
}
14931493

1494-
Decl *Sema::getCurLocalScopeDecl() {
1495-
if (const BlockScopeInfo *BSI = getCurBlock())
1496-
return BSI->TheDecl;
1497-
if (const LambdaScopeInfo *LSI = getCurLambda())
1498-
return LSI->CallOperator;
1499-
if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
1500-
return CSI->TheCapturedDecl;
1501-
if (NamedDecl *ND = getCurFunctionOrMethodDecl())
1502-
return ND;
1503-
return nullptr;
1504-
}
1505-
15061494
LangAS Sema::getDefaultCXXMethodAddrSpace() const {
15071495
if (getLangOpts().OpenCL)
15081496
return getASTContext().getDefaultOpenCLPointeeAddrSpace();

clang/lib/Sema/SemaExpr.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,15 @@ static PredefinedExpr::IdentKind getPredefinedExprKind(tok::TokenKind Kind) {
19041904
}
19051905
}
19061906

1907+
/// getPredefinedExprDecl - Returns Decl of a given DeclContext that can be used
1908+
/// to determine the value of a PredefinedExpr. This can be either a
1909+
/// block, lambda, captured statement, function, otherwise a nullptr.
1910+
static Decl *getPredefinedExprDecl(DeclContext *DC) {
1911+
while (DC && !isa<BlockDecl, CapturedDecl, FunctionDecl, ObjCMethodDecl>(DC))
1912+
DC = DC->getParent();
1913+
return cast_or_null<Decl>(DC);
1914+
}
1915+
19071916
/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
19081917
/// location of the token and the offset of the ud-suffix within it.
19091918
static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
@@ -1984,7 +1993,7 @@ Sema::ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks) {
19841993
// Note: Although function local macros are defined only inside functions,
19851994
// we ensure a valid `CurrentDecl` even outside of a function. This allows
19861995
// expansion of macros into empty string literals without additional checks.
1987-
Decl *CurrentDecl = getCurLocalScopeDecl();
1996+
Decl *CurrentDecl = getPredefinedExprDecl(CurContext);
19881997
if (!CurrentDecl)
19891998
CurrentDecl = Context.getTranslationUnitDecl();
19901999

@@ -3705,7 +3714,7 @@ static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
37053714

37063715
ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
37073716
PredefinedExpr::IdentKind IK) {
3708-
Decl *currentDecl = getCurLocalScopeDecl();
3717+
Decl *currentDecl = getPredefinedExprDecl(CurContext);
37093718
if (!currentDecl) {
37103719
Diag(Loc, diag::ext_predef_outside_function);
37113720
currentDecl = Context.getTranslationUnitDecl();

clang/test/Sema/ms_predefined_expr.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,40 @@ void test_static_assert() {
168168
void test_char_injection(decltype(sizeof('"')), decltype(sizeof("()"))) {
169169
unused("" __FUNCSIG__); // expected-warning{{expansion of predefined identifier '__FUNCSIG__' to a string literal is a Microsoft extension}}
170170
}
171+
172+
void test_in_struct_init() {
173+
struct {
174+
char F[sizeof(__FUNCTION__)];
175+
} s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
176+
177+
struct {
178+
char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
179+
} s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
180+
181+
class C {
182+
public:
183+
struct {
184+
char F[sizeof(__FUNCTION__)];
185+
} s;
186+
} c1 = { { __FUNCTION__ } }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
187+
}
188+
189+
void test_in_constexpr_struct_init() {
190+
struct {
191+
char F[sizeof(__FUNCTION__)];
192+
} constexpr s1 = { __FUNCTION__ }; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
193+
ASSERT_EQ(__FUNCTION__, s1.F);
194+
195+
struct {
196+
char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
197+
} constexpr s2 = { "F:" __FUNCTION__ }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
198+
ASSERT_EQ("F:" __FUNCTION__, s2.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
199+
200+
class C {
201+
public:
202+
struct {
203+
char F[sizeof("F:" __FUNCTION__)]; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
204+
} s;
205+
} constexpr c1 = { { "F:" __FUNCTION__ } }; // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
206+
ASSERT_EQ("F:" __FUNCTION__, c1.s.F); // expected-warning{{expansion of predefined identifier '__FUNCTION__' to a string literal is a Microsoft extension}}
207+
}

0 commit comments

Comments
 (0)