diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2023-01-18 08:49:45 -0500 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2023-01-18 08:51:21 -0500 |
commit | e7300e75b51a7e7d4e81975b4be7a6c65f9a8286 (patch) | |
tree | de4e2e3f1ceaca35ae0e37c4417c66b97d9af7d6 /clang/lib/Sema | |
parent | 63ba34f3fb752e0a60a78c21ee694e1064a870ab (diff) | |
download | llvm-e7300e75b51a7e7d4e81975b4be7a6c65f9a8286.zip llvm-e7300e75b51a7e7d4e81975b4be7a6c65f9a8286.tar.gz llvm-e7300e75b51a7e7d4e81975b4be7a6c65f9a8286.tar.bz2 |
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 <i@lyc.dev>
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Differential Revision: https://reviews.llvm.org/D133574
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 29 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 12 |
3 files changed, 24 insertions, 23 deletions
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<RecordDecl>(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; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e7dddc3..c8d384c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -16972,15 +16972,15 @@ DeclResult Sema::ActOnTemplatedFriendTag( if (SS.isEmpty()) { bool Owned = false; bool IsDependent = false; - return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, - Attr, AS_public, + return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr, + AS_public, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, IsDependent, /*ScopedEnumKWLoc=*/SourceLocation(), /*ScopedEnumUsesClassTag=*/false, /*UnderlyingType=*/TypeResult(), /*IsTypeSpecifier=*/false, - /*IsTemplateParamOrArg=*/false); + /*IsTemplateParamOrArg=*/false, /*OOK=*/OOK_Outside); } NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6b49c3f..b40bd09 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10181,13 +10181,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, bool Owned = false; bool IsDependent = false; - Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, - KWLoc, SS, Name, NameLoc, Attr, AS_none, - /*ModulePrivateLoc=*/SourceLocation(), - MultiTemplateParamsArg(), Owned, IsDependent, - SourceLocation(), false, TypeResult(), - /*IsTypeSpecifier*/false, - /*IsTemplateParamOrArg*/false).get(); + Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, + NameLoc, Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), + MultiTemplateParamsArg(), Owned, IsDependent, SourceLocation(), + false, TypeResult(), /*IsTypeSpecifier*/ false, + /*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside).get(); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); if (!TagD) |