[ASTImporter] Fix inequality of functions with different attributes

Summary:
FunctionType::ExtInfo holds such properties of a function which are needed
mostly for code gen. We should not compare these bits when checking for
structural equivalency.
Checking ExtInfo caused false ODR errors during CTU analysis (of tmux).

Reviewers: a_sidorin, a.sidorin, shafik

Subscribers: rnkovacs, dkrupp, Szelethus, cfe-commits

Differential Revision: https://reviews.llvm.org/D53699

llvm-svn: 352050
This commit is contained in:
Gabor Marton 2019-01-24 14:47:44 +00:00
parent 66038ffa13
commit 41f2046642
2 changed files with 53 additions and 1 deletions

View File

@ -296,6 +296,32 @@ static bool IsArrayStructurallyEquivalent(StructuralEquivalenceContext &Context,
return true;
}
/// Determine structural equivalence based on the ExtInfo of functions. This
/// is inspired by ASTContext::mergeFunctionTypes(), we compare calling
/// conventions bits but must not compare some other bits.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
FunctionType::ExtInfo EI1,
FunctionType::ExtInfo EI2) {
// Compatible functions must have compatible calling conventions.
if (EI1.getCC() != EI2.getCC())
return false;
// Regparm is part of the calling convention.
if (EI1.getHasRegParm() != EI2.getHasRegParm())
return false;
if (EI1.getRegParm() != EI2.getRegParm())
return false;
if (EI1.getProducesResult() != EI2.getProducesResult())
return false;
if (EI1.getNoCallerSavedRegs() != EI2.getNoCallerSavedRegs())
return false;
if (EI1.getNoCfCheck() != EI2.getNoCfCheck())
return false;
return true;
}
/// Determine structural equivalence of two types.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
QualType T1, QualType T2) {
@ -539,7 +565,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!IsStructurallyEquivalent(Context, Function1->getReturnType(),
Function2->getReturnType()))
return false;
if (Function1->getExtInfo() != Function2->getExtInfo())
if (!IsStructurallyEquivalent(Context, Function1->getExtInfo(),
Function2->getExtInfo()))
return false;
break;
}

View File

@ -370,6 +370,31 @@ TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {
EXPECT_FALSE(testStructuralMatch(t));
}
TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {
auto t = makeNamedDecls(
"__attribute__((noreturn)) void foo();",
" void foo();",
Lang_C);
EXPECT_TRUE(testStructuralMatch(t));
}
TEST_F(StructuralEquivalenceFunctionTest,
FunctionsWithDifferentCallingConventions) {
auto t = makeNamedDecls(
"__attribute__((fastcall)) void foo();",
"__attribute__((ms_abi)) void foo();",
Lang_C);
EXPECT_FALSE(testStructuralMatch(t));
}
TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {
auto t = makeNamedDecls(
"__attribute__((no_caller_saved_registers)) void foo();",
" void foo();",
Lang_C);
EXPECT_FALSE(testStructuralMatch(t));
}
struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {
};