Skip to content

Commit b9967bc

Browse files
rcvalleveselypeta
authored andcommitted
Add CFI integer types normalization
This commit adds a new option (i.e., `-fsanitize-cfi-icall-normalize-integers`) for normalizing integer types as vendor extended types for cross-language LLVM CFI/KCFI support with other languages that can't represent and encode C/C++ integer types. Specifically, integer types are encoded as their defined representations (e.g., 8-bit signed integer, 16-bit signed integer, 32-bit signed integer, ...) for compatibility with languages that define explicitly-sized integer types (e.g., i8, i16, i32, ..., in Rust). ``-fsanitize-cfi-icall-normalize-integers`` is compatible with ``-fsanitize-cfi-icall-generalize-pointers``. This helps with providing cross-language CFI support with the Rust compiler and is an alternative solution for the issue described and alternatives proposed in the RFC rust-lang/rfcs#3296. For more information about LLVM CFI/KCFI and cross-language LLVM CFI/KCFI support for the Rust compiler, see the design document in the tracking issue rust-lang/rust#89653. Reviewed By: pcc, samitolvanen Differential Revision: https://reviews.llvm.org/D139395
2 parents 9573126 + b1e9ab7 commit b9967bc

13 files changed

+300
-16
lines changed

clang/docs/ControlFlowIntegrity.rst

+19
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,25 @@ long as the qualifiers for the type they point to match. For example, ``char*``,
236236
``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with
237237
``-fsanitize-cfi-cross-dso``.
238238

239+
.. _cfi-icall-experimental-normalize-integers:
240+
241+
``-fsanitize-cfi-icall-experimental-normalize-integers``
242+
--------------------------------------------------------
243+
244+
This option enables normalizing integer types as vendor extended types for
245+
cross-language LLVM CFI/KCFI support with other languages that can't represent
246+
and encode C/C++ integer types.
247+
248+
Specifically, integer types are encoded as their defined representations (e.g.,
249+
8-bit signed integer, 16-bit signed integer, 32-bit signed integer, ...) for
250+
compatibility with languages that define explicitly-sized integer types (e.g.,
251+
i8, i16, i32, ..., in Rust).
252+
253+
``-fsanitize-cfi-icall-experimental-normalize-integers`` is compatible with
254+
``-fsanitize-cfi-icall-generalize-pointers``.
255+
256+
This option is currently experimental.
257+
239258
.. _cfi-canonical-jump-tables:
240259

241260
``-fsanitize-cfi-canonical-jump-tables``

clang/docs/UsersManual.rst

+8
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,14 @@ are listed below.
19921992
checked by Control Flow Integrity indirect call checking. See
19931993
:doc:`ControlFlowIntegrity` for more details.
19941994

1995+
.. option:: -fsanitize-cfi-icall-experimental-normalize-integers
1996+
1997+
Normalize integers in return and argument types in function type signatures
1998+
checked by Control Flow Integrity indirect call checking. See
1999+
:doc:`ControlFlowIntegrity` for more details.
2000+
2001+
This option is currently experimental.
2002+
19952003
.. option:: -fstrict-vtable-pointers
19962004

19972005
Enable optimizations based on the strict rules for overwriting polymorphic

clang/include/clang/AST/Mangle.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ class MangleContext {
140140
unsigned ManglingNumber,
141141
raw_ostream &) = 0;
142142
virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0;
143-
virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0;
143+
virtual void mangleCXXRTTIName(QualType T, raw_ostream &,
144+
bool NormalizeIntegers = false) = 0;
144145
virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0;
145146
virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&);
146147

@@ -177,7 +178,8 @@ class MangleContext {
177178
/// or type uniquing.
178179
/// TODO: Extend this to internal types by generating names that are unique
179180
/// across translation units so it can be used with LTO.
180-
virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
181+
virtual void mangleTypeName(QualType T, raw_ostream &,
182+
bool NormalizeIntegers = false) = 0;
181183

182184
/// @}
183185
};

clang/include/clang/Basic/CodeGenOptions.def

+2
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime f
257257
///< diagnostics.
258258
CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in
259259
///< CFI icall function signatures
260+
CODEGENOPT(SanitizeCfiICallNormalizeIntegers, 1, 0) ///< Normalize integer types in
261+
///< CFI icall function signatures
260262
CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical
261263
///< instead of creating a local jump table.
262264
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage

clang/include/clang/Driver/Options.td

