- Fix a crash when expanding a pack as the index of a subscript expression.
- Fix handling of constexpr dynamic memory allocations in template
arguments. (`#62462 <https://github.com/llvm/llvm-project/issues/62462>`_)
+- Some predefined expressions are now treated as string literals in MSVC
+ compatibility mode.
+ (`#114 <https://github.com/llvm/llvm-project/issues/114>`_)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
private:
PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
- StringLiteral *SL);
+ bool IsTransparent, StringLiteral *SL);
explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName);
public:
/// Create a PredefinedExpr.
+ ///
+ /// If IsTransparent, the PredefinedExpr is transparently handled as a
+ /// StringLiteral.
static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L,
- QualType FNTy, IdentKind IK, StringLiteral *SL);
+ QualType FNTy, IdentKind IK, bool IsTransparent,
+ StringLiteral *SL);
/// Create an empty PredefinedExpr.
static PredefinedExpr *CreateEmpty(const ASTContext &Ctx,
return static_cast<IdentKind>(PredefinedExprBits.Kind);
}
+ bool isTransparent() const { return PredefinedExprBits.IsTransparent; }
+
SourceLocation getLocation() const { return PredefinedExprBits.Loc; }
void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; }
return CE->getChosenSubExpr();
}
+ else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
+ if (PE->isTransparent() && PE->getFunctionName())
+ return PE->getFunctionName();
+ }
+
return E;
}
/// for the predefined identifier.
unsigned HasFunctionName : 1;
+ /// True if this PredefinedExpr should be treated as a StringLiteral (for
+ /// MSVC compatibility).
+ unsigned IsTransparent : 1;
+
/// The location of this PredefinedExpr.
SourceLocation Loc;
};
def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
def MicrosoftInaccessibleBase : DiagGroup<"microsoft-inaccessible-base">;
def MicrosoftStaticAssert : DiagGroup<"microsoft-static-assert">;
+def MicrosoftInitFromPredefined : DiagGroup<"microsoft-init-from-predefined">;
// Aliases.
def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
MicrosoftCommentPaste, MicrosoftEndOfFile, MicrosoftStaticAssert,
- MicrosoftInconsistentDllImport]>;
+ MicrosoftInitFromPredefined, MicrosoftInconsistentDllImport]>;
def ClangClPch : DiagGroup<"clang-cl-pch">;
def ext_predef_outside_function : Warning<
"predefined identifier is only valid inside function">,
InGroup<DiagGroup<"predefined-identifier-outside-function">>;
+def ext_init_from_predefined : ExtWarn<
+ "initializing an array from a '%0' predefined identifier is a Microsoft extension">,
+ InGroup<MicrosoftInitFromPredefined>;
def warn_float_overflow : Warning<
"magnitude of floating-point constant too large for type %0; maximum is %1">,
InGroup<LiteralRange>;
return std::move(Err);
return PredefinedExpr::Create(Importer.getToContext(), ToBeginLoc, ToType,
- E->getIdentKind(), ToFunctionName);
+ E->getIdentKind(), E->isTransparent(),
+ ToFunctionName);
}
ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
}
PredefinedExpr::PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK,
- StringLiteral *SL)
+ bool IsTransparent, StringLiteral *SL)
: Expr(PredefinedExprClass, FNTy, VK_LValue, OK_Ordinary) {
PredefinedExprBits.Kind = IK;
assert((getIdentKind() == IK) &&
"IdentKind do not fit in PredefinedExprBitfields!");
bool HasFunctionName = SL != nullptr;
PredefinedExprBits.HasFunctionName = HasFunctionName;
+ PredefinedExprBits.IsTransparent = IsTransparent;
PredefinedExprBits.Loc = L;
if (HasFunctionName)
setFunctionName(SL);
PredefinedExpr *PredefinedExpr::Create(const ASTContext &Ctx, SourceLocation L,
QualType FNTy, IdentKind IK,
- StringLiteral *SL) {
+ bool IsTransparent, StringLiteral *SL) {
bool HasFunctionName = SL != nullptr;
void *Mem = Ctx.Allocate(totalSizeToAlloc<Stmt *>(HasFunctionName),
alignof(PredefinedExpr));
- return new (Mem) PredefinedExpr(L, FNTy, IK, SL);
+ return new (Mem) PredefinedExpr(L, FNTy, IK, IsTransparent, SL);
}
PredefinedExpr *PredefinedExpr::CreateEmpty(const ASTContext &Ctx,
}
}
- return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL);
+ return PredefinedExpr::Create(Context, Loc, ResTy, IK, LangOpts.MicrosoftExt,
+ SL);
}
ExprResult Sema::BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
E = GSE->getResultExpr();
} else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
E = CE->getChosenSubExpr();
+ } else if (PredefinedExpr *PE = dyn_cast<PredefinedExpr>(E)) {
+ E = PE->getFunctionName();
} else {
llvm_unreachable("unexpected expr in string literal init");
}
<< Init->getSourceRange();
}
+ if (S.getLangOpts().MicrosoftExt && Args.size() == 1 &&
+ isa<PredefinedExpr>(Args[0]) && Entity.getType()->isArrayType()) {
+ // Produce a Microsoft compatibility warning when initializing from a
+ // predefined expression since MSVC treats predefined expressions as string
+ // literals.
+ Expr *Init = Args[0];
+ S.Diag(Init->getBeginLoc(), diag::ext_init_from_predefined) << Init;
+ }
+
// OpenCL v2.0 s6.13.11.1. atomic variables can be initialized in global scope
QualType ETy = Entity.getType();
bool HasGlobalAS = ETy.hasAddressSpace() &&
bool HasFunctionName = Record.readInt();
E->PredefinedExprBits.HasFunctionName = HasFunctionName;
E->PredefinedExprBits.Kind = Record.readInt();
+ E->PredefinedExprBits.IsTransparent = Record.readInt();
E->setLocation(readSourceLocation());
if (HasFunctionName)
E->setFunctionName(cast<StringLiteral>(Record.readSubExpr()));
bool HasFunctionName = E->getFunctionName() != nullptr;
Record.push_back(HasFunctionName);
Record.push_back(E->getIdentKind()); // FIXME: stable encoding
+ Record.push_back(E->isTransparent());
Record.AddSourceLocation(E->getLocation());
if (HasFunctionName)
Record.AddStmt(E->getFunctionName());
--- /dev/null
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -x c++ -std=c++20 -emit-module-interface a.h -o a.pcm -fms-extensions -verify
+// RUN: %clang_cc1 -std=c++20 a.cpp -fmodule-file=A=a.pcm -fms-extensions -fsyntax-only -verify
+
+//--- a.h
+
+// expected-no-diagnostics
+
+export module A;
+
+export template <typename T>
+void f() {
+ char a[] = __func__;
+}
+
+//--- a.cpp
+
+// expected-warning@a.h:8 {{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
+
+import A;
+
+void g() {
+ f<int>(); // expected-note {{in instantiation of function template specialization 'f<int>' requested here}}
+}
--- /dev/null
+// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions
+
+void f() {
+ const char a[] = __FUNCTION__; // expected-warning{{initializing an array from a '__FUNCTION__' predefined identifier is a Microsoft extension}}
+ const char b[] = __FUNCDNAME__; // expected-warning{{initializing an array from a '__FUNCDNAME__' predefined identifier is a Microsoft extension}}
+ const char c[] = __FUNCSIG__; // expected-warning{{initializing an array from a '__FUNCSIG__' predefined identifier is a Microsoft extension}}
+ const char d[] = __func__; // expected-warning{{initializing an array from a '__func__' predefined identifier is a Microsoft extension}}
+ const char e[] = __PRETTY_FUNCTION__; // expected-warning{{initializing an array from a '__PRETTY_FUNCTION__' predefined identifier is a Microsoft extension}}
+}
--- /dev/null
+// RUN: %clang_cc1 %s -std=c++17 -fsyntax-only -verify
+// RUN: %clang_cc1 %s -std=c++17 -fsyntax-only -verify -fms-extensions
+
+// expected-no-diagnostics
+
+struct StringRef {
+ StringRef(const char *);
+};
+template <typename T>
+StringRef getTypeName() {
+ StringRef s = __func__;
+}
+