Rename language option MicrosoftMode to MSVCCompat

There's been long-standing confusion over the role of these two options. This
commit makes the necessary changes to differentiate them clearly, following up
from r198936.

MicrosoftExt (aka. fms-extensions):
 Enable largely unobjectionable Microsoft language extensions to ease
 portability. This mode, also supported by gcc, is used for building software
 like FreeBSD and Linux kernel extensions that share code with Windows drivers.

MSVCCompat (aka. -fms-compatibility, formerly MicrosoftMode):
 Turn on a special mode supporting 'heinous' extensions for drop-in
 compatibility with the Microsoft Visual C++ product. Standards-compilant C and
 C++ code isn't guaranteed to work in this mode. Implies MicrosoftExt.

Note that full -fms-compatibility mode is currently enabled by default on the
Windows target, which may need tuning to serve as a reasonable default.

See cfe-commits for the full discourse, thread 'r198497 - Move MS predefined
type_info out of InitializePredefinedMacros'

No change in behaviour.

llvm-svn: 199209
This commit is contained in:
Alp Toker 2014-01-14 12:51:41 +00:00
parent 8fc32f01dc
commit bfa3934f27
20 changed files with 46 additions and 48 deletions

View File

@ -44,7 +44,7 @@
LANGOPT(C99 , 1, 0, "C99")
LANGOPT(C11 , 1, 0, "C11")
LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions")
LANGOPT(MicrosoftMode , 1, 0, "Microsoft Visual C++ full compatibility mode")
LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode")
LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks")
LANGOPT(Borland , 1, 0, "Borland extensions")
LANGOPT(CPlusPlus , 1, 0, "C++")

View File

