diff --git a/clang/include/clang/Testing/TestClangConfig.h b/clang/include/clang/Testing/TestClangConfig.h --- a/clang/include/clang/Testing/TestClangConfig.h +++ b/clang/include/clang/Testing/TestClangConfig.h @@ -58,9 +58,9 @@ Language == Lang_CXX14; } - bool hasDelayedTemplateParsing() const { - return Target == "x86_64-pc-win32-msvc"; - } + bool isWin32() const { return Target == "x86_64-pc-win32-msvc"; } + + bool hasDelayedTemplateParsing() const { return isWin32(); } std::vector getCommandLineArgs() const { std::vector Result = getCommandLineArgsForTesting(Language); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3552,9 +3552,10 @@ QualType ResTy; StringLiteral *SL = nullptr; - if (cast(currentDecl)->isDependentContext()) + if (cast(currentDecl)->isDependentContext()) { ResTy = Context.DependentTy; - else { + return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL); + } else { // Pre-defined identifiers are of type char[x], where x is the length of // the string. auto Str = PredefinedExpr::ComputeName(IK, currentDecl); @@ -3582,6 +3583,11 @@ } } + // MSVC treats all predefined expressions as string literals rather than char + // arrays. + if (LangOpts.MicrosoftExt) + return SL; + return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL); } diff --git a/clang/test/CodeGen/predefined-expr.c b/clang/test/CodeGen/predefined-expr.c --- a/clang/test/CodeGen/predefined-expr.c +++ b/clang/test/CodeGen/predefined-expr.c @@ -1,16 +1,27 @@ -// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -fms-extensions %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s - -// CHECK: @__func__.plainFunction = private unnamed_addr constant [14 x i8] c"plainFunction\00" -// CHECK: @__PRETTY_FUNCTION__.plainFunction = private unnamed_addr constant [25 x i8] c"void plainFunction(void)\00" -// CHECK: @__func__.externFunction = private unnamed_addr constant [15 x i8] c"externFunction\00" -// CHECK: @__PRETTY_FUNCTION__.externFunction = private unnamed_addr constant [26 x i8] c"void externFunction(void)\00" -// CHECK: @__func__.privateExternFunction = private unnamed_addr constant [22 x i8] c"privateExternFunction\00" -// CHECK: @__PRETTY_FUNCTION__.privateExternFunction = private unnamed_addr constant [33 x i8] c"void privateExternFunction(void)\00" -// CHECK: @__func__.__captured_stmt = private unnamed_addr constant [25 x i8] c"functionWithCapturedStmt\00" -// CHECK: @__PRETTY_FUNCTION__.__captured_stmt = private unnamed_addr constant [36 x i8] c"void functionWithCapturedStmt(void)\00" -// CHECK: @__func__.staticFunction = private unnamed_addr constant [15 x i8] c"staticFunction\00" -// CHECK: @__PRETTY_FUNCTION__.staticFunction = private unnamed_addr constant [26 x i8] c"void staticFunction(void)\00" +// RUN: %clang_cc1 %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s --check-prefix=ITANIUM +// RUN: %clang_cc1 -fms-extensions %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s --check-prefix=MS + +// ITANIUM: @__func__.plainFunction = private unnamed_addr constant [14 x i8] c"plainFunction\00" +// ITANIUM: @__PRETTY_FUNCTION__.plainFunction = private unnamed_addr constant [25 x i8] c"void plainFunction(void)\00" +// ITANIUM: @__func__.externFunction = private unnamed_addr constant [15 x i8] c"externFunction\00" +// ITANIUM: @__PRETTY_FUNCTION__.externFunction = private unnamed_addr constant [26 x i8] c"void externFunction(void)\00" +// ITANIUM: @__func__.privateExternFunction = private unnamed_addr constant [22 x i8] c"privateExternFunction\00" +// ITANIUM: @__PRETTY_FUNCTION__.privateExternFunction = private unnamed_addr constant [33 x i8] c"void privateExternFunction(void)\00" +// ITANIUM: @__func__.__captured_stmt = private unnamed_addr constant [25 x i8] c"functionWithCapturedStmt\00" +// ITANIUM: @__PRETTY_FUNCTION__.__captured_stmt = private unnamed_addr constant [36 x i8] c"void functionWithCapturedStmt(void)\00" +// ITANIUM: @__func__.staticFunction = private unnamed_addr constant [15 x i8] c"staticFunction\00" +// ITANIUM: @__PRETTY_FUNCTION__.staticFunction = private unnamed_addr constant [26 x i8] c"void staticFunction(void)\00" + +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [14 x i8] c"plainFunction\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [25 x i8] c"void plainFunction(void)\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [15 x i8] c"externFunction\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [26 x i8] c"void externFunction(void)\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [22 x i8] c"privateExternFunction\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [33 x i8] c"void privateExternFunction(void)\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [25 x i8] c"functionWithCapturedStmt\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [36 x i8] c"void functionWithCapturedStmt(void)\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [15 x i8] c"staticFunction\00" +// MS: @.str.{{[0-9]+}} = private unnamed_addr constant [26 x i8] c"void staticFunction(void)\00" int printf(const char *, ...); diff --git a/clang/test/Sema/ms_predefined_expr.cpp b/clang/test/Sema/ms_predefined_expr.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Sema/ms_predefined_expr.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -fsyntax-only -Wmicrosoft -verify -fms-extensions +// expected-no-diagnostics + +void f(void) { + const char a[] = __FUNCTION__; + const char b[] = __FUNCDNAME__; + const char c[] = __FUNCSIG__; + const char d[] = __func__; + const char e[] = __PRETTY_FUNCTION__; +} diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -509,6 +509,11 @@ } TEST_P(ImportExpr, ImportPredefinedExpr) { + // Predefined expressions are string literals under Microsoft extensions. + if (std::find(GetParam().begin(), GetParam().end(), "-fms-compatibility") != + GetParam().end()) + return; + MatchVerifier Verifier; // __func__ expands as StringLiteral("declToImport") testImport("void declToImport() { (void)__func__; }", Lang_CXX03, "", diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -1058,6 +1058,10 @@ } TEST_P(ASTMatchersTest, PredefinedExpr) { + // Predefined expressions are string literals under Microsoft extensions. + if (GetParam().isWin32()) + return; + // __func__ expands as StringLiteral("foo") EXPECT_TRUE(matches("void foo() { __func__; }", predefinedExpr(hasType(asString("const char[4]")),