aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-02-25 19:07:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-02-25 19:07:25 +0000
commit7b0060e4423605afe08a9888c47d634442c613a6 (patch)
tree205d9ce60e1b4ccc233928617a0bb9cef30064bf
parent5df36aae6442dbc915e71d1f0339b615af064b1b (diff)
downloadsrc-7b0060e4423605afe08a9888c47d634442c613a6.tar.gz
src-7b0060e4423605afe08a9888c47d634442c613a6.zip
Vendor import of clang release_80 branch r354799:vendor/clang/clang-release_80-r354799
Notes
Notes: svn path=/vendor/clang/dist-release_80/; revision=344537 svn path=/vendor/clang/clang-release_80-r354799/; revision=344538; tag=vendor/clang/clang-release_80-r354799
-rw-r--r--docs/ReleaseNotes.rst122
-rw-r--r--docs/UsersManual.rst2
-rw-r--r--include/clang/AST/Expr.h5
-rw-r--r--lib/CodeGen/CGDecl.cpp14
-rw-r--r--lib/Frontend/TextDiagnostic.cpp2
-rw-r--r--lib/Sema/SemaExpr.cpp26
-rw-r--r--test/CodeGenCXX/trivial-auto-var-init.cpp31
-rw-r--r--test/Misc/diag-format.c44
-rw-r--r--test/Sema/typo-correction.c15
9 files changed, 201 insertions, 60 deletions
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 50bf636a51f4..bdf4bcf70b8b 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,6 +1,6 @@
-=======================================
-Clang 8.0.0 (In-Progress) Release Notes
-=======================================
+=========================
+Clang 8.0.0 Release Notes
+=========================
.. contents::
:local:
@@ -8,16 +8,10 @@ Clang 8.0.0 (In-Progress) Release Notes
Written by the `LLVM Team <https://llvm.org/>`_
-.. warning::
-
- These are in-progress notes for the upcoming Clang 8 release.
- Release notes for previous releases can be found on
- `the Download Page <https://releases.llvm.org/download.html>`_.
-
Introduction
============
-This document contains the release notes for the Clang C/C++/Objective-C
+This document contains the release notes for the Clang C/C++/Objective-C/OpenCL
frontend, part of the LLVM Compiler Infrastructure, release 8.0.0. Here we
describe the status of Clang in some detail, including major
improvements from the previous release and new feature work. For the
@@ -30,11 +24,6 @@ For more information about Clang or LLVM, including information about the
latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
`LLVM Web Site <https://llvm.org>`_.
-Note that if you are reading this file from a Subversion checkout or the
-main Clang web page, this document applies to the *next* release, not
-the current one. To see the release notes for a specific release, please
-see the `releases page <https://llvm.org/releases/>`_.
-
What's New in Clang 8.0.0?
==========================
@@ -50,7 +39,36 @@ Major New Features
profile data captured for one version of a program to be applied
when building another version where symbols have changed (for
example, due to renaming a class or namespace).
- See the :doc:`UsersManual` for details.
+ See the :ref:`UsersManual <profile_remapping>` for details.
+
+- Clang has new options to initialize automatic variables with a pattern. The default is still that automatic variables are uninitialized. This isn't meant to change the semantics of C and C++. Rather, it's meant to be a last resort when programmers inadvertently have some undefined behavior in their code. These options aim to make undefined behavior hurt less, which security-minded people will be very happy about. Notably, this means that there's no inadvertent information leak when:
+
+ * The compiler re-uses stack slots, and a value is used uninitialized.
+
+ * The compiler re-uses a register, and a value is used uninitialized.
+
+ * Stack structs / arrays / unions with padding are copied.
+
+ These options only address stack and register information leaks.
+
+ Caveats:
+
+ * Variables declared in unreachable code and used later aren't initialized. This affects goto statements, Duff's device, and other objectionable uses of switch statements. This should instead be a hard-error in any serious codebase.
+
+ * These options don't affect volatile stack variables.
+
+ * Padding isn't fully handled yet.
+
+ How to use it on the command line:
+
+ * ``-ftrivial-auto-var-init=uninitialized`` (the default)
+
+ * ``-ftrivial-auto-var-init=pattern``
+
+ There is also a new attribute to request a variable to not be initialized, mainly to disable initialization of large stack arrays when deemed too expensive:
+
+ * ``int dont_initialize_me __attribute((uninitialized));``
+
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -131,14 +149,24 @@ Non-comprehensive list of changes in this release
- Improved support for MIPS N32 ABI and MIPS R6 target triples.
+- Clang now includes builtin functions for bitwise rotation of common value
+ sizes, such as: `__builtin_rotateleft32
+ <LanguageExtensions.html#builtin-rotateleft>`_
+
+- Improved optimization for the corresponding MSVC compatibility builtins such
+ as ``_rotl()``.
+
New Compiler Flags
------------------
+- ``-mspeculative-load-hardening`` Clang now has an option to enable
+ Speculative Load Hardening.
+
- ``-fprofile-filter-files=[regexes]`` and ``-fprofile-exclude-files=[regexes]``.
Clang has now options to filter or exclude some files when
instrumenting for gcov-based profiling.
- See the :doc:`UsersManual` for details.
+ See the `UsersManual <UsersManual.html#cmdoption-fprofile-filter-files>`_ for details.
- When using a custom stack alignment, the ``stackrealign`` attribute is now
implicitly set on the main function.
@@ -175,7 +203,9 @@ New Pragmas in Clang
Attribute Changes in Clang
--------------------------
-- ...
+* Clang now supports enabling/disabling speculative load hardening on a
+ per-function basis using the function attribute
+ ``speculative_load_hardening``/``no_speculative_load_hardening``.
Windows Support
---------------
@@ -229,10 +259,60 @@ Objective-C Language Changes in Clang
...
-OpenCL C Language Changes in Clang
-----------------------------------
+OpenCL Kernel Language Changes in Clang
+---------------------------------------
+
+Misc:
+
+- Improved address space support with Clang builtins.
+
+- Improved various diagnostics for vectors with element types from extensions;
+ values used in attributes; duplicate address spaces.
+
+- Allow blocks to capture arrays.
+
+- Allow zero assignment and comparisons between variables of ``queue_t`` type.
+
+- Improved diagnostics of formatting specifiers and argument promotions for
+ vector types in ``printf``.
+
+- Fixed return type of enqueued kernel and pipe builtins.
+
+- Fixed address space of ``clk_event_t`` generated in the IR.
+
+- Fixed address space when passing/returning structs.
+
+Header file fixes:
+
+- Added missing extension guards around several builtin function overloads.
+
+- Fixed serialization support when registering vendor extensions using pragmas.
+
+- Fixed OpenCL version in declarations of builtin functions with sampler-less
+ image accesses.
+
+New vendor extensions added:
+
+- ``cl_intel_planar_yuv``
+
+- ``cl_intel_device_side_avc_motion_estimation``
+
+
+C++ for OpenCL:
+
+- Added support of address space conversions in C style casts.
+
+- Enabled address spaces for references.
+
+- Fixed use of address spaces in templates: address space deduction and diagnostics.
+
+- Changed default address space to work with C++ specific concepts: class members,
+ template parameters, etc.
+
+- Added generic address space by default to the generated hidden 'this' parameter.
+
+- Extend overload ranking rules for address spaces.
-...
ABI Changes in Clang
--------------------
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 7634d24eb5a6..38f7615bf95b 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -1799,6 +1799,8 @@ In these cases, you can use the flag ``-fno-profile-instr-generate`` (or
Note that these flags should appear after the corresponding profile
flags to have an effect.
+.. _profile_remapping:
+
Profile remapping
^^^^^^^^^^^^^^^^^
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 3de73428829b..bf4f3babbd3c 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -2577,6 +2577,11 @@ public:
NumArgs = NewNumArgs;
}
+ /// Bluntly set a new number of arguments without doing any checks whatsoever.
+ /// Only used during construction of a CallExpr in a few places in Sema.
+ /// FIXME: Find a way to remove it.
+ void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; }
+
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
typedef llvm::iterator_range<arg_iterator> arg_range;
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index b98657ffd800..790a8df3d7e4 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -1620,8 +1620,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
bool capturedByInit =
Init && emission.IsEscapingByRef && isCapturedBy(D, Init);
- Address Loc =
- capturedByInit ? emission.Addr : emission.getObjectAddress(*this);
+ bool locIsByrefHeader = !capturedByInit;
+ const Address Loc =
+ locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr;
// Note: constexpr already initializes everything correctly.
LangOptions::TrivialAutoVarInitKind trivialAutoVarInit =
@@ -1637,7 +1638,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
return;
// Only initialize a __block's storage: we always initialize the header.
- if (emission.IsEscapingByRef)
+ if (emission.IsEscapingByRef && !locIsByrefHeader)
Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false);
CharUnits Size = getContext().getTypeSizeInChars(type);
@@ -1745,10 +1746,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
}
llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace());
- if (Loc.getType() != BP)
- Loc = Builder.CreateBitCast(Loc, BP);
-
- emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant);
+ emitStoresForConstant(
+ CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP),
+ isVolatile, Builder, constant);
}
/// Emit an expression as an initializer for an object (variable, field, etc.)
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 35b99b10f94a..8b18fcccb462 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -838,7 +838,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
if (LangOpts.MSCompatibilityVersion &&
!LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
OS << ' ';
- OS << ": ";
+ OS << ':';
break;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index db0c62630a9e..ff9393a56b9c 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -5676,18 +5676,36 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
}
if (!getLangOpts().CPlusPlus) {
+ // Forget about the nulled arguments since typo correction
+ // do not handle them well.
+ TheCall->shrinkNumArgs(Args.size());
// C cannot always handle TypoExpr nodes in builtin calls and direct
// function calls as their argument checking don't necessarily handle
// dependent types properly, so make sure any TypoExprs have been
// dealt with.
ExprResult Result = CorrectDelayedTyposInExpr(TheCall);
if (!Result.isUsable()) return ExprError();
+ CallExpr *TheOldCall = TheCall;
TheCall = dyn_cast<CallExpr>(Result.get());
+ bool CorrectedTypos = TheCall != TheOldCall;
if (!TheCall) return Result;
- // TheCall at this point has max(Args.size(), NumParams) arguments,
- // with extra arguments nulled. We don't want to introduce nulled
- // arguments in Args and so we only take the first Args.size() arguments.
- Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size());
+ Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
+
+ // A new call expression node was created if some typos were corrected.
+ // However it may not have been constructed with enough storage. In this
+ // case, rebuild the node with enough storage. The waste of space is
+ // immaterial since this only happens when some typos were corrected.
+ if (CorrectedTypos && Args.size() < NumParams) {
+ if (Config)
+ TheCall = CUDAKernelCallExpr::Create(
+ Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_RValue,
+ RParenLoc, NumParams);
+ else
+ TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
+ RParenLoc, NumParams, UsesADL);
+ }
+ // We can now handle the nulled arguments for the default arguments.
+ TheCall->setNumArgsUnsafe(std::max<unsigned>(Args.size(), NumParams));
}
// Bail out early if calling a builtin with custom type checking.
diff --git a/test/CodeGenCXX/trivial-auto-var-init.cpp b/test/CodeGenCXX/trivial-auto-var-init.cpp
index 37ff770abf57..0a9ad86c7e2f 100644
--- a/test/CodeGenCXX/trivial-auto-var-init.cpp
+++ b/test/CodeGenCXX/trivial-auto-var-init.cpp
@@ -45,14 +45,35 @@ void test_block() {
// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4
// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8
// PATTERN: %call = call %struct.XYZ* @create(
+using Block = void (^)();
+typedef struct XYZ {
+ Block block;
+} * xyz_t;
void test_block_self_init() {
- using Block = void (^)();
- typedef struct XYZ {
- Block block;
- } * xyz_t;
extern xyz_t create(Block block);
__block xyz_t captured = create(^() {
- (void)captured;
+ used(captured);
+ });
+}
+
+// Capturing with escape after initialization is also an edge case.
+//
+// UNINIT-LABEL: test_block_captures_self_after_init(
+// ZERO-LABEL: test_block_captures_self_after_init(
+// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
+// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4
+// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8
+// ZERO: %call = call %struct.XYZ* @create(
+// PATTERN-LABEL: test_block_captures_self_after_init(
+// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8
+// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4
+// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8
+// PATTERN: %call = call %struct.XYZ* @create(
+void test_block_captures_self_after_init() {
+ extern xyz_t create(Block block);
+ __block xyz_t captured;
+ captured = create(^() {
+ used(captured);
});
}
diff --git a/test/Misc/diag-format.c b/test/Misc/diag-format.c
index bc29894ad03e..b24aeb9356ae 100644
--- a/test/Misc/diag-format.c
+++ b/test/Misc/diag-format.c
@@ -1,30 +1,30 @@
-// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s -check-prefix=DEFAULT
-// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s -check-prefix=DEFAULT
-// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT
+// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT
+// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT
//
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2013
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2015
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015
//
-// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s -check-prefix=VI
+// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=VI
//
-// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015_ORIG
+// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015_ORIG
//
-// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s -check-prefix=NO_COLUMN
+// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=NO_COLUMN
//
-// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK
-// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK
-// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013-FALLBACK
-// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015-FALLBACK
+// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK
+// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK
+// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013-FALLBACK
+// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015-FALLBACK
diff --git a/test/Sema/typo-correction.c b/test/Sema/typo-correction.c
index e7992ac90bb3..73ba265509e4 100644
--- a/test/Sema/typo-correction.c
+++ b/test/Sema/typo-correction.c
@@ -100,3 +100,18 @@ void rdar38642201_caller() {
structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}}
structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}}
}
+
+void PR40286_g(int x, int y);
+void PR40286_h(int x, int y, int z);
+void PR40286_1(int the_value) {
+ PR40286_g(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
+}
+void PR40286_2(int the_value) {
+ PR40286_h(the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
+}
+void PR40286_3(int the_value) {
+ PR40286_h(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
+}
+void PR40286_4(int the_value) { // expected-note {{'the_value' declared here}}
+ PR40286_h(the_value, the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'; did you mean 'the_value'?}}
+}