Skip to content

Commit 856f384

Browse files
committed
[clang] Make predefined expressions string literals under -fms-extensions
MSVC makes these string literals [1][2]. [1] https://godbolt.org/z/6vnTzbExx [2] https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170 Fixes swiftlang#114 Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D146764
1 parent 5545f1b commit 856f384

File tree

14 files changed

+82
-8
lines changed

14 files changed

+82
-8
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ Bug Fixes to C++ Support
416416
initialization.
417417
(`#61567 <https://github.com/llvm/llvm-project/issues/61567>`_)
418418
- Fix a crash when expanding a pack as the index of a subscript expression.
419+
- Some predefined expressions are now treated as string literals in MSVC
420+
compatibility mode.
421+
(`#114 <https://github.com/llvm/llvm-project/issues/114>`_)
419422

420423
Bug Fixes to AST Handling
421424
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/AST/Expr.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,7 +1992,7 @@ class PredefinedExpr final
19921992

19931993
private:
19941994
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
1995-
StringLiteral *SL);
1995+
bool IsTransparent, StringLiteral *SL);
19961996

19971997
explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);
19981998

@@ -2007,8 +2007,12 @@ class PredefinedExpr final
20072007

20082008
public:
20092009
/// Create a PredefinedExpr.
2010+
///
2011+
/// If IsTransparent, the PredefinedExpr is transparently handled as a
2012+
/// StringLiteral.
20102013
static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
2011-
QualType FNTy, IdentKind IK, StringLiteral *SL);
2014+
QualType FNTy, IdentKind IK, bool IsTransparent,
2015+
StringLiteral *SL);
20122016

20132017
/// Create an empty PredefinedExpr.
20142018
static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
@@ -2018,6 +2022,8 @@ class PredefinedExpr final
20182022
return static_cast<IdentKind>(PredefinedExprBits.Kind);
20192023
}
20202024

2025+
bool isTransparent() const { return PredefinedExprBits.IsTransparent; }
2026+
20212027
SourceLocation getLocation() const { return PredefinedExprBits.Loc; }
20222028
void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; }
20232029

clang/include/clang/AST/IgnoreExpr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ inline Expr *IgnoreParensSingleStep(Expr *E) {
166166
return CE->getChosenSubExpr();
167167
}
168168

169+
else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
170+
if (PE->isTransparent())
171+
return PE->getFunctionName();
172+
}
173+
169174
return E;
170175
}
171176

clang/include/clang/AST/Stmt.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,10 @@ class alignas(void *) Stmt {
364364
/// for the predefined identifier.
365365
unsigned HasFunctionName : 1;
366366

367+
/// True if this PredefinedExpr should be treated as a StringLiteral (for
368+
/// MSVC compatibility).
369+
unsigned IsTransparent : 1;
370+
367371
/// The location of this PredefinedExpr.
368372
SourceLocation Loc;
369373
};

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,6 +1190,7 @@ def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">;
11901190
def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
11911191
def MicrosoftInaccessibleBase : DiagGroup<"microsoft-inaccessible-base">;
11921192
def MicrosoftStaticAssert : DiagGroup<"microsoft-static-assert">;
1193+
def MicrosoftInitFromPredefined : DiagGroup<"microsoft-init-from-predefined">;
11931194

11941195
// Aliases.
11951196
def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
@@ -1207,7 +1208,7 @@ def Microsoft : DiagGroup<"microsoft",
12071208
MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
12081209
MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
12091210
MicrosoftCommentPaste, MicrosoftEndOfFile, MicrosoftStaticAssert,
1210-
MicrosoftInconsistentDllImport]>;
1211+
MicrosoftInitFromPredefined, MicrosoftInconsistentDllImport]>;
12111212

