Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 55deb31

Browse files
committed
Add flag to request Clang is ABI-compatible with older versions of itself
This patch adds a flag -fclang-abi-compat that can be used to request that Clang attempts to be ABI-compatible with some older version of itself. This is provided on a best-effort basis; right now, this can be used to undo the ABI change in r310401, reverting Clang to its prior C++ ABI for pass/return by value of class types affected by that change, and to undo the ABI change in r262688, reverting Clang to using integer registers rather than SSE registers for passing <1 x long long> vectors. The intent is that we will maintain this backwards compatibility path as we make ABI-breaking fixes in future. The reversion to the old behavior for r310401 is also applied to the PS4 target since that change is not part of its platform ABI (which is essentially to do whatever Clang 3.2 did). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311823 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d673c2f commit 55deb31

14 files changed

+160
-23
lines changed

include/clang/Driver/Options.td

+3
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,9 @@ def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>;
711711
def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group<f_Group>,
712712
Flags<[DriverOption]>, HelpText<"Load the clang builtins module map file.">;
713713
def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>;
714+
def fclang_abi_compat_EQ : Joined<["-"], "fclang-abi-compat=">, Group<f_clang_Group>,
715+
Flags<[CC1Option]>, MetaVarName<"<version>">, Values<"<major>.<minor>,latest">,
716+
HelpText<"Attempt to match the ABI of Clang <version>">;
714717
def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
715718
def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>,
716719
Flags<[CoreOption, CC1Option]>, HelpText<"Use colors in diagnostics">;

include/clang/Frontend/CodeGenOptions.def

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss.
120120
ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy)
121121
CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is
122122
///< enabled.
123+
124+
/// A version of Clang that we should attempt to be ABI-compatible with.
125+
ENUM_CODEGENOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest)
126+
123127
VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified.
124128
VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified.
125129

include/clang/Frontend/CodeGenOptions.h

+17
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@ class CodeGenOptions : public CodeGenOptionsBase {
6969
LocalExecTLSModel
7070
};
7171

