From e7300e75b51a7e7d4e81975b4be7a6c65f9a8286 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 18 Jan 2023 08:49:45 -0500 Subject: Diagnose extensions in 'offsetof' https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm made very clear that it is an UB having type definitions with in offsetof. Clang supports defining a type as the first argument as a conforming extension due to how many projects use the construct in C99 and earlier to calculate the alignment of a type. GCC also supports defining a type as the first argument. This adds extension warnings and documentation for the functionality Clang explicitly supports. Fixes #57065 Reverts the revert of 39da55e8f548a11f7dadefa73ea73d809a5f1729 Co-authored-by: Yingchi Long Co-authored-by: Aaron Ballman Differential Revision: https://reviews.llvm.org/D133574 --- clang/lib/Sema/SemaDecl.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'clang/lib/Sema/SemaDecl.cpp') diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index af20c707..c94b7ec 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16583,17 +16583,16 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, /// /// \param SkipBody If non-null, will be set to indicate if the caller should /// skip the definition of this tag and treat it as if it were a declaration. -DeclResult Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - const ParsedAttributesView &Attrs, AccessSpecifier AS, - SourceLocation ModulePrivateLoc, - MultiTemplateParamsArg TemplateParameterLists, - bool &OwnedDecl, bool &IsDependent, - SourceLocation ScopedEnumKWLoc, - bool ScopedEnumUsesClassTag, - TypeResult UnderlyingType, bool IsTypeSpecifier, - bool IsTemplateParamOrArg, SkipBodyInfo *SkipBody) { +DeclResult +Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attrs, AccessSpecifier AS, + SourceLocation ModulePrivateLoc, + MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, + bool &IsDependent, SourceLocation ScopedEnumKWLoc, + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, + bool IsTypeSpecifier, bool IsTemplateParamOrArg, + OffsetOfKind OOK, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; assert((Name != nullptr || TUK == TUK_Definition) && @@ -17366,10 +17365,14 @@ CreateNewDecl: cast_or_null(PrevDecl)); } + if (OOK != OOK_Outside && TUK == TUK_Definition && !getLangOpts().CPlusPlus) + Diag(New->getLocation(), diag::ext_type_defined_in_offsetof) + << (OOK == OOK_Macro) << New->getSourceRange(); + // C++11 [dcl.type]p3: // A type-specifier-seq shall not define a class or enumeration [...]. - if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) && - TUK == TUK_Definition) { + if (!Invalid && getLangOpts().CPlusPlus && + (IsTypeSpecifier || IsTemplateParamOrArg) && TUK == TUK_Definition) { Diag(New->getLocation(), diag::err_type_defined_in_type_specifier) << Context.getTagDeclType(New); Invalid = true; -- cgit v1.1