+4
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,10 @@ def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-g
19441944
Group<f_clang_Group>,
19451945
HelpText<"Generalize pointers in CFI indirect call type signature checks">,
19461946
MarshallingInfoFlag<CodeGenOpts<"SanitizeCfiICallGeneralizePointers">>;
1947+
def fsanitize_cfi_icall_normalize_integers : Flag<["-"], "fsanitize-cfi-icall-experimental-normalize-integers">,
1948+
Group<f_clang_Group>,
1949+
HelpText<"Normalize integers in CFI indirect call type signature checks">,
1950+
MarshallingInfoFlag<CodeGenOpts<"SanitizeCfiICallNormalizeIntegers">>;
19471951
defm sanitize_cfi_canonical_jump_tables : BoolOption<"f", "sanitize-cfi-canonical-jump-tables",
19481952
CodeGenOpts<"SanitizeCfiCanonicalJumpTables">, DefaultFalse,
19491953
PosFlag<SetTrue, [], "Make">, NegFlag<SetFalse, [CoreOption, NoXarchOption], "Do not make">,

clang/include/clang/Driver/SanitizerArgs.h

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class SanitizerArgs {
3737
bool MsanParamRetval = true;
3838
bool CfiCrossDso = false;
3939
bool CfiICallGeneralizePointers = false;
40+
bool CfiICallNormalizeIntegers = false;
4041
bool CfiCanonicalJumpTables = false;
4142
int AsanFieldPadding = 0;
4243
bool SharedRuntime = false;

clang/lib/AST/ItaniumMangle.cpp

+97-7
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
115115
void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
116116
const CXXRecordDecl *Type, raw_ostream &) override;
117117
void mangleCXXRTTI(QualType T, raw_ostream &) override;
118-
void mangleCXXRTTIName(QualType T, raw_ostream &) override;
119-
void mangleTypeName(QualType T, raw_ostream &) override;
118+
void mangleCXXRTTIName(QualType T, raw_ostream &,
119+
bool NormalizeIntegers) override;
120+
void mangleTypeName(QualType T, raw_ostream &,
121+
bool NormalizeIntegers) override;
120122