12121213
def ClangClPch : DiagGroup<"clang-cl-pch">;
12131214

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ def err_expr_not_string_literal : Error<"expression is not a string literal">;
112112
def ext_predef_outside_function : Warning<
113113
"predefined identifier is only valid inside function">,
114114
InGroup<DiagGroup<"predefined-identifier-outside-function">>;
115+
def ext_init_from_predefined : ExtWarn<
116+
"initializing an array from a '%0' predefined identifier is a Microsoft extension">,
117+
InGroup<MicrosoftInitFromPredefined>;
115118
def warn_float_overflow : Warning<
116119
"magnitude of floating-point constant too large for type %0; maximum is %1">,
117120
InGroup<LiteralRange>;

clang/lib/AST/ASTImporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7068,7 +7068,8 @@ ExpectedStmt ASTNodeImporter::VisitPredefinedExpr(PredefinedExpr *E) {
70687068
return std::move(Err);
70697069

70707070
return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType,
7071-
E->getIdentKind(), ToFunctionName);
7071+
E->getIdentKind(), E->isTransparent(),
7072+
ToFunctionName);
70727073
}
70737074

70747075
ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {

clang/lib/AST/Expr.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -663,13 +663,14 @@ std::string SYCLUniqueStableNameExpr::ComputeName(ASTContext &Context,
663663
}
664664

665665
PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
666-
StringLiteral *SL)
666+
bool IsTransparent, StringLiteral *SL)
667667
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) {
668668
PredefinedExprBits.Kind = IK;
669669
assert((getIdentKind() == IK) &&
670670
"IdentKind do not fit in PredefinedExprBitfields!");
671671
bool HasFunctionName = SL != nullptr;
672672
PredefinedExprBits.HasFunctionName = HasFunctionName;
673+
PredefinedExprBits.IsTransparent = IsTransparent;
673674
PredefinedExprBits.Loc = L;
674675
if (HasFunctionName)
675676
setFunctionName(SL);
@@ -683,11 +684,11 @@ PredefinedExpr::PredefinedExpr(EmptyShell Empty, bool HasFunctionName)
683684

684685
PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
685686
QualType FNTy, IdentKind IK,
686-
StringLiteral *SL) {
687+
bool IsTransparent, StringLiteral *SL) {
687688
bool HasFunctionName = SL != nullptr;
688689
void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
689690
alignof(PredefinedExpr));
690-
return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
691+
return new (Mem) PredefinedExpr(L, FNTy, IK, IsTransparent, SL);
691692
}
692693

693694
PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx,

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3581,7 +3581,8 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
35813581
}
35823582
}
35833583

3584-
return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL);
3584+
return PredefinedExpr::Create(Context, Loc, ResTy, IK, LangOpts.MicrosoftExt,
3585+
SL);
35853586
}
35863587

35873588
ExprResult Sema::BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,

clang/lib/Sema/SemaInit.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ static void updateStringLiteralType(Expr *E, QualType Ty) {
174174
E = GSE->getResultExpr();
175175
} else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
176176
E = CE->getChosenSubExpr();
177+
} else if (PredefinedExpr *PE = dyn_cast<PredefinedExpr>(E)) {
178+
E = PE->getFunctionName();
177179
} else {
178180
llvm_unreachable("unexpected expr in string literal init");
179181
}
@@ -8501,6 +8503,15 @@ ExprResult InitializationSequence::Perform(Sema &S,
85018503
<< Init->getSourceRange();
85028504
}
85038505

8506+
if (S.getLangOpts().MicrosoftExt && Args.size() == 1 &&
8507+
isa<PredefinedExpr>(Args[0]) && Entity.getType()->isArrayType()) {
8508+
// Produce a Microsoft compatibility warning when initializing from a
8509+
// predefined expression since MSVC treats predefined expressions as string
8510+
// literals.
8511+
Expr *Init = Args[0];
8512+
S.Diag(Init->getBeginLoc(), diag::ext_init_from_predefined) << Init;
8513+
}
8514+
85048515
// OpenCL v2.0 s6.13.11.1. atomic variables can be initialized in global scope
85058516
QualType ETy = Entity.getType();
85068517
bool HasGlobalAS = ETy.hasAddressSpace() &&

0 commit comments

Comments
 (0)