Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -306,12 +306,17 @@ Non-comprehensive list of changes in this release

- Clang now rejects the invalid use of ``constexpr`` with ``auto`` and an explicit type in C. (#GH163090)

- ``_MSVC_TRADITIONAL`` is now defined to ``0`` when using ``-fms-extensions``. The charize operator and ``/##/`` paste trick remain as supported extensions, which is a divergence from MSVC.

New Compiler Flags
------------------
- New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
- New option ``-fsanitize-debug-trap-reasons=`` added to control emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
- New options for enabling allocation token instrumentation: ``-fsanitize=alloc-token``, ``-falloc-token-max=``, ``-fsanitize-alloc-token-fast-abi``, ``-fsanitize-alloc-token-extended``.
- The ``-resource-dir`` option is now displayed in the list of options shown by ``--help``.
- The ``-fms-preprocessor-compat`` flag has been added to control whether full emulation of the MSVC traditional preprocessor is performed.
Using ``-fms-preprocessor-compat`` will define ``_MSVC_TRADITIONAL`` to ``1``, and enables the full set of functionality required to emulate
the old MSVC character buffer based preprocessor as closely as possible. It is enabled by default when using ``-fms-compatibility``, which is the case for clang-cl.

Lanai Support
^^^^^^^^^^^^^^
Expand Down Expand Up @@ -581,6 +586,8 @@ Android Support
Windows Support
^^^^^^^^^^^^^^^

- clang-cl now supports ``/Zc:preprocessor``, which is an alias for ``-fno-ms-preprocessor-compat``.

LoongArch Support
^^^^^^^^^^^^^^^^^
- Enable linker relaxation by default for loongarch64.
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5055,6 +5055,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
/Zc:trigraphs Enable trigraphs
/Zc:twoPhase- Disable two-phase name lookup in templates
/Zc:twoPhase Enable two-phase name lookup in templates
/Zc:preprocessor- Use the traditional (non-conforming) preprocessor (default)
/Zc:preprocessor Use the standard conforming preprocessor
/Zi Alias for /Z7. Does not produce PDBs.
/Zl Don't mention any default libraries in the object file
/Zp Set the default maximum struct packing alignment to 1
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ LANGOPT(HIPStdParInterposeAlloc, 1, 0, NotCompatible, "Replace allocations / dea

LANGOPT(OpenACC , 1, 0, NotCompatible, "OpenACC Enabled")

LANGOPT(MSVCPreprocessor , 1, 0, NotCompatible, "Fully emulate the Microsoft Visual C++ traditional (non-conforming) preprocessor")
LANGOPT(MSVCEnableStdcMacro , 1, 0, NotCompatible, "Define __STDC__ with '-fms-compatibility'")
LANGOPT(SizedDeallocation , 1, 0, NotCompatible, "sized deallocation")
LANGOPT(AlignedAllocation , 1, 0, NotCompatible, "aligned allocation")
Expand Down
20 changes: 20 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,26 @@ class LangOptions : public LangOptionsBase {
return MSCompatibilityVersion >= MajorVersion * 100000U;
}

/// Returns true if we want to enable lightweight Microsoft preprocessor
/// extensions.
/// Historically, MicrosoftExt and MSVCCompat enabled different extensions
/// to the preprocessor, but we want to disable a majority of them when
/// MSVCPreprocessor is set to false.
bool wantsMSVCPreprocessorExtensions() const {
// If we want full compatibility then we need the extensions
if (MSVCPreprocessor)
return true;
// If MS extensions are turned off, we don't want the extensions
if (!MicrosoftExt)
return false;
// If we're in full MSVC compat mode, we know MSVCPreprocessor is false,
// thus, we don't want the extensions
if (MSVCCompat)
return false;
// We just want lightweight extensions
return true;
}

bool isOverflowPatternExcluded(OverflowPatternExclusionKind Kind) const {
if (OverflowPatternExclusionMask & OverflowPatternExclusionKind::None)
return false;
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3238,6 +3238,10 @@ def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>,
Visibility<[ClangOption, CC1Option, CLOption]>,
HelpText<"Enable full Microsoft Visual C++ compatibility">,
MarshallingInfoFlag<LangOpts<"MSVCCompat">>;
def fms_preprocessor_compat : Flag<["-"], "fms-preprocessor-compat">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Enable full emulation of the traditional MSVC preprocessor">,
MarshallingInfoFlag<LangOpts<"MSVCPreprocessor">>;
def fms_define_stdc : Flag<["-"], "fms-define-stdc">, Group<f_Group>,
Visibility<[ClangOption, CC1Option, CLOption]>,
HelpText<"Define '__STDC__' to '1' in MSVC Compatibility mode">,
Expand Down Expand Up @@ -3614,6 +3618,8 @@ def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>,
Visibility<[ClangOption, CLOption]>;
def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>,
Visibility<[ClangOption, CLOption]>;
def fno_ms_preprocessor_compat : Flag<["-"], "fno-ms-preprocessor-compat">, Group<f_Group>,
Visibility<[ClangOption]>;
def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group<f_Group>;
def fno_objc_weak : Flag<["-"], "fno-objc-weak">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>;
Expand Down Expand Up @@ -9123,6 +9129,12 @@ def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">,
Alias<vtordisp_mode_EQ>;
def _SLASH_X : CLFlag<"X">,
HelpText<"Do not add %INCLUDE% to include search path">, Alias<nostdlibinc>;
def _SLASH_Zc_preprocessor : CLFlag<"Zc:preprocessor">,
HelpText<"Use the standard conforming preprocessor">,
Alias<fno_ms_preprocessor_compat>;
def _SLASH_Zc_preprocessor_ : CLFlag<"Zc:preprocessor-">,
HelpText<"Use the traditional (non-conforming) preprocessor (default)">,
Alias<fms_preprocessor_compat>;
def _SLASH_Zc___STDC__ : CLFlag<"Zc:__STDC__">,
HelpText<"Define __STDC__">,
Alias<fms_define_stdc>;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7056,6 +7056,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!types::isCXX(Input.getType()) &&
Args.hasArg(options::OPT_fms_define_stdc))
CmdArgs.push_back("-fms-define-stdc");
// FIXME: This should be disabled by default in C11 and newer.
if (Args.hasFlag(options::OPT_fms_preprocessor_compat,
options::OPT_fno_ms_preprocessor_compat, true))
CmdArgs.push_back("-fms-preprocessor-compat");
}

if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode() &&
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,17 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
}
}