121123
void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override;
122124
void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override;
@@ -221,6 +223,10 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
221223
class CXXNameMangler {
222224
ItaniumMangleContextImpl &Context;
223225
raw_ostream &Out;
226+
/// Normalize integer types for cross-language CFI support with other
227+
/// languages that can't represent and encode C/C++ integer types.
228+
bool NormalizeIntegers = false;
229+
224230
bool NullOut = false;
225231
/// In the "DisableDerivedAbiTags" mode derived ABI tags are not calculated.
226232
/// This mode is used when mangler creates another mangler recursively to
@@ -419,6 +425,10 @@ class CXXNameMangler {
419425
: Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
420426
AbiTagsRoot(AbiTags) {}
421427

428+
CXXNameMangler(ItaniumMangleContextImpl &C, raw_ostream &Out_,
429+
bool NormalizeIntegers_)
430+
: Context(C), Out(Out_), NormalizeIntegers(NormalizeIntegers_),
431+
NullOut(false), AbiTagsRoot(AbiTags) {}
422432
CXXNameMangler(CXXNameMangler &Outer, raw_ostream &Out_)
423433
: Context(Outer.Context), Out(Out_), Structor(Outer.Structor),
424434
StructorType(Outer.StructorType), SeqID(Outer.SeqID),
@@ -2944,6 +2954,85 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
29442954
// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
29452955
// ::= u <source-name> # vendor extended type
29462956
std::string type_name;
2957+
// Normalize integer types as vendor extended types:
2958+
// u<length>i<type size>
2959+
// u<length>u<type size>
2960+
if (NormalizeIntegers && T->isInteger()) {
2961+
if (T->isSignedInteger()) {
2962+
switch (getASTContext().getTypeSize(T)) {
2963+
case 8:
2964+
// Pick a representative for each integer size in the substitution
2965+
// dictionary. (Its actual defined size is not relevant.)
2966+
if (mangleSubstitution(BuiltinType::SChar))
2967+
break;
2968+
Out << "u2i8";
2969+
addSubstitution(BuiltinType::SChar);
2970+
break;
2971+
case 16:
2972+
if (mangleSubstitution(BuiltinType::Short))
2973+
break;
2974+
Out << "u3i16";
2975+
addSubstitution(BuiltinType::Short);
2976+
break;
2977+
case 32:
2978+
if (mangleSubstitution(BuiltinType::Int))
2979+
break;
2980+
Out << "u3i32";
2981+
addSubstitution(BuiltinType::Int);
2982+
break;
2983+
case 64:
2984+
if (mangleSubstitution(BuiltinType::Long))
2985+
break;
2986+
Out << "u3i64";
2987+
addSubstitution(BuiltinType::Long);
2988+
break;
2989+
case 128:
2990+
if (mangleSubstitution(BuiltinType::Int128))
2991+
break;
2992+
Out << "u4i128";
2993+
addSubstitution(BuiltinType::Int128);
2994+
break;
2995+
default:
2996+
llvm_unreachable("Unknown integer size for normalization");
2997+
}
2998+
} else {
2999+
switch (getASTContext().getTypeSize(T)) {
3000+
case 8:
3001+
if (mangleSubstitution(BuiltinType::UChar))
3002+
break;
3003+
Out << "u2u8";
3004+
addSubstitution(BuiltinType::UChar);
3005+
break;
3006+
case 16:
3007+
if (mangleSubstitution(BuiltinType::UShort))
3008+
break;
3009+
Out << "u3u16";
3010+
addSubstitution(BuiltinType::UShort);
3011+
break;
3012+
case 32:
3013+
if (mangleSubstitution(BuiltinType::UInt))
3014+
break;
3015+
Out << "u3u32";
3016+
addSubstitution(BuiltinType::UInt);
3017+
break;
3018+
case 64:
3019+
if (mangleSubstitution(BuiltinType::ULong))
3020+
break;
3021+
Out << "u3u64";
3022+
addSubstitution(BuiltinType::ULong);
3023+
break;
3024+
case 128:
3025+
if (mangleSubstitution(BuiltinType::UInt128))
3026+
break;
3027+
Out << "u4u128";
3028+
addSubstitution(BuiltinType::UInt128);
3029+
break;
3030+
default:
3031+
llvm_unreachable("Unknown integer size for normalization");
3032+
}
3033+
}
3034+
return;
3035+
}
29473036
switch (T->getKind()) {
29483037
case BuiltinType::Void:
29493038
Out << 'v';
@@ -6558,16 +6647,17 @@ void ItaniumMangleContextImpl::mangleCXXRTTI(QualType Ty, raw_ostream &Out) {
65586647
Mangler.mangleType(Ty);
65596648
}
65606649

6561-
void ItaniumMangleContextImpl::mangleCXXRTTIName(QualType Ty,
6562-
raw_ostream &Out) {
6650+
void ItaniumMangleContextImpl::mangleCXXRTTIName(
6651+
QualType Ty, raw_ostream &Out, bool NormalizeIntegers = false) {
65636652
// <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
6564-
CXXNameMangler Mangler(*this, Out);
6653+
CXXNameMangler Mangler(*this, Out, NormalizeIntegers);
65656654
Mangler.getStream() << "_ZTS";
65666655
Mangler.mangleType(Ty);
65676656
}
65686657

6569-
void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) {
6570-
mangleCXXRTTIName(Ty, Out);
6658+
void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out,
6659+
bool NormalizeIntegers = false) {
6660+
mangleCXXRTTIName(Ty, Out, NormalizeIntegers);
65716661
}
65726662

65736663
void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_ostream &) {

clang/lib/AST/MicrosoftMangle.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
180180
int32_t VBPtrOffset, uint32_t VBIndex,
181181
raw_ostream &Out) override;
182182
void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
183-
void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
183+
void mangleCXXRTTIName(QualType T, raw_ostream &Out,
184+
bool NormalizeIntegers) override;
184185
void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
185186
uint32_t NVOffset, int32_t VBPtrOffset,
186187
uint32_t VBTableOffset, uint32_t Flags,
@@ -193,7 +194,8 @@ class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
193194
mangleCXXRTTICompleteObjectLocator(const CXXRecordDecl *Derived,
194195
ArrayRef<const CXXRecordDecl *> BasePath,
195196
raw_ostream &Out) override;
196-
void mangleTypeName(QualType T, raw_ostream &) override;
197+
void mangleTypeName(QualType T, raw_ostream &,
198+
bool NormalizeIntegers) override;
197199
void mangleReferenceTemporary(const VarDecl *, unsigned ManglingNumber,
198200
raw_ostream &) override;
199201
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &Out) override;
@@ -3604,8 +3606,8 @@ void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
36043606
Mangler.getStream() << "@8";
36053607
}
36063608

