Skip to content

Commit 84955ae

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. Relands b1e9ab7 with fixes. Reviewed By: pcc, samitolvanen Differential Revision: https://reviews.llvm.org/D139395
2 parents 556a958 + 71c7313 commit 84955ae

File tree

13 files changed

+300
-16
lines changed

13 files changed

+300
-16
lines changed

clang/docs/ControlFlowIntegrity.rst

Lines changed: 19 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 4 additions & 2 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,10 @@ def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-g
19751975
Group<f_clang_Group>,
19761976
HelpText<"Generalize pointers in CFI indirect call type signature checks">,
19771977
MarshallingInfoFlag<CodeGenOpts<"SanitizeCfiICallGeneralizePointers">>;
1978+
def fsanitize_cfi_icall_normalize_integers : Flag<["-"], "fsanitize-cfi-icall-experimental-normalize-integers">,
1979+
Group<f_clang_Group>,
1980+
HelpText<"Normalize integers in CFI indirect call type signature checks">,
1981+
MarshallingInfoFlag<CodeGenOpts<"SanitizeCfiICallNormalizeIntegers">>;
19781982
defm sanitize_cfi_canonical_jump_tables : BoolOption<"f", "sanitize-cfi-canonical-jump-tables",
19791983
CodeGenOpts<"SanitizeCfiCanonicalJumpTables">, DefaultFalse,
19801984
PosFlag<SetTrue, [], "Make">, NegFlag<SetFalse, [CoreOption, NoXarchOption], "Do not make">,

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 1 addition & 0 deletions
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

Lines changed: 97 additions & 7 deletions
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), Structor(nullptr), 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';
@@ -6552,16 +6641,17 @@ void ItaniumMangleContextImpl::mangleCXXRTTI(QualType Ty, raw_ostream &Out) {
65526641
Mangler.mangleType(Ty);
65536642
}
65546643

6555-
void ItaniumMangleContextImpl::mangleCXXRTTIName(QualType Ty,
6556-
raw_ostream &Out) {
6644+
void ItaniumMangleContextImpl::mangleCXXRTTIName(
6645+
QualType Ty, raw_ostream &Out, bool NormalizeIntegers = false) {
65576646
// <special-name> ::= TS <type> # typeinfo name (null terminated byte string)
6558-
CXXNameMangler Mangler(*this, Out);
6647+
CXXNameMangler Mangler(*this, Out, NormalizeIntegers);
65596648
Mangler.getStream() << "_ZTS";
65606649
Mangler.mangleType(Ty);
65616650
}
65626651

6563-
void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out) {
6564-
mangleCXXRTTIName(Ty, Out);
6652+
void ItaniumMangleContextImpl::mangleTypeName(QualType Ty, raw_ostream &Out,
6653+
bool NormalizeIntegers = false) {
6654+
mangleCXXRTTIName(Ty, Out, NormalizeIntegers);
65656655
}
65666656

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

clang/lib/AST/MicrosoftMangle.cpp

Lines changed: 8 additions & 5 deletions
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;
@@ -3597,8 +3599,8 @@ void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) {
35973599
Mangler.getStream() << "@8";
35983600
}
35993601

3600-
void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T,
3601-
raw_ostream &Out) {
3602+
void MicrosoftMangleContextImpl::mangleCXXRTTIName(
3603+
QualType T, raw_ostream &Out, bool NormalizeIntegers = false) {
36023604
MicrosoftCXXNameMangler Mangler(*this, Out);
36033605
Mangler.getStream() << '.';
36043606
Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result);
@@ -3765,7 +3767,8 @@ void MicrosoftMangleContextImpl::mangleSEHFinallyBlock(
37653767
Mangler.mangleName(EnclosingDecl);
37663768
}
37673769

3768-
void MicrosoftMangleContextImpl::mangleTypeName(QualType T, raw_ostream &Out) {
3770+
void MicrosoftMangleContextImpl::mangleTypeName(
3771+
QualType T, raw_ostream &Out, bool NormalizeIntegers = false) {
37693772
// This is just a made up unique string for the purposes of tbaa. undname
37703773
// does *not* know how to demangle it.
37713774
MicrosoftCXXNameMangler Mangler(*this, Out);

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,7 +1820,11 @@ llvm::ConstantInt *CodeGenModule::CreateKCFITypeId(QualType T) {
18201820

18211821
std::string OutName;
18221822
llvm::raw_string_ostream Out(OutName);
1823-
getCXXABI().getMangleContext().mangleTypeName(T, Out);
1823+
getCXXABI().getMangleContext().mangleTypeName(
1824+
T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers);
1825+
1826+
if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers)
1827+
Out << ".normalized";
18241828

18251829
return llvm::ConstantInt::get(Int32Ty,
18261830
static_cast<uint32_t>(llvm::xxHash64(OutName)));
@@ -7057,7 +7061,12 @@ CodeGenModule::CreateMetadataIdentifierImpl(QualType T, MetadataTypeMap &Map,
70577061
if (isExternallyVisible(T->getLinkage())) {
70587062
std::string OutName;
70597063
llvm::raw_string_ostream Out(OutName);
7060-
getCXXABI().getMangleContext().mangleTypeName(T, Out);
7064+
getCXXABI().getMangleContext().mangleTypeName(
7065+
T, Out, getCodeGenOpts().SanitizeCfiICallNormalizeIntegers);
7066+
7067+
if (getCodeGenOpts().SanitizeCfiICallNormalizeIntegers)
7068+
Out << ".normalized";
7069+
70617070
Out << Suffix;
70627071

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

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
714714
CfiICallGeneralizePointers =
715715
Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);
716716

717+
CfiICallNormalizeIntegers =
718+
Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);
719+
717720
if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)
718721
D.Diag(diag::err_drv_argument_not_allowed_with)
719722
<< "-fsanitize-cfi-cross-dso"
@@ -1218,6 +1221,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
12181221
if (CfiICallGeneralizePointers)
12191222
CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");
12201223

1224+
if (CfiICallNormalizeIntegers)
1225+
CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");
1226+
12211227
if (CfiCanonicalJumpTables)
12221228
CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
12231229

Lines changed: 78 additions & 0 deletions
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)