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
This commit is contained in:
parent
4cef24a886
commit
e6d305e64f
@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -3620,10 +3620,6 @@ public:
|
||||
/// 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);
|
||||
|
||||
|
||||
@ -7528,6 +7528,9 @@ public:
|
||||
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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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}}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user