72+
/// Clang versions with different platform ABI conformance.
73+
enum class ClangABI {
74+
/// Attempt to be ABI-compatible with code generated by Clang 3.8.x
75+
/// (SVN r257626). This causes <1 x long long> to be passed in an
76+
/// integer register instead of an SSE register on x64_64.
77+
Ver3_8,
78+
79+
/// Attempt to be ABI-compatible with code generated by Clang 4.0.x
80+
/// (SVN r291814). This causes move operations to be ignored when
81+
/// determining whether a class type can be passed or returned directly.
82+
Ver4,
83+
84+
/// Conform to the underlying platform's C and C++ ABIs as closely
85+
/// as we can.
86+
Latest
87+
};
88+
7289
enum StructReturnConventionKind {
7390
SRCK_Default, // No special option was passed.
7491
SRCK_OnStack, // Small structs on the stack (-fpcc-struct-return).

lib/CodeGen/ABIInfo.h

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace llvm {
2424

2525
namespace clang {
2626
class ASTContext;
27+
class CodeGenOptions;
2728
class TargetInfo;
2829

2930
namespace CodeGen {
@@ -68,6 +69,7 @@ namespace swiftcall {
6869
llvm::LLVMContext &getVMContext() const;
6970
const llvm::DataLayout &getDataLayout() const;
7071
const TargetInfo &getTarget() const;
72+
const CodeGenOptions &getCodeGenOpts() const;
7173

7274
/// Return the calling convention to use for system runtime
7375
/// functions.

lib/CodeGen/CodeGenTypes.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ CodeGenTypes::~CodeGenTypes() {
4444
delete &*I++;
4545
}
4646

47+
const CodeGenOptions &CodeGenTypes::getCodeGenOpts() const {
48+
return CGM.getCodeGenOpts();
49+
}
50+
4751
void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
4852
llvm::StructType *Ty,
4953
StringRef suffix) {

lib/CodeGen/CodeGenTypes.h

+1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ class CodeGenTypes {
178178
const TargetInfo &getTarget() const { return Target; }
179179
CGCXXABI &getCXXABI() const { return TheCXXABI; }
180180
llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
181+
const CodeGenOptions &getCodeGenOpts() const;
181182

182183
/// ConvertType - Convert type T into a llvm::Type.
183184
llvm::Type *ConvertType(QualType T);

lib/CodeGen/ItaniumCXXABI.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,20 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
6262

6363
bool classifyReturnType(CGFunctionInfo &FI) const override;
6464

65+
bool passClassIndirect(const CXXRecordDecl *RD) const {
66+
// Clang <= 4 used the pre-C++11 rule, which ignores move operations.
67+
// The PS4 platform ABI follows the behavior of Clang 3.2.
68+
if (CGM.getCodeGenOpts().getClangABICompat() <=
69+
CodeGenOptions::ClangABI::Ver4 ||
70+
CGM.getTriple().getOS() == llvm::Triple::PS4)
71+
return RD->hasNonTrivialDestructor() ||
72+
RD->hasNonTrivialCopyConstructor();
73+
return !canCopyArgument(RD);
74+
}
75+
6576
RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override {
6677
// If C++ prohibits us from making a copy, pass by address.
67-
if (!canCopyArgument(RD))
78+
if (passClassIndirect(RD))
6879
return RAA_Indirect;
6980
return RAA_Default;
7081
}
@@ -1012,7 +1023,7 @@ bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const {
10121023
return false;
10131024

10141025
// If C++ prohibits us from making a copy, return by address.
1015-
if (!canCopyArgument(RD)) {
1026+
if (passClassIndirect(RD)) {
10161027
auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
10171028
FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
10181029
return true;

lib/CodeGen/TargetInfo.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,11 @@ const TargetInfo &ABIInfo::getTarget() const {
184184
return CGT.getTarget();
185185
}
186186

187-
bool ABIInfo:: isAndroid() const { return getTarget().getTriple().isAndroid(); }
187+
const CodeGenOptions &ABIInfo::getCodeGenOpts() const {
188+
return CGT.getCodeGenOpts();
189+
}
190+
191+
bool ABIInfo::isAndroid() const { return getTarget().getTriple().isAndroid(); }
188192

189193
bool ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const {
190194
return false;
@@ -2112,9 +2116,14 @@ class X86_64ABIInfo : public SwiftABIInfo {
21122116
return !getTarget().getTriple().isOSDarwin();
21132117
}
21142118

2115-
/// GCC classifies <1 x long long> as SSE but compatibility with older clang
2116-
// compilers require us to classify it as INTEGER.
2119+
/// GCC classifies <1 x long long> as SSE but some platform ABIs choose to
2120+
/// classify it as INTEGER (for compatibility with older clang compilers).
21172121
bool classifyIntegerMMXAsSSE() const {
2122+
// Clang <= 3.8 did not do this.
2123+
if (getCodeGenOpts().getClangABICompat() <=
2124+
CodeGenOptions::ClangABI::Ver3_8)
2125+
return false;
2126+
21182127
const llvm::Triple &Triple = getTarget().getTriple();
21192128
if (Triple.isOSDarwin() || Triple.getOS() == llvm::Triple::PS4)
21202129
return false;

lib/Driver/ToolChains/Clang.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -2933,6 +2933,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
29332933

29342934
addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
29352935

2936+
if (auto *ABICompatArg = Args.getLastArg(options::OPT_fclang_abi_compat_EQ))
2937+
ABICompatArg->render(Args, CmdArgs);
2938+
29362939
// Add runtime flag for PS4 when PGO or Coverage are enabled.
29372940
if (getToolChain().getTriple().isPS4CPU())
29382941
PS4cpu::addProfileRTArgs(getToolChain(), Args, CmdArgs);

lib/Frontend/CompilerInvocation.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,33 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
573573
if (!Opts.ProfileInstrumentUsePath.empty())
574574
setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath);
575575

576+
if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) {
577+
Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest);
578+
579+
StringRef Ver = A->getValue();
580+
std::pair<StringRef, StringRef> VerParts = Ver.split('.');
581+
unsigned Major, Minor = 0;
582+
583+
// Check the version number is valid: either 3.x (0 <= x <= 9) or
584+
// y or y.0 (4 <= y <= current version).
585+
if (!VerParts.first.startswith("0") &&
586+
!VerParts.first.getAsInteger(10, Major) &&
587+
3 <= Major && Major <= CLANG_VERSION_MAJOR &&
588+
(Major == 3 ? VerParts.second.size() == 1 &&
589+
!VerParts.second.getAsInteger(10, Minor)
590+
: VerParts.first.size() == Ver.size() ||
591+
VerParts.second == "0")) {
592+
// Got a valid version number.
593+
if (Major == 3 && Minor <= 8)
594+
Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8);
595+
else if (Major <= 4)
596+
Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4);
597+
} else if (Ver != "latest") {
598+
Diags.Report(diag::err_drv_invalid_value)
599+
<< A->getAsString(Args) << A->getValue();
600+
}
601+
}
602+
576603
Opts.CoverageMapping =
577604
Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false);
578605
Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);

test/CodeGenCXX/clang-abi-compat.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefix=PRE39 --check-prefix=PRE5 %s
2+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefix=PRE39 --check-prefix=PRE5 %s
3+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=PRE5 %s
4+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=PRE5 %s
5+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=V5 %s
6+
// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefix=V39 --check-prefix=V5 %s
7+
8+
typedef __attribute__((vector_size(8))) long long v1xi64;
9+
void clang39(v1xi64) {}
10+
// PRE39: @_Z7clang39Dv1_x(i64
11+
// V39: @_Z7clang39Dv1_x(double
12+
13+
struct A {
14+
A(const A&) = default;
15+
A(A&&);
16+
};
17+
void clang5(A) {}
18+
// PRE5: @_Z6clang51A()
19+
// V5: @_Z6clang51A(%{{.*}}*

test/CodeGenCXX/uncopyable-args.cpp

+37-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s
1+
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=NEWABI
2+
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI
3+
// RUN: %clang_cc1 -std=c++11 -triple x86_64-scei-ps4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=OLDABI
24
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=18 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-18
35
// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-msvc -emit-llvm -o - %s -fms-compatibility -fms-compatibility-version=19 | FileCheck %s -check-prefix=WIN64 -check-prefix=WIN64-19
46

@@ -56,8 +58,10 @@ void bar() {
5658
// CHECK-LABEL: define void @_ZN9move_ctor3barEv()
5759
// CHECK: call void @_Z{{.*}}C1Ev(
5860
// CHECK-NOT: call
59-
// CHECK: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
60-
// CHECK-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
61+
// NEWABI: call void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"* %{{.*}})
62+
// OLDABI: call void @_ZN9move_ctor3fooENS_1AE(i8* %{{.*}})
63+
// NEWABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(%"struct.move_ctor::A"*)
64+
// OLDABI-LABEL: declare void @_ZN9move_ctor3fooENS_1AE(i8*)
6165

6266
// WIN64-LABEL: declare void @"\01?foo@move_ctor@@YAXUA@1@@Z"(%"struct.move_ctor::A"*)
6367
}
@@ -76,8 +80,10 @@ void bar() {
7680
// CHECK-LABEL: define void @_ZN11all_deleted3barEv()
7781
// CHECK: call void @_Z{{.*}}C1Ev(
7882
// CHECK-NOT: call
79-
// CHECK: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
80-
// CHECK-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
83+
// NEWABI: call void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"* %{{.*}})
84+
// OLDABI: call void @_ZN11all_deleted3fooENS_1AE(i8* %{{.*}})
85+
// NEWABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(%"struct.all_deleted::A"*)
86+
// OLDABI-LABEL: declare void @_ZN11all_deleted3fooENS_1AE(i8*)
8187

8288
// WIN64-LABEL: declare void @"\01?foo@all_deleted@@YAXUA@1@@Z"(%"struct.all_deleted::A"*)
8389
}
@@ -95,8 +101,10 @@ void bar() {
95101
// CHECK-LABEL: define void @_ZN18implicitly_deleted3barEv()
96102
// CHECK: call void @_Z{{.*}}C1Ev(
97103
// CHECK-NOT: call
98-
// CHECK: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}})
99-
// CHECK-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
104+
// NEWABI: call void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"* %{{.*}})
105+
// OLDABI: call void @_ZN18implicitly_deleted3fooENS_1AE(i8* %{{.*}})
106+
// NEWABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(%"struct.implicitly_deleted::A"*)
107+
// OLDABI-LABEL: declare void @_ZN18implicitly_deleted3fooENS_1AE(i8*)
100108

101109
// In MSVC 2013, the copy ctor is not deleted by a move assignment. In MSVC 2015, it is.
102110
// WIN64-18-LABEL: declare void @"\01?foo@implicitly_deleted@@YAXUA@1@@Z"(i64
@@ -116,8 +124,10 @@ void bar() {
116124
// CHECK-LABEL: define void @_ZN11one_deleted3barEv()
117125
// CHECK: call void @_Z{{.*}}C1Ev(
118126
// CHECK-NOT: call
119-
// CHECK: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
120-
// CHECK-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
127+
// NEWABI: call void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"* %{{.*}})
128+
// OLDABI: call void @_ZN11one_deleted3fooENS_1AE(i8* %{{.*}})
129+
// NEWABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(%"struct.one_deleted::A"*)
130+
// OLDABI-LABEL: declare void @_ZN11one_deleted3fooENS_1AE(i8*)
121131

122132
// WIN64-LABEL: declare void @"\01?foo@one_deleted@@YAXUA@1@@Z"(%"struct.one_deleted::A"*)
123133
}
@@ -196,8 +206,10 @@ void bar() {
196206
}
197207
// CHECK-LABEL: define void @_ZN14two_copy_ctors3barEv()
198208
// CHECK: call void @_Z{{.*}}C1Ev(
199-
// CHECK: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
200-
// CHECK-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
209+
// NEWABI: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* %{{.*}})
210+
// OLDABI: call void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* byval
211+
// NEWABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"*)
212+
// OLDABI-LABEL: declare void @_ZN14two_copy_ctors3fooENS_1BE(%"struct.two_copy_ctors::B"* byval
201213

202214
// WIN64-LABEL: declare void @"\01?foo@two_copy_ctors@@YAXUB@1@@Z"(%"struct.two_copy_ctors::B"*)
203215
}
@@ -209,7 +221,8 @@ struct A {
209221
void *p;
210222
};
211223
void *foo(A a) { return a.p; }
212-
// CHECK-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(%"struct.definition_only::A"*
224+
// NEWABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(%"struct.definition_only::A"*
225+
// OLDABI-LABEL: define i8* @_ZN15definition_only3fooENS_1AE(i8*
213226
// WIN64-LABEL: define i8* @"\01?foo@definition_only@@YAPEAXUA@1@@Z"(%"struct.definition_only::A"*
214227
}
215228

@@ -224,7 +237,8 @@ struct A {
224237
B b;
225238
};
226239
void *foo(A a) { return a.b.p; }
227-
// CHECK-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(%"struct.deleted_by_member::A"*
240+
// NEWABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(%"struct.deleted_by_member::A"*
241+
// OLDABI-LABEL: define i8* @_ZN17deleted_by_member3fooENS_1AE(i8*
228242
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member::A"*
229243
}
230244

@@ -238,7 +252,8 @@ struct A : B {
238252
A();
239253
};
240254
void *foo(A a) { return a.p; }
241-
// CHECK-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(%"struct.deleted_by_base::A"*
255+
// NEWABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(%"struct.deleted_by_base::A"*
256+
// OLDABI-LABEL: define i8* @_ZN15deleted_by_base3fooENS_1AE(i8*
242257
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base::A"*
243258
}
244259

@@ -253,7 +268,8 @@ struct A {
253268
B b;
254269
};
255270
void *foo(A a) { return a.b.p; }
256-
// CHECK-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(%"struct.deleted_by_member_copy::A"*
271+
// NEWABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(%"struct.deleted_by_member_copy::A"*
272+
// OLDABI-LABEL: define i8* @_ZN22deleted_by_member_copy3fooENS_1AE(i8*
257273
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_member_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_member_copy::A"*
258274
}
259275

