summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2010-10-24 18:30:18 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2010-10-24 18:30:18 +0000
commita99fdcf93ef8a1f55a5e7da6aca1a72444ac4838 (patch)
tree78c3fc747b82496f5e515f1f6c1374408a396374 /clang/lib
parent800fd3533c2c862c88bcfd86694e2fd9875c461f (diff)
downloadbcm5719-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')
-rw-r--r--clang/lib/AST/ASTContext.cpp48
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)
OpenPOWER on IntegriCloud