diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -40,6 +40,7 @@ #include "clang/Basic/ProfileList.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/XRayLists.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" @@ -730,6 +731,11 @@ return FullSourceLoc(Loc,SourceMgr); } + /// Return the C++ ABI kind that should be used. The C++ ABI can be overriden + /// at compile time with `-fc++-abi=`. If this is not provided, we instead use + /// the default ABI set by the target. + TargetCXXABI::Kind getCXXABIKind() const; + /// All comments in this translation unit. RawCommentList Comments; diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -540,6 +540,9 @@ def err_aix_default_altivec_abi : Error< "The default Altivec ABI on AIX is not yet supported, use '-mabi=vec-extabi' for the extended Altivec ABI">; +def err_invalid_cxx_abi : Error<"Invalid C++ ABI name '%0'">; +def err_unsupported_cxx_abi : Error<"C++ ABI '%0' is not supported on target triple '%1'">; + def note_cc1_round_trip_original : Note<"Original arguments in round-trip: %0">; def note_cc1_round_trip_generated : Note<"Generated arguments #%0 in round-trip: %1">; def remark_cc1_round_trip_generated : Remark<"Generated arguments #%0 in round-trip: %1">, InGroup; diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -19,6 +19,7 @@ #include "clang/Basic/LangStandard.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" +#include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/FloatingPointMode.h" #include "llvm/ADT/StringRef.h" @@ -337,6 +338,10 @@ /// like CUDA/HIP. std::string CUID; + /// C++ ABI to compile with, if specified by the frontend through -fc++-abi=. + /// This overrides the default ABI used by the target. + llvm::Optional CXXABI; + /// Indicates whether the front-end is explicitly told that the /// input is a header file (i.e. -x c-header). bool IsHeaderFile = false; diff --git a/clang/include/clang/Basic/TargetCXXABI.h b/clang/include/clang/Basic/TargetCXXABI.h --- a/clang/include/clang/Basic/TargetCXXABI.h +++ b/clang/include/clang/Basic/TargetCXXABI.h @@ -15,7 +15,11 @@ #ifndef LLVM_CLANG_BASIC_TARGETCXXABI_H #define LLVM_CLANG_BASIC_TARGETCXXABI_H +#include + #include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" namespace clang { @@ -25,105 +29,8 @@ public: /// The basic C++ ABI kind. enum Kind { - /// The generic Itanium ABI is the standard ABI of most open-source - /// and Unix-like platforms. It is the primary ABI targeted by - /// many compilers, including Clang and GCC. - /// - /// It is documented here: - /// http://www.codesourcery.com/public/cxx-abi/ - GenericItanium, - - /// The generic ARM ABI is a modified version of the Itanium ABI - /// proposed by ARM for use on ARM-based platforms. - /// - /// These changes include: - /// - the representation of member function pointers is adjusted - /// to not conflict with the 'thumb' bit of ARM function pointers; - /// - constructors and destructors return 'this'; - /// - guard variables are smaller; - /// - inline functions are never key functions; - /// - array cookies have a slightly different layout; - /// - additional convenience functions are specified; - /// - and more! - /// - /// It is documented here: - /// http://infocenter.arm.com - /// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf - GenericARM, - - /// The iOS ABI is a partial implementation of the ARM ABI. - /// Several of the features of the ARM ABI were not fully implemented - /// in the compilers that iOS was launched with. - /// - /// Essentially, the iOS ABI includes the ARM changes to: - /// - member function pointers, - /// - guard variables, - /// - array cookies, and - /// - constructor/destructor signatures. - iOS, - - /// The iOS 64-bit and macOS 64-bit ARM ABI follows ARM's published 64-bit - /// ABI more closely, but we don't guarantee to follow it perfectly. - /// - /// It is documented here: - /// http://infocenter.arm.com - /// /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf - AppleARM64, - - /// WatchOS is a modernisation of the iOS ABI, which roughly means it's - /// the AppleARM64 ABI ported to 32-bits. The primary difference from - /// AppleARM64 is that RTTI objects must still be unique at the moment. - WatchOS, - - /// The generic AArch64 ABI is also a modified version of the Itanium ABI, - /// but it has fewer divergences than the 32-bit ARM ABI. - /// - /// The relevant changes from the generic ABI in this case are: - /// - representation of member function pointers adjusted as in ARM. - /// - guard variables are smaller. - GenericAArch64, - - /// The generic Mips ABI is a modified version of the Itanium ABI. - /// - /// At the moment, only change from the generic ABI in this case is: - /// - representation of member function pointers adjusted as in ARM. - GenericMIPS, - - /// The WebAssembly ABI is a modified version of the Itanium ABI. - /// - /// The changes from the Itanium ABI are: - /// - representation of member function pointers is adjusted, as in ARM; - /// - member functions are not specially aligned; - /// - constructors and destructors return 'this', as in ARM; - /// - guard variables are 32-bit on wasm32, as in ARM; - /// - unused bits of guard variables are reserved, as in ARM; - /// - inline functions are never key functions, as in ARM; - /// - C++11 POD rules are used for tail padding, as in AppleARM64. - /// - /// TODO: At present the WebAssembly ABI is not considered stable, so none - /// of these details is necessarily final yet. - WebAssembly, - - /// The Fuchsia ABI is a modified version of the Itanium ABI. - /// - /// The relevant changes from the Itanium ABI are: - /// - constructors and destructors return 'this', as in ARM. - Fuchsia, - - /// The XL ABI is the ABI used by IBM xlclang compiler and is a modified - /// version of the Itanium ABI. - /// - /// The relevant changes from the Itanium ABI are: - /// - static initialization is adjusted to use sinit and sterm functions; - XL, - - /// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and - /// compatible compilers). - /// - /// FIXME: should this be split into Win32 and Win64 variants? - /// - /// Only scattered and incomplete official documentation exists. - Microsoft +#define CXXABI(Name, Str) Name, +#include "TargetCXXABI.def" }; private: @@ -132,7 +39,31 @@ // audit the users to pass it by reference instead. Kind TheKind; + static const auto &getABIMap() { + static llvm::StringMap ABIMap = { +#define CXXABI(Name, Str) {Str, Name}, +#include "TargetCXXABI.def" + }; + return ABIMap; + } + + static const auto &getSpellingMap() { + static std::map SpellingMap = { +#define CXXABI(Name, Str) {Name, Str}, +#include "TargetCXXABI.def" + }; + return SpellingMap; + } + public: + static Kind getKind(StringRef Name) { return getABIMap().lookup(Name); } + static const auto &getSpelling(Kind ABIKind) { + return getSpellingMap().find(ABIKind)->second; + } + static bool isABI(StringRef Name) { + return getABIMap().find(Name) != getABIMap().end(); + } + /// A bogus initialization of the platform ABI. TargetCXXABI() : TheKind(GenericItanium) {} @@ -144,22 +75,53 @@ Kind getKind() const { return TheKind; } - /// Does this ABI generally fall into the Itanium family of ABIs? - bool isItaniumFamily() const { - switch (getKind()) { - case AppleARM64: - case Fuchsia: - case GenericAArch64: - case GenericItanium: + // Check that the kind provided by the fc++-abi flag is supported on this + // target. Users who want to experiment using different ABIs on specific + // platforms can change this freely, but this function should be conservative + // enough such that not all ABIs are allowed on all platforms. For example, we + // probably don't want to allow usage of an ARM ABI on an x86 architecture. + static bool isSupportedCXXABI(const llvm::Triple &T, Kind Kind) { + switch (Kind) { case GenericARM: + return T.isARM() || T.isAArch64(); + case iOS: case WatchOS: + case AppleARM64: + return T.isOSDarwin(); + + case Fuchsia: + return T.isOSFuchsia(); + + case GenericAArch64: + return T.isAArch64(); + case GenericMIPS: + return T.isMIPS(); + case WebAssembly: + return T.isWasm(); + case XL: + return T.isOSAIX(); + + case GenericItanium: return true; case Microsoft: + return T.isKnownWindowsMSVCEnvironment(); + } + }; + + /// Does this ABI generally fall into the Itanium family of ABIs? + bool isItaniumFamily() const { + switch (getKind()) { +#define CXXABI(Name, Str) +#define ITANIUM_CXXABI(Name, Str) case Name: +#include "TargetCXXABI.def" + return true; + + default: return false; } llvm_unreachable("bad ABI kind"); @@ -168,20 +130,13 @@ /// Is this ABI an MSVC-compatible ABI? bool isMicrosoft() const { switch (getKind()) { - case AppleARM64: - case Fuchsia: - case GenericAArch64: - case GenericItanium: - case GenericARM: - case iOS: - case WatchOS: - case GenericMIPS: - case WebAssembly: - case XL: - return false; - - case Microsoft: +#define CXXABI(Name, Str) +#define MICROSOFT_CXXABI(Name, Str) case Name: +#include "TargetCXXABI.def" return true; + + default: + return false; } llvm_unreachable("bad ABI kind"); } diff --git a/clang/include/clang/Basic/TargetCXXABI.def b/clang/include/clang/Basic/TargetCXXABI.def new file mode 100644 --- /dev/null +++ b/clang/include/clang/Basic/TargetCXXABI.def @@ -0,0 +1,129 @@ +//===--- TargetCXXABI.def - Target C++ ABI database --------------- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the various C++ ABI kinds used on different platforms. +// Users of this file must define the CXXABI macro to make use of this +// information. +// +//===----------------------------------------------------------------------===// + +#ifndef CXXABI +#error Define the CXXABI macro to handle C++ ABI kinds. +#endif + +#ifndef ITANIUM_CXXABI +#define ITANIUM_CXXABI(Name, Str) CXXABI(Name, Str) +#endif + +#ifndef MICROSOFT_CXXABI +#define MICROSOFT_CXXABI(Name, Str) CXXABI(Name, Str) +#endif + +/// The generic Itanium ABI is the standard ABI of most open-source +/// and Unix-like platforms. It is the primary ABI targeted by +/// many compilers, including Clang and GCC. +/// +/// It is documented here: +/// http://www.codesourcery.com/public/cxx-abi/ +ITANIUM_CXXABI(GenericItanium, "itanium") + +/// The generic ARM ABI is a modified version of the Itanium ABI +/// proposed by ARM for use on ARM-based platforms. +/// +/// These changes include: +/// - the representation of member function pointers is adjusted +/// to not conflict with the 'thumb' bit of ARM function pointers; +/// - constructors and destructors return 'this'; +/// - guard variables are smaller; +/// - inline functions are never key functions; +/// - array cookies have a slightly different layout; +/// - additional convenience functions are specified; +/// - and more! +/// +/// It is documented here: +/// http://infocenter.arm.com +/// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf +ITANIUM_CXXABI(GenericARM, "arm") + +/// The iOS ABI is a partial implementation of the ARM ABI. +/// Several of the features of the ARM ABI were not fully implemented +/// in the compilers that iOS was launched with. +/// +/// Essentially, the iOS ABI includes the ARM changes to: +/// - member function pointers, +/// - guard variables, +/// - array cookies, and +/// - constructor/destructor signatures. +ITANIUM_CXXABI(iOS, "ios") + +/// The iOS 64-bit and macOS 64-bit ARM ABI follows ARM's published 64-bit +/// ABI more closely, but we don't guarantee to follow it perfectly. +/// +/// It is documented here: +/// http://infocenter.arm.com +/// /help/topic/com.arm.doc.ihi0059a/IHI0059A_cppabi64.pdf +ITANIUM_CXXABI(AppleARM64, "applearm64") + +/// WatchOS is a modernisation of the iOS ABI, which roughly means it's +/// the iOS64 ABI ported to 32-bits. The primary difference from iOS64 is +/// that RTTI objects must still be unique at the moment. +ITANIUM_CXXABI(WatchOS, "watchos") + +/// The generic AArch64 ABI is also a modified version of the Itanium ABI, +/// but it has fewer divergences than the 32-bit ARM ABI. +/// +/// The relevant changes from the generic ABI in this case are: +/// - representation of member function pointers adjusted as in ARM. +/// - guard variables are smaller. +ITANIUM_CXXABI(GenericAArch64, "aarch64") + +/// The generic Mips ABI is a modified version of the Itanium ABI. +/// +/// At the moment, only change from the generic ABI in this case is: +/// - representation of member function pointers adjusted as in ARM. +ITANIUM_CXXABI(GenericMIPS, "mips") + +/// The WebAssembly ABI is a modified version of the Itanium ABI. +/// +/// The changes from the Itanium ABI are: +/// - representation of member function pointers is adjusted, as in ARM; +/// - member functions are not specially aligned; +/// - constructors and destructors return 'this', as in ARM; +/// - guard variables are 32-bit on wasm32, as in ARM; +/// - unused bits of guard variables are reserved, as in ARM; +/// - inline functions are never key functions, as in ARM; +/// - C++11 POD rules are used for tail padding, as in iOS64. +/// +/// TODO: At present the WebAssembly ABI is not considered stable, so none +/// of these details is necessarily final yet. +ITANIUM_CXXABI(WebAssembly, "webassembly") + +/// The Fuchsia ABI is a modified version of the Itanium ABI. +/// +/// The relevant changes from the Itanium ABI are: +/// - constructors and destructors return 'this', as in ARM. +ITANIUM_CXXABI(Fuchsia, "fuchsia") + +/// The XL ABI is the ABI used by IBM xlclang compiler and is a modified +/// version of the Itanium ABI. +/// +/// The relevant changes from the Itanium ABI are: +/// - static initialization is adjusted to use sinit and sterm functions; +ITANIUM_CXXABI(XL, "xl") + +/// The Microsoft ABI is the ABI used by Microsoft Visual Studio (and +/// compatible compilers). +/// +/// FIXME: should this be split into Win32 and Win64 variants? +/// +/// Only scattered and incomplete official documentation exists. +MICROSOFT_CXXABI(Microsoft, "microsoft") + +#undef CXXABI +#undef ITANIUM_CXXABI +#undef MICROSOFT_CXXABI diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1910,6 +1910,10 @@ PosFlag, NegFlag, BothFlags<[CC1Option], " the experimental C++ class ABI for classes with virtual tables">>; +def fcxx_abi_EQ : Joined<["-"], "fc++-abi=">, + Group, Flags<[CC1Option]>, + HelpText<"C++ ABI to use. This will override the target C++ ABI.">; + def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions_EQ : Joined<["-"], "flax-vector-conversions=">, Group, HelpText<"Enable implicit vector bit-casts">, Values<"none,integer,all">, Flags<[CC1Option]>, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -880,10 +880,15 @@ return CanonTTP; } +TargetCXXABI::Kind ASTContext::getCXXABIKind() const { + auto Kind = getTargetInfo().getCXXABI().getKind(); + return getLangOpts().CXXABI.getValueOr(Kind); +} + CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { if (!LangOpts.CPlusPlus) return nullptr; - switch (T.getCXXABI().getKind()) { + switch (getCXXABIKind()) { case TargetCXXABI::AppleARM64: case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericARM: // Same as Itanium at this level diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -75,7 +75,7 @@ static const char AnnotationSection[] = "llvm.metadata"; static CGCXXABI *createCXXABI(CodeGenModule &CGM) { - switch (CGM.getTarget().getCXXABI().getKind()) { + switch (CGM.getContext().getCXXABIKind()) { case TargetCXXABI::AppleARM64: case TargetCXXABI::Fuchsia: case TargetCXXABI::GenericAArch64: diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -546,7 +546,7 @@ } CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { - switch (CGM.getTarget().getCXXABI().getKind()) { + switch (CGM.getContext().getCXXABIKind()) { // For IR-generation purposes, there's no significant difference // between the ARM and iOS ABIs. case TargetCXXABI::GenericARM: diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5321,6 +5321,9 @@ /*Default=*/false)) Args.AddLastArg(CmdArgs, options::OPT_ffixed_point); + if (Arg *A = Args.getLastArg(options::OPT_fcxx_abi_EQ)) + A->render(Args, CmdArgs); + // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi} // (-ansi is equivalent to -std=c89 or -std=c++98). // diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3512,6 +3512,10 @@ if (Opts.getSignReturnAddressKey() == LangOptions::SignReturnAddressKeyKind::BKey) GenerateArg(Args, OPT_msign_return_address_key_EQ, "b_key", SA); + + if (Opts.CXXABI) + GenerateArg(Args, OPT_fcxx_abi_EQ, TargetCXXABI::getSpelling(*Opts.CXXABI), + SA); } bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, @@ -3996,6 +4000,20 @@ } } + // The value can be empty, which indicates the system default should be used. + StringRef CXXABI = Args.getLastArgValue(OPT_fcxx_abi_EQ); + if (!CXXABI.empty()) { + if (!TargetCXXABI::isABI(CXXABI)) { + Diags.Report(diag::err_invalid_cxx_abi) << CXXABI; + } else { + auto Kind = TargetCXXABI::getKind(CXXABI); + if (!TargetCXXABI::isSupportedCXXABI(T, Kind)) + Diags.Report(diag::err_unsupported_cxx_abi) << CXXABI << T.str(); + else + Opts.CXXABI = Kind; + } + } + return Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/test/CodeGenCXX/cxx-abi-switch.cpp b/clang/test/CodeGenCXX/cxx-abi-switch.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/cxx-abi-switch.cpp @@ -0,0 +1,28 @@ +// Assert that the ABI switch uses the proper codegen. Fuchsia uses the +// "return this" ABI on constructors and destructors by default, but if we +// explicitly choose the generic itanium C++ ABI, we should not return "this" on +// ctors/dtors. +// +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-unknown-fuchsia -fc++-abi=itanium | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=aarch64-unknown-fuchsia -fc++-abi=itanium | FileCheck %s + +class A { +public: + virtual ~A(); + int x_; +}; + +class B : public A { +public: + B(int *i); + virtual ~B(); + int *i_; +}; + +B::B(int *i) : i_(i) {} +B::~B() {} + +// CHECK: define{{.*}} void @_ZN1BC2EPi(%class.B* {{[^,]*}} %this, i32* %i) +// CHECK: define{{.*}} void @_ZN1BC1EPi(%class.B* {{[^,]*}} %this, i32* %i) +// CHECK: define{{.*}} void @_ZN1BD2Ev(%class.B* {{[^,]*}} %this) +// CHECK: define{{.*}} void @_ZN1BD1Ev(%class.B* {{[^,]*}} %this) diff --git a/clang/test/Frontend/invalid-cxx-abi.cpp b/clang/test/Frontend/invalid-cxx-abi.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Frontend/invalid-cxx-abi.cpp @@ -0,0 +1,34 @@ +// These should succeed. +// RUN: %clang -c -fc++-abi=itanium %s +// RUN: %clang -c -fc++-abi=arm -target arm64 %s +// RUN: %clang -c -fc++-abi=ios -target arm64-apple-ios %s +// RUN: %clang -c -fc++-abi=aarch64 -target arm64 %s +// RUN: %clang -c -fc++-abi=mips -target mips %s +// RUN: %clang -c -fc++-abi=webassembly -target wasm64 %s +// RUN: %clang -c -fc++-abi=fuchsia -target x86_64-unknown-fuchsia %s +// RUN: %clang -S -fc++-abi=xl -target powerpc-unknown-aix %s -o /dev/null +// RUN: %clang -c -fc++-abi=microsoft -target x86_64-windows-msvc %s +// RUN: %clang_cc1 -fc++-abi=itanium %s +// RUN: %clang_cc1 -fc++-abi=arm -triple arm64 %s +// RUN: %clang_cc1 -fc++-abi=ios -triple arm64-apple-ios %s +// RUN: %clang_cc1 -fc++-abi=aarch64 -triple arm64 %s +// RUN: %clang_cc1 -fc++-abi=mips -triple mips %s +// RUN: %clang_cc1 -fc++-abi=webassembly -triple wasm64 %s +// RUN: %clang_cc1 -fc++-abi=fuchsia -triple x86_64-unknown-fuchsia %s +// RUN: %clang_cc1 -S -fc++-abi=xl -triple powerpc-unknown-aix %s -o /dev/null +// RUN: %clang_cc1 -fc++-abi=microsoft -triple x86_64-windows-msvc %s + +// RUN: not %clang -c -fc++-abi=InvalidABI %s 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: not %clang -c -fc++-abi=Fuchsia %s 2>&1 | FileCheck %s -check-prefix=CASE-SENSITIVE +// RUN: not %clang_cc1 -fc++-abi=InvalidABI %s 2>&1 | FileCheck %s -check-prefix=INVALID +// RUN: not %clang_cc1 -fc++-abi=Fuchsia %s 2>&1 | FileCheck %s -check-prefix=CASE-SENSITIVE +// INVALID: error: Invalid C++ ABI name 'InvalidABI' +// CASE-SENSITIVE: error: Invalid C++ ABI name 'Fuchsia' + +// The flag is propgated from the driver to cc1. +// RUN: %clang -fc++-abi=InvalidABI %s -### 2>&1 | FileCheck %s -check-prefix=CC1-FLAG +// CC1-FLAG: -fc++-abi=InvalidABI + +// Some C++ ABIs are not supported on some platforms. +// RUN: not %clang_cc1 -c -fc++-abi=fuchsia -triple i386 %s 2>&1 | FileCheck %s -check-prefix=UNSUPPORTED-FUCHSIA +// UNSUPPORTED-FUCHSIA: error: C++ ABI 'fuchsia' is not supported on target triple 'i386'