@@ -267,7 +283,8 @@ struct A : B {
267283
A();
268284
};
269285
void *foo(A a) { return a.p; }
270-
// CHECK-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(%"struct.deleted_by_base_copy::A"*
286+
// NEWABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(%"struct.deleted_by_base_copy::A"*
287+
// OLDABI-LABEL: define i8* @_ZN20deleted_by_base_copy3fooENS_1AE(i8*
271288
// WIN64-LABEL: define i8* @"\01?foo@deleted_by_base_copy@@YAPEAXUA@1@@Z"(%"struct.deleted_by_base_copy::A"*
272289
}
273290

@@ -277,7 +294,8 @@ struct A {
277294
A(const A &o) = delete;
278295
void *p;
279296
};
280-
// CHECK-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(%"struct.explicit_delete::A"*
297+
// NEWABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(%"struct.explicit_delete::A"*
298+
// OLDABI-LABEL: define i8* @_ZN15explicit_delete3fooENS_1AE(i8*
281299
// WIN64-LABEL: define i8* @"\01?foo@explicit_delete@@YAPEAXUA@1@@Z"(%"struct.explicit_delete::A"*
282300
void *foo(A a) { return a.p; }
283301
}
@@ -289,7 +307,8 @@ struct A {
289307
// Deleted copy ctor due to rvalue ref member.
290308
int &&ref;
291309
};
292-
// CHECK-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(%"struct.implicitly_deleted_copy_ctor::A"*
310+
// NEWABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(%"struct.implicitly_deleted_copy_ctor::A"*
311+
// OLDABI-LABEL: define {{.*}} @_ZN28implicitly_deleted_copy_ctor3fooENS_1AE(i32*
293312
// WIN64-LABEL: define {{.*}} @"\01?foo@implicitly_deleted_copy_ctor@@YAAEAHUA@1@@Z"(%"struct.implicitly_deleted_copy_ctor::A"*
294313
int &foo(A a) { return a.ref; }
295314

