diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2010-10-24 18:30:18 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2010-10-24 18:30:18 +0000 |
commit | 4846675e0e42d1802b0ffd8972a45e72aeb3758d (patch) | |
tree | d90c53930baf9fd0f2b31f2cf0ce8d564babb767 /lib/AST/ASTContext.cpp | |
parent | b6cc0e1a789c3f33e3f4b1ee768e679a9beab941 (diff) |
Implement GNU C extension: two types are compatible if they appear
as a function argument, one of the types is a transparent union type
and the other type is compatible with a union member
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117243 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 313c2ea96b..10f875b1b7 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4674,6 +4674,49 @@ bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) { return !mergeTypes(LHS, RHS, true).isNull(); } +/// mergeTransparentUnionType - if T is a transparent union type and a member +/// of T is compatible with SubType, return the merged type, else return +/// QualType() +QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, + bool OfBlockPointer, + bool Unqualified) { + if (const RecordType *UT = T->getAsUnionType()) { + RecordDecl *UD = UT->getDecl(); + if (UD->hasAttr<TransparentUnionAttr>()) { + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); it != itend; ++it) { + QualType ET = it->getType(); + QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified); + if (!MT.isNull()) + return MT; + } + } + } + + return QualType(); +} + +/// mergeFunctionArgumentTypes - merge two types which appear as function +/// argument types +QualType ASTContext::mergeFunctionArgumentTypes(QualType lhs, QualType rhs, + bool OfBlockPointer, + bool Unqualified) { + // GNU extension: two types are compatible if they appear as a function + // argument, one of the types is a transparent union type and the other + // type is compatible with a union member + QualType lmerge = mergeTransparentUnionType(lhs, rhs, OfBlockPointer, + Unqualified); + if (!lmerge.isNull()) + return lmerge; + + QualType rmerge = mergeTransparentUnionType(rhs, lhs, OfBlockPointer, + Unqualified); + if (!rmerge.isNull()) + return rmerge; + + return mergeTypes(lhs, rhs, OfBlockPointer, Unqualified); +} + QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, bool OfBlockPointer, bool Unqualified) { @@ -4751,8 +4794,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, for (unsigned i = 0; i < lproto_nargs; i++) { QualType largtype = lproto->getArgType(i).getUnqualifiedType(); QualType rargtype = rproto->getArgType(i).getUnqualifiedType(); - QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer, - Unqualified); + QualType argtype = mergeFunctionArgumentTypes(largtype, rargtype, + OfBlockPointer, + Unqualified); if (argtype.isNull()) return QualType(); if (Unqualified) |