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 | a99fdcf93ef8a1f55a5e7da6aca1a72444ac4838 (patch) | |
| tree | 78c3fc747b82496f5e515f1f6c1374408a396374 /clang/lib/AST/ASTContext.cpp | |
| parent | 800fd3533c2c862c88bcfd86694e2fd9875c461f (diff) | |
| download | bcm5719-llvm-a99fdcf93ef8a1f55a5e7da6aca1a72444ac4838.tar.gz bcm5719-llvm-a99fdcf93ef8a1f55a5e7da6aca1a72444ac4838.zip | |
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
llvm-svn: 117243
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 313c2ea96b6..10f875b1b76 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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) |