test/Driver/flags.c

+3
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@
2424

2525
// RUN: %clang -target armv7-apple-darwin10 -### -S -mno-implicit-float -mimplicit-float %s 2>&1 | FileCheck -check-prefix=TEST8 %s
2626
// TEST8-NOT: "-no-implicit-float"
27+
28+
// RUN: %clang -target x86_64-linux-gnu -### -c -fclang-abi-compat=3.2 %s 2>&1 | FileCheck -check-prefix=TEST9 %s
29+
// TEST9: "-fclang-abi-compat=3.2"

test/Frontend/clang-abi-compat.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: not %clang_cc1 -fclang-abi-compat=banana %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
2+
// RUN: not %clang_cc1 -fclang-abi-compat=2.9 %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
3+
// RUN: not %clang_cc1 -fclang-abi-compat=8 %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
4+
// RUN: not %clang_cc1 -fclang-abi-compat=3.10 %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
5+
// RUN: not %clang_cc1 -fclang-abi-compat=4.1 %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
6+
// RUN: not %clang_cc1 -fclang-abi-compat=04 %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
7+
// RUN: not %clang_cc1 -fclang-abi-compat=4. %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
8+
// RUN: not %clang_cc1 -fclang-abi-compat=4.00 %s -fsyntax-only 2>&1 | FileCheck --check-prefix=INVALID %s
9+
// INVALID: error: invalid value '{{.*}}' in '-fclang-abi-compat={{.*}}'
10+
//
11+
// RUN: %clang_cc1 -fclang-abi-compat=3.0 %s -fsyntax-only
12+
// RUN: %clang_cc1 -fclang-abi-compat=3.9 %s -fsyntax-only
13+
// RUN: %clang_cc1 -fclang-abi-compat=4 %s -fsyntax-only
14+
// RUN: %clang_cc1 -fclang-abi-compat=4.0 %s -fsyntax-only
15+
// RUN: %clang_cc1 -fclang-abi-compat=latest %s -fsyntax-only

0 commit comments

Comments
 (0)