3607-
void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
3608-
raw_ostream &Out) {
3609+
void MicrosoftMangleContextImpl::mangleCXXRTTIName(
3610+
QualType T, raw_ostream &Out, bool NormalizeIntegers = false) {
36093611
MicrosoftCXXNameMangler Mangler(*this, Out);
36103612
Mangler.getStream() << '.';
36113613
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
@@ -3772,7 +3774,8 @@ void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
37723774
Mangler.mangleName(EnclosingDecl);
37733775
}
37743776

3775-
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
3777+
void MicrosoftMangleContextImpl::mangleTypeName(
3778+
QualType T, raw_ostream &Out, bool NormalizeIntegers = false) {
37763779
// This is just a made up unique string for the purposes of tbaa. undname
37773780
// does *not* know how to demangle it.
37783781
MicrosoftCXXNameMangler Mangler(*this, Out);

clang/lib/CodeGen/CodeGenModule.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,11 @@ llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T) {
18161816

18171817
std::string OutName;
18181818
llvm::raw_string_ostream Out(OutName);
1819-
getCXXABI().getMangleContext().mangleTypeName(T, Out);
1819+
getCXXABI().getMangleContext().mangleTypeName(
1820+
T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers);
1821+
1822+
if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers)
1823+
Out << ".normalized";
18201824

18211825
return llvm::ConstantInt::get(Int32Ty,
18221826
static_cast<uint32_t>(llvm::xxHash64(OutName)));
@@ -7053,7 +7057,12 @@ CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map,
70537057
if (isExternallyVisible(T->getLinkage())) {
70547058
std::string OutName;
70557059
llvm::raw_string_ostream Out(OutName);
7056-
getCXXABI().getMangleContext().mangleTypeName(T, Out);
7060+
getCXXABI().getMangleContext().mangleTypeName(
7061+
T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers);
7062+
7063+
if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers)
7064+
Out << ".normalized";
7065+
70577066
Out << Suffix;
70587067

70597068
InternalId = llvm::MDString::get(getLLVMContext(), Out.str());

clang/lib/Driver/SanitizerArgs.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
712712
CfiICallGeneralizePointers =
713713
Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
714714

715+
CfiICallNormalizeIntegers =
716+
Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
717+
715718
if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
716719
D.Diag(diag::err_drv_argument_not_allowed_with)
717720
<< "-fsanitize-cfi-cross-dso"
@@ -1216,6 +1219,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
12161219
if (CfiICallGeneralizePointers)
12171220
CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
12181221

1222+
if (CfiICallNormalizeIntegers)
1223+
CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1224+
12191225
if (CfiCanonicalJumpTables)
12201226
CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
12211227

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -fsanitize-cfi-icall-experimental-normalize-integers -emit-llvm -o - %s | FileCheck %s
2+
3+
// Test that integer types are normalized for cross-language CFI support with
4+
// other languages that can't represent and encode C/C++ integer types.
5+
6+
void foo0(char arg) { }
7+
// CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}}
8+
void foo1(char arg1, signed char arg2) { }
9+
// CHECK: define{{.*}}foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}}
10+
void foo2(char arg1, signed char arg2, signed char arg3) { }
11+
// CHECK: define{{.*}}foo2{{.*}}!type ![[TYPE2:[0-9]+]] !type !{{[0-9]+}}
12+
void foo3(int arg) { }
13+
// CHECK: define{{.*}}foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}}
14+
void foo4(int arg1, int arg2) { }
15+
// CHECK: define{{.*}}foo4{{.*}}!type ![[TYPE4:[0-9]+]] !type !{{[0-9]+}}
16+
void foo5(int arg1, int arg2, int arg3) { }
17+
// CHECK: define{{.*}}foo5{{.*}}!type ![[TYPE5:[0-9]+]] !type !{{[0-9]+}}
18+
void foo6(long arg) { }
19+
// CHECK: define{{.*}}foo6{{.*}}!type ![[TYPE6:[0-9]+]] !type !{{[0-9]+}}
20+
void foo7(long arg1, long long arg2) { }
21+
// CHECK: define{{.*}}foo7{{.*}}!type ![[TYPE7:[0-9]+]] !type !{{[0-9]+}}
22+
void foo8(long arg1, long long arg2, long long arg3) { }
23+
// CHECK: define{{.*}}foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}}
24+
void foo9(short arg) { }
25+
// CHECK: define{{.*}}foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}}
26+
void foo10(short arg1, short arg2) { }
27+
// CHECK: define{{.*}}foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}}
28+
void foo11(short arg1, short arg2, short arg3) { }
29+
// CHECK: define{{.*}}foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}}
30+
void foo12(unsigned char arg) { }
31+
// CHECK: define{{.*}}foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}}
32+
void foo13(unsigned char arg1, unsigned char arg2) { }
33+
// CHECK: define{{.*}}foo13{{.*}}!type ![[TYPE13:[0-9]+]] !type !{{[0-9]+}}
34+
void foo14(unsigned char arg1, unsigned char arg2, unsigned char arg3) { }
35+
// CHECK: define{{.*}}foo14{{.*}}!type ![[TYPE14:[0-9]+]] !type !{{[0-9]+}}
36+
void foo15(unsigned int arg) { }
37+
// CHECK: define{{.*}}foo15{{.*}}!type ![[TYPE15:[0-9]+]] !type !{{[0-9]+}}
38+
void foo16(unsigned int arg1, unsigned int arg2) { }
39+
// CHECK: define{{.*}}foo16{{.*}}!type ![[TYPE16:[0-9]+]] !type !{{[0-9]+}}
40+
void foo17(unsigned int arg1, unsigned int arg2, unsigned int arg3) { }
41+
// CHECK: define{{.*}}foo17{{.*}}!type ![[TYPE17:[0-9]+]] !type !{{[0-9]+}}
42+
void foo18(unsigned long arg) { }
43+
// CHECK: define{{.*}}foo18{{.*}}!type ![[TYPE18:[0-9]+]] !type !{{[0-9]+}}
44+
void foo19(unsigned long arg1, unsigned long long arg2) { }
45+
// CHECK: define{{.*}}foo19{{.*}}!type ![[TYPE19:[0-9]+]] !type !{{[0-9]+}}
46+
void foo20(unsigned long arg1, unsigned long long arg2, unsigned long long arg3) { }
47+
// CHECK: define{{.*}}foo20{{.*}}!type ![[TYPE20:[0-9]+]] !type !{{[0-9]+}}
48+
void foo21(unsigned short arg) { }
49+
// CHECK: define{{.*}}foo21{{.*}}!type ![[TYPE21:[0-9]+]] !type !{{[0-9]+}}
50+
void foo22(unsigned short arg1, unsigned short arg2) { }
51+
// CHECK: define{{.*}}foo22{{.*}}!type ![[TYPE22:[0-9]+]] !type !{{[0-9]+}}
52+
void foo23(unsigned short arg1, unsigned short arg2, unsigned short arg3) { }
53+
// CHECK: define{{.*}}foo23{{.*}}!type ![[TYPE23:[0-9]+]] !type !{{[0-9]+}}
54+
55+
// CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvu2i8E.normalized"}
56+
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu2i8S_E.normalized"}
57+
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu2i8S_S_E.normalized"}
58+
// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3i32E.normalized"}
59+
// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3i32S_E.normalized"}
60+
// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3i32S_S_E.normalized"}
61+
// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3i64E.normalized"}
62+
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3i64S_E.normalized"}
63+
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3i64S_S_E.normalized"}
64+
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3i16E.normalized"}
65+
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3i16S_E.normalized"}
66+
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3i16S_S_E.normalized"}
67+
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu2u8E.normalized"}
68+
// CHECK: ![[TYPE13]] = !{i64 0, !"_ZTSFvu2u8S_E.normalized"}
69+
// CHECK: ![[TYPE14]] = !{i64 0, !"_ZTSFvu2u8S_S_E.normalized"}
70+
// CHECK: ![[TYPE15]] = !{i64 0, !"_ZTSFvu3u32E.normalized"}
71+
// CHECK: ![[TYPE16]] = !{i64 0, !"_ZTSFvu3u32S_E.normalized"}
72+
// CHECK: ![[TYPE17]] = !{i64 0, !"_ZTSFvu3u32S_S_E.normalized"}
73+
// CHECK: ![[TYPE18]] = !{i64 0, !"_ZTSFvu3u64E.normalized"}
74+
// CHECK: ![[TYPE19]] = !{i64 0, !"_ZTSFvu3u64S_E.normalized"}
75+
// CHECK: ![[TYPE20]] = !{i64 0, !"_ZTSFvu3u64S_S_E.normalized"}
76+
// CHECK: ![[TYPE21]] = !{i64 0, !"_ZTSFvu3u16E.normalized"}
77+
// CHECK: ![[TYPE22]] = !{i64 0, !"_ZTSFvu3u16S_E.normalized"}
78+
// CHECK: ![[TYPE23]] = !{i64 0, !"_ZTSFvu3u16S_S_E.normalized"}

0 commit comments

Comments
 (0)