@ -7808,7 +7808,7 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) {
if (!FD->isInlined())
return External;
if ((!getLangOpts().CPlusPlus && !getLangOpts().MicrosoftMode) ||
if ((!getLangOpts().CPlusPlus && !getLangOpts().MSVCCompat) ||
FD->hasAttr<GNUInlineAttr>()) {
// GNU or C99 inline semantics. Determine whether this symbol should be
// externally visible.

View File

@ -3030,7 +3030,7 @@ Expr::NullPointerConstantKind
Expr::isNullPointerConstant(ASTContext &Ctx,
NullPointerConstantValueDependence NPC) const {
if (isValueDependent() &&
(!Ctx.getLangOpts().CPlusPlus11 || Ctx.getLangOpts().MicrosoftMode)) {
(!Ctx.getLangOpts().CPlusPlus11 || Ctx.getLangOpts().MSVCCompat)) {
switch (NPC) {
case NPC_NeverValueDependent:
llvm_unreachable("Unexpected value dependent expression!");
@ -3116,8 +3116,7 @@ Expr::isNullPointerConstant(ASTContext &Ctx,
const IntegerLiteral *Lit = dyn_cast<IntegerLiteral>(this);
if (Lit && !Lit->getValue())
return NPCK_ZeroLiteral;
else if (!Ctx.getLangOpts().MicrosoftMode ||
!isCXX98IntegralConstantExpr(Ctx))
else if (!Ctx.getLangOpts().MSVCCompat || !isCXX98IntegralConstantExpr(Ctx))
return NPCK_NotNull;
} else {
// If we have an integer constant expression, we need to *evaluate* it and

View File

@ -139,8 +139,8 @@ static void AddKeyword(StringRef Keyword,
else if (LangOpts.ObjC2 && (Flags & KEYARC)) AddResult = 2;
else if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) AddResult = 3;
// Don't add this keyword under MicrosoftMode.
if (LangOpts.MicrosoftMode && (Flags & KEYNOMS))
// Don't add this keyword under MSVCCompat.
if (LangOpts.MSVCCompat && (Flags & KEYNOMS))
return;
// Don't add this keyword if disabled in this language.
if (AddResult == 0) return;

View File

@ -1305,7 +1305,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
Opts.MicrosoftExt
= Args.hasArg(OPT_fms_extensions) || Args.hasArg(OPT_fms_compatibility);
Opts.MicrosoftMode = Args.hasArg(OPT_fms_compatibility);
Opts.MSVCCompat = Args.hasArg(OPT_fms_compatibility);
Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt;
Opts.MSCVersion = getLastArgIntValue(Args, OPT_fmsc_version, 0, Diags);
Opts.Borland = Args.hasArg(OPT_fborland_extensions);

View File

@ -300,7 +300,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
const LangOptions &LangOpts,
const FrontendOptions &FEOpts,
MacroBuilder &Builder) {
if (!LangOpts.MicrosoftMode && !LangOpts.TraditionalCPP)
if (!LangOpts.MSVCCompat && !LangOpts.TraditionalCPP)
Builder.defineMacro("__STDC__");
if (LangOpts.Freestanding)
Builder.defineMacro("__STDC_HOSTED__", "0");
@ -399,7 +399,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
+ getClangFullRepositoryVersion() + "\"");
#undef TOSTR
#undef TOSTR2
if (!LangOpts.MicrosoftMode) {
if (!LangOpts.MSVCCompat) {
// Currently claim to be compatible with GCC 4.2.1-5621, but only if we're
// not compiling for MSVC compatibility
Builder.defineMacro("__GNUC_MINOR__", "2");

View File

@ -1682,10 +1682,10 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
if (!IsUDSuffix) {
if (!isLexingRawMode())
Diag(CurPtr, getLangOpts().MicrosoftMode ?
diag::ext_ms_reserved_user_defined_literal :
diag::ext_reserved_user_defined_literal)
<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
Diag(CurPtr, getLangOpts().MSVCCompat
? diag::ext_ms_reserved_user_defined_literal
: diag::ext_reserved_user_defined_literal)
<< FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
return CurPtr;
}

View File

@ -162,7 +162,7 @@ void Preprocessor::ReadMacroName(Token &MacroNameTok, char isDefineUndef) {
const IdentifierInfo &Info = Identifiers.get(Spelling);
// Allow #defining |and| and friends in microsoft mode.
if (Info.isCPlusPlusOperatorKeyword() && getLangOpts().MicrosoftMode) {
if (Info.isCPlusPlusOperatorKeyword() && getLangOpts().MSVCCompat) {
MacroNameTok.setIdentifierInfo(getIdentifierInfo(Spelling));
return;
}
@ -582,7 +582,7 @@ const FileEntry *Preprocessor::LookupFile(
// MSVC searches the current include stack from top to bottom for
// headers included by quoted include directives.
// See: http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
if (LangOpts.MicrosoftMode && !isAngled) {
if (LangOpts.MSVCCompat && !isAngled) {
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1];
if (IsFileLexer(ISEntry))
@ -1712,7 +1712,7 @@ void Preprocessor::HandleMicrosoftImportDirective(Token &Tok) {
void Preprocessor::HandleImportDirective(SourceLocation HashLoc,
Token &ImportTok) {
if (!LangOpts.ObjC1) { // #import is standard for ObjC.
if (LangOpts.MicrosoftMode)
if (LangOpts.MSVCCompat)
return HandleMicrosoftImportDirective(ImportTok);
Diag(ImportTok, diag::ext_pp_import_directive);
}

View File

@ -133,7 +133,7 @@ static bool MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks,
// 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().MicrosoftMode)
if (!HasPasteOperator && !PP.getLangOpts().MSVCCompat)
return false;
// GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if
@ -282,7 +282,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().MicrosoftMode && NumToks == 1 &&
if (PP.getLangOpts().MSVCCompat && NumToks == 1 &&
ResultToks.back().is(tok::comma))
ResultToks.back().setFlag(Token::IgnoredComma);

View File

@ -1582,7 +1582,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
// We will consume the typedef token here and put it back after we have
// parsed the first identifier, transforming it into something more like:
// typename T_::D typedef D;
if (getLangOpts().MicrosoftMode && NextToken().is(tok::kw_typedef)) {
if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) {
Token TypedefToken;
PP.Lex(TypedefToken);
bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType);

View File

@ -752,7 +752,7 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
SmallVector<unsigned, 10> ToScopesError;
SmallVector<unsigned, 10> ToScopesWarning;
for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) {
if (S.getLangOpts().MicrosoftMode && JumpDiagWarning != 0 &&
if (S.getLangOpts().MSVCCompat && JumpDiagWarning != 0 &&
IsMicrosoftJumpWarning(JumpDiagError, Scopes[I].InDiag))
ToScopesWarning.push_back(I);
else if (IsCXX98CompatWarning(S, Scopes[I].InDiag))

View File

@ -178,7 +178,7 @@ void Sema::Initialize() {
}
// Initialize Microsoft "predefined C++ types".
if (PP.getLangOpts().MicrosoftMode && PP.getLangOpts().CPlusPlus) {
if (PP.getLangOpts().MSVCCompat && PP.getLangOpts().CPlusPlus) {
if (IdResolver.begin(&Context.Idents.get("type_info")) == IdResolver.end())
PushOnScopeChains(Context.buildImplicitRecord("type_info", TTK_Class),
TUScope);

View File

@ -797,7 +797,7 @@ static AccessResult HasAccess(Sema &S,
// Emulate a MSVC bug where the creation of pointer-to-member
// to protected member of base class is allowed but only from
// static member functions.
if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
if (S.getLangOpts().MSVCCompat && !EC.Functions.empty())
if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
if (MD->isStatic()) return AR_accessible;
@ -1422,7 +1422,7 @@ static AccessResult CheckEffectiveAccess(Sema &S,
AccessTarget &Entity) {
assert(Entity.getAccess() != AS_public && "called for public access!");
if (S.getLangOpts().MicrosoftMode &&
if (S.getLangOpts().MSVCCompat &&
IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
return AR_accessible;

View File

@ -484,7 +484,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// FIXME: Deal with ambiguities cleanly.
if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MicrosoftMode) {
if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MSVCCompat) {
// We haven't found anything, and we're not recovering from a
// different kind of error, so look for typos.
DeclarationName Name = Found.getLookupName();
@ -646,7 +646,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
// public:
// void foo() { D::foo2(); }
// };
if (getLangOpts().MicrosoftMode) {
if (getLangOpts().MSVCCompat) {
DeclContext *DC = LookupCtx ? LookupCtx : CurContext;
if (DC->isDependentContext() && DC->isFunctionOrMethod()) {
SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc);

View File

@ -467,7 +467,7 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
<< II << DC << SS->getRange();
else if (isDependentScopeSpecifier(*SS)) {
unsigned DiagID = diag::err_typename_missing;
if (getLangOpts().MicrosoftMode && isMicrosoftMissingTypename(SS, S))
if (getLangOpts().MSVCCompat && isMicrosoftMissingTypename(SS, S))
DiagID = diag::warn_typename_missing;
Diag(SS->getRange().getBegin(), DiagID)
@ -10488,7 +10488,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
UPPC_FixedUnderlyingType))
EnumUnderlying = Context.IntTy.getTypePtr();
} else if (getLangOpts().MicrosoftMode)
} else if (getLangOpts().MSVCCompat)
// Microsoft enums are always of int type.
EnumUnderlying = Context.IntTy.getTypePtr();
}
@ -10981,7 +10981,7 @@ CreateNewDecl:
Diag(Def->getLocation(), diag::note_previous_definition);
} else {
unsigned DiagID = diag::ext_forward_ref_enum;
if (getLangOpts().MicrosoftMode)
if (getLangOpts().MSVCCompat)
DiagID = diag::ext_ms_forward_ref_enum;
else if (getLangOpts().CPlusPlus)
DiagID = diag::err_forward_ref_enum;
@ -12353,7 +12353,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
else {
SourceLocation ExpLoc;
if (getLangOpts().CPlusPlus11 && Enum->isFixed() &&
!getLangOpts().MicrosoftMode) {
!getLangOpts().MSVCCompat) {
// C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the
// constant-expression in the enumerator-definition shall be a converted
// constant expression of the underlying type.
@ -12378,7 +12378,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// we perform a non-narrowing conversion as part of converted constant
// expression checking.
if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
if (getLangOpts().MicrosoftMode) {
if (getLangOpts().MSVCCompat) {
Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy;
Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take();
} else

View File

@ -5310,7 +5310,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
// In Microsoft mode, a user-declared move only causes the deletion of the
// corresponding copy operation, not both copy operations.
if (RD->hasUserDeclaredMoveConstructor() &&
(!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) {
(!getLangOpts().MSVCCompat || CSM == CXXCopyConstructor)) {
if (!Diagnose) return true;
// Find any user-declared move constructor.
@ -5323,7 +5323,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
}
assert(UserDeclaredMove);
} else if (RD->hasUserDeclaredMoveAssignment() &&
(!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) {
(!getLangOpts().MSVCCompat || CSM == CXXCopyAssignment)) {
if (!Diagnose) return true;
// Find any user-declared move assignment operator.
@ -9361,7 +9361,7 @@ static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
UserDeclaredOperation = RD->getDestructor();
} else if (!isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyConstructor() &&
!S.getLangOpts().MicrosoftMode) {
!S.getLangOpts().MSVCCompat) {
// Find any user-declared copy constructor.
for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
E = RD->ctor_end(); I != E; ++I) {
@ -9373,7 +9373,7 @@ static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp,
assert(UserDeclaredOperation);
} else if (isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyAssignment() &&
!S.getLangOpts().MicrosoftMode) {
!S.getLangOpts().MSVCCompat) {
// Find any user-declared move assignment operator.
for (CXXRecordDecl::method_iterator I = RD->method_begin(),
E = RD->method_end(); I != E; ++I) {

View File

@ -1733,7 +1733,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
// Actually quite difficult!
if (getLangOpts().MicrosoftMode)
if (getLangOpts().MSVCCompat)
diagnostic = diag::warn_found_via_dependent_bases_lookup;
if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
@ -1799,7 +1799,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
// function definition declared at class scope then we must set
// DC to the lexical parent to be able to search into the parent
// class.
if (getLangOpts().MicrosoftMode && isa<FunctionDecl>(DC) &&
if (getLangOpts().MSVCCompat && isa<FunctionDecl>(DC) &&
cast<FunctionDecl>(DC)->getFriendObjectKind() &&
DC->getLexicalParent()->isRecord())
DC = DC->getLexicalParent();
@ -2018,7 +2018,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
// unqualified name lookup. Any name lookup during template parsing means
// clang might find something that MSVC doesn't. For now, we only handle
// the common case of members of a dependent base class.
if (getLangOpts().MicrosoftMode) {
if (getLangOpts().MSVCCompat) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
if (MD && MD->isInstance() && MD->getParent()->hasAnyDependentBases()) {
assert(SS.isEmpty() && "qualifiers should be already handled");

View File

@ -454,7 +454,7 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
// Microsoft's typeinfo doesn't have type_info in std but in the global
// namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153.
if (!CXXTypeInfoDecl && LangOpts.MicrosoftMode) {
if (!CXXTypeInfoDecl && LangOpts.MSVCCompat) {
LookupQualifiedName(R, Context.getTranslationUnitDecl());
CXXTypeInfoDecl = R.getAsSingle<RecordDecl>();
}
@ -1650,7 +1650,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// Didn't find a member overload. Look for a global one.
DeclareGlobalNewDelete();
DeclContext *TUDecl = Context.getTranslationUnitDecl();
bool FallbackEnabled = IsArray && Context.getLangOpts().MicrosoftMode;
bool FallbackEnabled = IsArray && Context.getLangOpts().MSVCCompat;
if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl,
/*AllowMissing=*/FallbackEnabled, OperatorNew,
/*Diagnose=*/!FallbackEnabled)) {
@ -5070,7 +5070,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
// In MS mode, don't perform any extra checking of call return types within a
// decltype expression.
if (getLangOpts().MicrosoftMode)
if (getLangOpts().MSVCCompat)
return Owned(E);
// Perform the semantic checks we delayed until this point.
@ -5345,7 +5345,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base,
if (!ObjectType->isDependentType() && !ObjectType->isScalarType() &&
!ObjectType->isVectorType()) {
if (getLangOpts().MicrosoftMode && ObjectType->isVoidType())
if (getLangOpts().MSVCCompat && ObjectType->isVoidType())
Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange();
else
Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)

View File

@ -4065,7 +4065,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// In Microsoft mode, don't perform typo correction in a template member
// function dependent context because it interferes with the "lookup into
// dependent bases of class templates" feature.
if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
isa<CXXMethodDecl>(CurContext))
return TypoCorrection();

View File

@ -3631,11 +3631,10 @@ CompareStandardConversionSequences(Sema &S,
// }
// Here, MSVC will call f(int) instead of generating a compile error
// as clang will do in standard mode.
if (S.getLangOpts().MicrosoftMode &&
SCS1.Second == ICK_Integral_Conversion &&
SCS2.Second == ICK_Floating_Integral &&
if (S.getLangOpts().MSVCCompat && SCS1.Second == ICK_Integral_Conversion &&
SCS2.Second == ICK_Floating_Integral &&
S.Context.getTypeSize(SCS1.getFromType()) ==
S.Context.getTypeSize(SCS1.getToType(2)))
S.Context.getTypeSize(SCS1.getToType(2)))
return ImplicitConversionSequence::Better;
return ImplicitConversionSequence::Indistinguishable;
@ -10445,7 +10444,7 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
// create a type dependent CallExpr. The goal is to postpone name lookup
// to instantiation time to be able to search into type dependent base
// classes.
if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() &&
if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
(isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) {
CallExpr *CE = new (Context) CallExpr(Context, Fn, Args,
Context.DependentTy, VK_RValue,