//=== unittests/CodeGen/TBAAMetadataTest.cpp - Checks metadata generation -===// // // 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 // //===----------------------------------------------------------------------===// #include "IRMatchers.h" #include "TestCompiler.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/IR/Constants.h" #include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" #include using namespace llvm; namespace { struct TBAATestCompiler : public TestCompiler { TBAATestCompiler(clang::LangOptions LO, clang::CodeGenOptions CGO) : TestCompiler(LO, CGO) {} static clang::CodeGenOptions getCommonCodeGenOpts() { clang::CodeGenOptions CGOpts; CGOpts.StructPathTBAA = 1; CGOpts.OptimizationLevel = 1; return CGOpts; } }; auto OmnipotentCharC = MMTuple( MMString("omnipotent char"), MMTuple( MMString("Simple C/C++ TBAA")), MConstInt(0, 64) ); auto OmnipotentCharCXX = MMTuple( MMString("omnipotent char"), MMTuple( MMString("Simple C++ TBAA")), MConstInt(0, 64) ); TEST(TBAAMetadataTest, BasicTypes) { const char TestProgram[] = R"**( void func(char *CP, short *SP, int *IP, long long *LP, void **VPP, int **IPP) { *CP = 4; *SP = 11; *IP = 601; *LP = 604; *VPP = CP; *IPP = IP; } )**"; clang::LangOptions LO; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(4, 8), MMTuple( OmnipotentCharC, MSameAs(0), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(11, 16), MMTuple( MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MSameAs(0), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(601, 32), MMTuple( MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MSameAs(0), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(604, 64), MMTuple( MMTuple( MMString("long long"), OmnipotentCharC, MConstInt(0)), MSameAs(0), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MValType(Type::getInt8PtrTy(Compiler.Context)), MMTuple( MMTuple( MMString("any pointer"), OmnipotentCharC, MConstInt(0)), MSameAs(0), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MValType(Type::getInt32PtrTy(Compiler.Context)), MMTuple( MMTuple( MMString("any pointer"), OmnipotentCharC, MConstInt(0)), MSameAs(0), MConstInt(0)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, CFields) { const char TestProgram[] = R"**( struct ABC { short f16; int f32; long long f64; unsigned short f16_2; unsigned f32_2; unsigned long long f64_2; }; void func(struct ABC *A) { A->f32 = 4; A->f16 = 11; A->f64 = 601; A->f16_2 = 22; A->f32_2 = 77; A->f64_2 = 604; } )**"; clang::LangOptions LO; LO.C11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto StructABC = MMTuple( MMString("ABC"), MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4), MMTuple( MMString("long long"), OmnipotentCharC, MConstInt(0)), MConstInt(8), MSameAs(1), MConstInt(16), MSameAs(3), MConstInt(20), MSameAs(5), MConstInt(24)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(4, 32), MMTuple( StructABC, MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(11, 16), MMTuple( StructABC, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(601, 64), MMTuple( StructABC, MMTuple( MMString("long long"), OmnipotentCharC, MConstInt(0)), MConstInt(8)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(22, 16), MMTuple( StructABC, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(16)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(77, 32), MMTuple( StructABC, MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(20)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(604, 64), MMTuple( StructABC, MMTuple( MMString("long long"), OmnipotentCharC, MConstInt(0)), MConstInt(24)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, CTypedefFields) { const char TestProgram[] = R"**( typedef struct { short f16; int f32; } ABC; typedef struct { short value_f16; int value_f32; } CDE; void func(ABC *A, CDE *B) { A->f32 = 4; A->f16 = 11; B->value_f32 = 44; B->value_f16 = 111; } )**"; clang::LangOptions LO; LO.C11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto NamelessStruct = MMTuple( MMString(""), MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)); const Metadata *MetaABC = nullptr; const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(4, 32), MMTuple( MMSave(MetaABC, NamelessStruct), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(11, 16), MMTuple( NamelessStruct, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); const Metadata *MetaCDE = nullptr; I = matchNext(I, MInstruction(Instruction::Store, MConstInt(44, 32), MMTuple( MMSave(MetaCDE, NamelessStruct), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(111, 16), MMTuple( NamelessStruct, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are // different structures and must be described by different descriptors. //ASSERT_TRUE(MetaABC != MetaCDE); } TEST(TBAAMetadataTest, CTypedefFields2) { const char TestProgram[] = R"**( typedef struct { short f16; int f32; } ABC; typedef struct { short f16; int f32; } CDE; void func(ABC *A, CDE *B) { A->f32 = 4; A->f16 = 11; B->f32 = 44; B->f16 = 111; } )**"; clang::LangOptions LO; LO.C11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto NamelessStruct = MMTuple( MMString(""), MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)); const Metadata *MetaABC = nullptr; const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(4, 32), MMTuple( MMSave(MetaABC, NamelessStruct), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(11, 16), MMTuple( NamelessStruct, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); const Metadata *MetaCDE = nullptr; I = matchNext(I, MInstruction(Instruction::Store, MConstInt(44, 32), MMTuple( MMSave(MetaCDE, NamelessStruct), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(111, 16), MMTuple( NamelessStruct, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are // different structures, although they have the same field sequence. They must // be described by different descriptors. //ASSERT_TRUE(MetaABC != MetaCDE); } TEST(TBAAMetadataTest, CTypedefFields3) { const char TestProgram[] = R"**( typedef struct { short f16; int f32; } ABC; typedef struct { int f32; short f16; } CDE; void func(ABC *A, CDE *B) { A->f32 = 4; A->f16 = 11; B->f32 = 44; B->f16 = 111; } )**"; clang::LangOptions LO; LO.C11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto NamelessStruct1 = MMTuple( MMString(""), MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)); auto NamelessStruct2 = MMTuple( MMString(""), MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(0), MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(4)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(4, 32), MMTuple( NamelessStruct1, MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(11, 16), MMTuple( NamelessStruct1, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(44, 32), MMTuple( NamelessStruct2, MMTuple( MMString("int"), OmnipotentCharC, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(111, 16), MMTuple( NamelessStruct2, MMTuple( MMString("short"), OmnipotentCharC, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, CXXFields) { const char TestProgram[] = R"**( struct ABC { short f16; int f32; long long f64; unsigned short f16_2; unsigned f32_2; unsigned long long f64_2; }; void func(struct ABC *A) { A->f32 = 4; A->f16 = 11; A->f64 = 601; A->f16_2 = 22; A->f32_2 = 77; A->f64_2 = 604; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto StructABC = MMTuple( MMString("_ZTS3ABC"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4), MMTuple( MMString("long long"), OmnipotentCharCXX, MConstInt(0)), MConstInt(8), MSameAs(1), MConstInt(16), MSameAs(3), MConstInt(20), MSameAs(5), MConstInt(24)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(4, 32), MMTuple( StructABC, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(11, 16), MMTuple( StructABC, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(601, 64), MMTuple( StructABC, MMTuple( MMString("long long"), OmnipotentCharCXX, MConstInt(0)), MConstInt(8)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(22, 16), MMTuple( StructABC, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(16)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(77, 32), MMTuple( StructABC, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(20)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(604, 64), MMTuple( StructABC, MMTuple( MMString("long long"), OmnipotentCharCXX, MConstInt(0)), MConstInt(24)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, CXXTypedefFields) { const char TestProgram[] = R"**( typedef struct { short f16; int f32; } ABC; typedef struct { short value_f16; int value_f32; } CDE; void func(ABC *A, CDE *B) { A->f32 = 4; A->f16 = 11; B->value_f32 = 44; B->value_f16 = 111; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto StructABC = MMTuple( MMString("_ZTS3ABC"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)); auto StructCDE = MMTuple( MMString("_ZTS3CDE"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(4, 32), MMTuple( StructABC, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(11, 16), MMTuple( StructABC, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(44, 32), MMTuple( StructCDE, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(111, 16), MMTuple( StructCDE, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, StructureFields) { const char TestProgram[] = R"**( struct Inner { int f32; }; struct Outer { short f16; Inner b1; Inner b2; }; void func(Outer *S) { S->f16 = 14; S->b1.f32 = 35; S->b2.f32 = 77; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto StructInner = MMTuple( MMString("_ZTS5Inner"), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)); auto StructOuter = MMTuple( MMString("_ZTS5Outer"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0), StructInner, MConstInt(4), MSameAs(3), MConstInt(8)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(14, 16), MMTuple( StructOuter, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(35, 32), MMTuple( StructOuter, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(77, 32), MMTuple( StructOuter, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(8)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, ArrayFields) { const char TestProgram[] = R"**( struct Inner { int f32; }; struct Outer { short f16; Inner b1[2]; }; void func(Outer *S) { S->f16 = 14; S->b1[0].f32 = 35; S->b1[1].f32 = 77; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto StructInner = MMTuple( MMString("_ZTS5Inner"), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)); auto StructOuter = MMTuple( MMString("_ZTS5Outer"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0), OmnipotentCharCXX, // FIXME: Info about array field is lost. MConstInt(4)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(14, 16), MMTuple( StructOuter, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(35, 32), MMTuple( StructInner, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(77, 32), MMTuple( StructInner, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, BaseClass) { const char TestProgram[] = R"**( struct Base { int f32; }; struct Derived : public Base { short f16; }; void func(Base *B, Derived *D) { B->f32 = 14; D->f16 = 35; D->f32 = 77; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto ClassBase = MMTuple( MMString("_ZTS4Base"), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)); auto ClassDerived = MMTuple( MMString("_ZTS7Derived"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(14, 32), MMTuple( ClassBase, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(35, 16), MMTuple( ClassDerived, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(77, 32), MMTuple( ClassBase, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, PolymorphicClass) { const char TestProgram[] = R"**( struct Base { virtual void m1(int *) = 0; int f32; }; struct Derived : public Base { virtual void m1(int *) override; short f16; }; void func(Base *B, Derived *D) { B->f32 = 14; D->f16 = 35; D->f32 = 77; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto ClassBase = MMTuple( MMString("_ZTS4Base"), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(Compiler.PtrSize)); auto ClassDerived = MMTuple( MMString("_ZTS7Derived"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(Compiler.PtrSize + 4)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(14, 32), MMTuple( ClassBase, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(Compiler.PtrSize)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(35, 16), MMTuple( ClassDerived, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(Compiler.PtrSize + 4)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(77, 32), MMTuple( ClassBase, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(Compiler.PtrSize)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, VirtualBase) { const char TestProgram[] = R"**( struct Base { int f32; }; struct Derived : public virtual Base { short f16; }; void func(Base *B, Derived *D) { B->f32 = 14; D->f16 = 35; D->f32 = 77; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto ClassBase = MMTuple( MMString("_ZTS4Base"), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)); auto ClassDerived = MMTuple( MMString("_ZTS7Derived"), MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(Compiler.PtrSize)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MConstInt(14, 32), MMTuple( ClassBase, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(35, 16), MMTuple( ClassDerived, MMTuple( MMString("short"), OmnipotentCharCXX, MConstInt(0)), MConstInt(Compiler.PtrSize)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Load, MMTuple( MMTuple( MMString("vtable pointer"), MMTuple( MMString("Simple C++ TBAA")), MConstInt(0)), MSameAs(0), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(77, 32), MMTuple( ClassBase, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); } TEST(TBAAMetadataTest, TemplSpec) { const char TestProgram[] = R"**( template struct ABC { T1 f1; T2 f2; }; void func(ABC *p) { p->f1 = 12.1; p->f2 = 44; } )**"; clang::LangOptions LO; LO.CPlusPlus = 1; LO.CPlusPlus11 = 1; TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); Compiler.init(TestProgram); const BasicBlock *BB = Compiler.compile(); auto SpecABC = MMTuple( MMString("_ZTS3ABCIdiE"), MMTuple( MMString("double"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0), MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(8)); const Instruction *I = match(BB, MInstruction(Instruction::Store, MValType(MType([](const Type &T)->bool { return T.isDoubleTy(); })), MMTuple( SpecABC, MMTuple( MMString("double"), OmnipotentCharCXX, MConstInt(0)), MConstInt(0)))); ASSERT_TRUE(I); I = matchNext(I, MInstruction(Instruction::Store, MConstInt(44, 32), MMTuple( SpecABC, MMTuple( MMString("int"), OmnipotentCharCXX, MConstInt(0)), MConstInt(8)))); ASSERT_TRUE(I); } }