if (LangOpts.MSVCPreprocessor) {
Builder.defineMacro("_MSVC_TRADITIONAL", "1");
} else if (LangOpts.MicrosoftExt) {
// Note: when set to 0 this macro implies, under cl.exe, that the
// charize operator and /##/ no longer function as they used to.
// However, we have special code that cleanly deals with these patterns,
// so we'll allow them to exist as extensions, even though we are stating
// that we do not support the "traditional" preprocessor.
Builder.defineMacro("_MSVC_TRADITIONAL", "0");
}

// Macros to help identify the narrow and wide character sets
// FIXME: clang currently ignores -fexec-charset=. If this changes,
// then this may need to be updated.
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Lex/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2181,7 +2181,7 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,

if (!IsUDSuffix) {
if (!isLexingRawMode())
Diag(CurPtr, LangOpts.MSVCCompat
Diag(CurPtr, LangOpts.MSVCPreprocessor
? diag::ext_ms_reserved_user_defined_literal
: diag::ext_reserved_user_defined_literal)
<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
Expand Down Expand Up @@ -4217,7 +4217,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
Kind = tok::hashhash; // '%:%:' -> '##'
CurPtr = ConsumeChar(ConsumeChar(CurPtr, SizeTmp, Result),
SizeTmp2, Result);
} else if (Char == '@' && LangOpts.MicrosoftExt) {// %:@ -> #@ -> Charize
} else if (Char == '@' && LangOpts.wantsMSVCPreprocessorExtensions()) {// %:@ -> #@ -> Charize
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
if (!isLexingRawMode())
Diag(BufferPtr, diag::ext_charize_microsoft);
Expand Down Expand Up @@ -4405,7 +4405,7 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
if (Char == '#') {
Kind = tok::hashhash;
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
} else if (Char == '@' && LangOpts.MicrosoftExt) { // #@ -> Charize
} else if (Char == '@' && LangOpts.wantsMSVCPreprocessorExtensions()) { // #@ -> Charize
Kind = tok::hashat;
if (!isLexingRawMode())
Diag(BufferPtr, diag::ext_charize_microsoft);
Expand Down
14 changes: 7 additions & 7 deletions clang/lib/Lex/TokenLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs(
// In Microsoft-compatibility mode, a comma is removed in the expansion
// of " ... , __VA_ARGS__ " if __VA_ARGS__ is empty. This extension is
// not supported by gcc.
if (!HasPasteOperator && !PP.getLangOpts().MSVCCompat)
if (!HasPasteOperator && !PP.getLangOpts().MSVCPreprocessor)
return false;

// GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if
Expand Down Expand Up @@ -467,7 +467,7 @@ void TokenLexer::ExpandFunctionArguments() {
// behavior by not considering single commas from nested macro
// expansions as argument separators. Set a flag on the token so we can
// test for this later when the macro expansion is processed.
if (PP.getLangOpts().MSVCCompat && NumToks == 1 &&
if (PP.getLangOpts().MSVCPreprocessor && NumToks == 1 &&
ResultToks.back().is(tok::comma))
ResultToks.back().setFlag(Token::IgnoredComma);

Expand Down Expand Up @@ -653,7 +653,7 @@ bool TokenLexer::Lex(Token &Tok) {
// Special processing of L#x macros in -fms-compatibility mode.
// Microsoft compiler is able to form a wide string literal from
// 'L#macro_arg' construct in a function-like macro.
(PP.getLangOpts().MSVCCompat &&
(PP.getLangOpts().MSVCPreprocessor &&
isWideStringLiteralFromMacro(Tok, Tokens[CurTokenIdx])))) {
// When handling the microsoft /##/ extension, the final token is
// returned by pasteTokens, not the pasted token.
Expand Down Expand Up @@ -732,15 +732,15 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,
unsigned int &CurIdx) {
assert(CurIdx > 0 && "## can not be the first token within tokens");
assert((TokenStream[CurIdx].is(tok::hashhash) ||
(PP.getLangOpts().MSVCCompat &&
(PP.getLangOpts().MSVCPreprocessor &&
isWideStringLiteralFromMacro(LHSTok, TokenStream[CurIdx]))) &&
"Token at this Index must be ## or part of the MSVC 'L "
"#macro-arg' pasting pair");

// MSVC: If previous token was pasted, this must be a recovery from an invalid
// paste operation. Ignore spaces before this token to mimic MSVC output.
// Required for generating valid UUID strings in some MS headers.
if (PP.getLangOpts().MicrosoftExt && (CurIdx >= 2) &&
if (PP.getLangOpts().wantsMSVCPreprocessorExtensions() && (CurIdx >= 2) &&
TokenStream[CurIdx - 2].is(tok::hashhash))
LHSTok.clearFlag(Token::LeadingSpace);

Expand Down Expand Up @@ -854,8 +854,8 @@ bool TokenLexer::pasteTokens(Token &LHSTok, ArrayRef<Token> TokenStream,

// Test for the Microsoft extension of /##/ turning into // here on the
// error path.
if (PP.getLangOpts().MicrosoftExt && LHSTok.is(tok::slash) &&
RHS.is(tok::slash)) {
if (PP.getLangOpts().wantsMSVCPreprocessorExtensions() &&
LHSTok.is(tok::slash) && RHS.is(tok::slash)) {
HandleMicrosoftCommentPaste(LHSTok, Loc);
return true;
}
Expand Down
6 changes: 6 additions & 0 deletions clang/test/Driver/cl-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,12 @@
// RUN: %clang_cl -c -### /std:clatest -- %s 2>&1 | FileCheck -check-prefix CHECK-CLATEST %s
// CHECK-CLATEST: -std=c23

// RUN: %clang_cl -c -### /Zc:preprocessor- -- %s 2>&1 | FileCheck -check-prefix CHECK-ZC-PREPROCESSOR-NO %s
// CHECK-ZC-PREPROCESSOR-NO: -fms-preprocessor-compat

// RUN: %clang_cl -c -### /Zc:preprocessor -- %s 2>&1 | FileCheck -check-prefix CHECK-ZC-PREPROCESSOR %s
// CHECK-ZC-PREPROCESSOR-NOT: -fms-preprocessor-compat

// For some warning ids, we can map from MSVC warning to Clang warning.
// RUN: %clang_cl -wd4005 -wd4100 -wd4910 -wd4996 -wd12345678 -### -- %s 2>&1 | FileCheck -check-prefix=Wno %s
// Wno: "-cc1"
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Lexer/ms-compatibility.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -E -fms-compatibility %s | FileCheck --check-prefix=CHECK-MS-COMPAT %s
// RUN: %clang_cc1 -E -fms-preprocessor-compat %s | FileCheck --check-prefix=CHECK-MS-COMPAT %s
// RUN: %clang_cc1 -E %s | FileCheck --check-prefix=CHECK-NO-MS-COMPAT %s

#define FN(x) L#x
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Preprocessor/macro_fn_comma_swallow2.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// RUN: %clang_cc1 -E -std=c11 %s | FileCheck -check-prefix=C99 -strict-whitespace %s
// RUN: %clang_cc1 -E -x c++ %s | FileCheck -check-prefix=GCC -strict-whitespace %s
// RUN: %clang_cc1 -E -std=gnu99 %s | FileCheck -check-prefix=GCC -strict-whitespace %s
// RUN: %clang_cc1 -E -fms-compatibility %s | FileCheck -check-prefix=MS -strict-whitespace %s
// RUN: %clang_cc1 -E -fms-preprocessor-compat %s | FileCheck -check-prefix=MS -strict-whitespace %s
// RUN: %clang_cc1 -E -DNAMED %s | FileCheck -check-prefix=GCC -strict-whitespace %s
// RUN: %clang_cc1 -E -std=c99 -DNAMED %s | FileCheck -check-prefix=C99 -strict-whitespace %s

Expand Down
2 changes: 1 addition & 1 deletion clang/test/Preprocessor/microsoft-ext.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -E -fms-compatibility %s -o %t
// RUN: %clang_cc1 -E -fms-preprocessor-compat %s -o %t
// RUN: FileCheck %s < %t

# define M2(x, y) x + y
Expand Down
36 changes: 36 additions & 0 deletions clang/test/Preprocessor/microsoft-preprocessor-compat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This test verifies that _MSVC_TRADITIONAL is defined under the right
// circumstances, microsoft-ext.c is responsible for testing the implementation
// details of the traditional preprocessor.
// FIXME: C11 should eventually use the conforming preprocessor by default.
//
// RUN: %clang_cc1 -E %s | FileCheck --check-prefix=CHECK-DEFAULT %s
// RUN: %clang_cc1 -E -fms-extensions %s | FileCheck --check-prefix=CHECK-MS-EXT %s
// RUN: %clang -E -fms-compatibility %s | FileCheck --check-prefix=CHECK-MS-COMPAT %s
// RUN: %clang_cc1 -E -fms-preprocessor-compat %s | FileCheck --check-prefix=CHECK-MS-PREPRO-COMPAT %s
// RUN: %clang_cl -E %s | FileCheck --check-prefix=CHECK-CL %s
// RUN: %clang_cl -E /std:c11 %s | FileCheck --check-prefix=CHECK-C11 %s
// RUN: %clang_cl -E /Zc:preprocessor %s | FileCheck --check-prefix=CHECK-ZC-PREPRO %s
// RUN: %clang_cl -E /clang:-fno-ms-preprocessor-compat %s | FileCheck --check-prefix=CHECK-NO-PREPRO-COMPAT %s

typedef enum {
NOT_DEFINED,
IS_ZERO,
IS_ONE
} State;

#if !defined(_MSVC_TRADITIONAL)
State state = NOT_DEFINED;
#elif _MSVC_TRADITIONAL == 0
State state = IS_ZERO;
#elif _MSVC_TRADITIONAL == 1
State state = IS_ONE;
#endif

// CHECK-DEFAULT: State state = NOT_DEFINED;
// CHECK-MS-EXT: State state = IS_ZERO;
// CHECK-MS-COMPAT: State state = IS_ONE;
// CHECK-MS-PREPRO-COMPAT: State state = IS_ONE;
// CHECK-CL: State state = IS_ONE;
// CHECK-C11: State state = IS_ONE;
// CHECK-ZC-PREPRO: State state = IS_ZERO;
// CHECK-NO-PREPRO-COMPAT: State state = IS_ZERO;