From: Eli Friedman Date: Tue, 2 Sep 2008 05:19:23 +0000 (+0000) Subject: An extremely hacky version of transparent_union support; it isn't X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bc88745b43f440341e60ed93b0d27bac7c418029;p=clang An extremely hacky version of transparent_union support; it isn't anywhere near correct in terms of missing cases and missing diagnostics, but it's good enough to handle the uses in the Linux system headers, which are currently a constant pain for compiling applications on Linux. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55621 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 95d2112650..9c90306177 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -694,6 +694,9 @@ DIAG(err_attr_wrong_decl, ERROR, "'%0' attribute invalid on this declaration, requires typedef or value") DIAG(warn_attribute_nonnull_no_pointers, WARNING, "'nonnull' attribute applied to function with no pointer arguments") +DIAG(warn_transparent_union_nonpointer, WARNING, + "'transparent_union' attribute support incomplete; only supported for" + "pointer unions") // Clang-Specific Attributes DIAG(err_attribute_iboutlet_non_ivar, ERROR, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index eb9888e9a2..b5737d8b3c 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -725,19 +725,34 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, return; } - TypeDecl *decl = dyn_cast(d); - - if (!decl || !S.Context.getTypeDeclType(decl)->isUnionType()) { + // FIXME: This shouldn't be restricted to typedefs + TypedefDecl *TD = dyn_cast(d); + if (!TD || !TD->getUnderlyingType()->isUnionType()) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type, "transparent_union", "union"); return; } - //QualType QTy = Context.getTypeDeclType(decl); - //const RecordType *Ty = QTy->getAsUnionType(); + RecordDecl* RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); + + // FIXME: Should we do a check for RD->isDefinition()? + + // FIXME: This isn't supposed to be restricted to pointers, but otherwise + // we might silently generate incorrect code; see following code + for (int i = 0; i < RD->getNumMembers(); i++) { + if (!RD->getMember(i)->getType()->isPointerType()) { + S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer); + return; + } + } -// FIXME -// Ty->addAttr(new TransparentUnionAttr()); + // FIXME: This is a complete hack; we should be properly propagating + // transparent_union through Sema. That said, this is close enough to + // correctly compile all the common cases of transparent_union without + // errors or warnings + QualType NewTy = S.Context.VoidPtrTy; + NewTy.addConst(); + TD->setUnderlyingType(NewTy); } static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { diff --git a/test/Sema/transparent-union-pointer.c b/test/Sema/transparent-union-pointer.c new file mode 100644 index 0000000000..58597b1809 --- /dev/null +++ b/test/Sema/transparent-union-pointer.c @@ -0,0 +1,14 @@ +// RUN: clang %s -fsyntax-only -verify + +typedef union { + union wait *__uptr; + int *__iptr; +} __WAIT_STATUS __attribute__ ((__transparent_union__)); + +extern int wait (__WAIT_STATUS __stat_loc); + +void fastcgi_cleanup() { + int status = 0; + wait(&status); +} +