53 changes: 24 additions & 29 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16583,16 +16583,17 @@ 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,
OffsetOfKind OOK, SkipBodyInfo *SkipBody) {
Decl *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) {
// If this is not a definition, it must have a name.
IdentifierInfo *OrigName = Name;
assert((Name != nullptr || TUK == TUK_Definition) &&
Expand All @@ -16618,15 +16619,15 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
TUK == TUK_Friend, isMemberSpecialization, Invalid)) {
if (Kind == TTK_Enum) {
Diag(KWLoc, diag::err_enum_template);
return true;
return nullptr;
}

if (TemplateParams->size() > 0) {
// This is a declaration or definition of a class template (which may
// be a member of another template).

if (Invalid)
return true;
return nullptr;

OwnedDecl = false;
DeclResult Result = CheckClassTemplate(
Expand All @@ -16645,7 +16646,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,

if (!TemplateParameterLists.empty() && isMemberSpecialization &&
CheckTemplateDeclScope(S, TemplateParameterLists.back()))
return true;
return nullptr;
}

// Figure out the underlying type if this a enum declaration. We need to do
Expand Down Expand Up @@ -16761,26 +16762,26 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
DC = computeDeclContext(SS, false);
if (!DC) {
IsDependent = true;
return true;
return nullptr;
}
} else {
DC = computeDeclContext(SS, true);
if (!DC) {
Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
<< SS.getRange();
return true;
return nullptr;
}
}

if (RequireCompleteDeclContext(SS, DC))
return true;
return nullptr;

SearchDC = DC;
// Look-up name inside 'foo::'.
LookupQualifiedName(Previous, DC);

if (Previous.isAmbiguous())
return true;
return nullptr;

if (Previous.empty()) {
// Name lookup did not find anything. However, if the
Expand All @@ -16792,7 +16793,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
if (Previous.wasNotFoundInCurrentInstantiation() &&
(TUK == TUK_Reference || TUK == TUK_Friend)) {
IsDependent = true;
return true;
return nullptr;
}

// A tag 'foo::bar' must already exist.
Expand All @@ -16809,7 +16810,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
// -- every member of class T that is itself a type
if (TUK != TUK_Reference && TUK != TUK_Friend &&
DiagnoseClassNameShadow(SearchDC, DeclarationNameInfo(Name, NameLoc)))
return true;
return nullptr;

// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
Expand Down Expand Up @@ -16873,7 +16874,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,

// Note: there used to be some attempt at recovery here.
if (Previous.isAmbiguous())
return true;
return nullptr;

if (!getLangOpts().CPlusPlus && TUK != TUK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
Expand Down Expand Up @@ -17365,16 +17366,10 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
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();
Invalid = true;
}

// C++11 [dcl.type]p3:
// A type-specifier-seq shall not define a class or enumeration [...].
if (!Invalid && getLangOpts().CPlusPlus &&
(IsTypeSpecifier || IsTemplateParamOrArg) && TUK == TUK_Definition) {
if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
TUK == TUK_Definition) {
Diag(New->getLocation(), diag::err_type_defined_in_type_specifier)
<< Context.getTagDeclType(New);
Invalid = true;
Expand Down Expand Up @@ -17530,7 +17525,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
if (New->isBeingDefined())
if (auto RD = dyn_cast<RecordDecl>(New))
RD->completeDefinition();
return true;
return nullptr;
} else if (SkipBody && SkipBody->ShouldSkip) {
return SkipBody->Previous;
} else {
Expand Down
22 changes: 12 additions & 10 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16922,10 +16922,12 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,

/// Handle a friend tag declaration where the scope specifier was
/// templated.
DeclResult Sema::ActOnTemplatedFriendTag(
Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc,
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists) {
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
CXXScopeSpec &SS, IdentifierInfo *Name,
SourceLocation NameLoc,
const ParsedAttributesView &Attr,
MultiTemplateParamsArg TempParamLists) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);

bool IsMemberSpecialization = false;
Expand All @@ -16938,7 +16940,7 @@ DeclResult Sema::ActOnTemplatedFriendTag(
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
return true;
return nullptr;

return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name,
NameLoc, Attr, TemplateParams, AS_public,
Expand All @@ -16953,7 +16955,7 @@ DeclResult Sema::ActOnTemplatedFriendTag(
}
}

if (Invalid) return true;
if (Invalid) return nullptr;

bool isAllExplicitSpecializations = true;
for (unsigned I = TempParamLists.size(); I-- > 0; ) {
Expand All @@ -16972,15 +16974,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, /*OOK=*/OOK_Outside);
/*IsTemplateParamOrArg=*/false);
}

NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
Expand All @@ -16989,7 +16991,7 @@ DeclResult Sema::ActOnTemplatedFriendTag(
QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
*Name, NameLoc);
if (T.isNull())
return true;
return nullptr;

TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
Expand Down
13 changes: 7 additions & 6 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10181,12 +10181,13 @@ 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, /*OOK=*/OOK_Outside).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);
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");

if (!TagD)
Expand Down
74 changes: 0 additions & 74 deletions clang/test/C/C2x/n2350.c

This file was deleted.

14 changes: 7 additions & 7 deletions clang/test/C/drs/dr4xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,12 @@ void dr496(void) {
* because it references an array of another struct. Clang calculates the
* correct offset to each of those fields.
*/
_Static_assert(__builtin_offsetof(struct B, a.n) == 0, ""); /* expected-warning {{using a member access expression within '__builtin_offsetof' is a Clang extension}} */
_Static_assert(__builtin_offsetof(struct B, a.n) == 0, "");
/* First int below is for 'n' and the second int is for 'a[0]'; this presumes
* there is no padding involved.
*/
_Static_assert(__builtin_offsetof(struct B, a.a[1]) == sizeof(int) + sizeof(int), ""); /* expected-warning {{using a member access expression within '__builtin_offsetof' is a Clang extension}}
expected-warning {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
*/
_Static_assert(__builtin_offsetof(struct B, a.a[1]) == sizeof(int) + sizeof(int), "");

/* However, we do not support using the -> operator to access a member, even
* if that would be a valid expression. FIXME: GCC accepts this, perhaps we
* should as well.
Expand All @@ -353,10 +352,11 @@ void dr496(void) {
*/

/* The DR asked a question about whether defining a new type within offsetof
* is allowed. C2x N2350 made this explicitly undefined behavior, but GCC and
* Clang both support it as an extension.
* is allowed. C2x N2350 made this explicitly undefined behavior, but Clang
* has always supported defining a type in this location, and GCC also
* supports it.
*/
(void)__builtin_offsetof(struct S { int a; }, a); /* expected-warning{{defining a type within '__builtin_offsetof' is a Clang extension}} */
(void)__builtin_offsetof(struct S { int a; }, a);
}

/* WG14 DR499: yes
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CXX/drs/dr4xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,9 +687,9 @@ namespace dr447 { // dr447: yes
U<__builtin_offsetof(A, n)>::type a;
U<__builtin_offsetof(T, n)>::type b; // expected-error +{{}} expected-warning 0+{{}}
// as an extension, we allow the member-designator to include array indices
g(__builtin_offsetof(A, a[0])).h<int>(); // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
g(__builtin_offsetof(A, a[N])).h<int>(); // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
U<__builtin_offsetof(A, a[0])>::type c; // expected-error {{using an array subscript expression within '__builtin_offsetof' is a Clang extension}}
g(__builtin_offsetof(A, a[0])).h<int>();
g(__builtin_offsetof(A, a[N])).h<int>();
U<__builtin_offsetof(A, a[0])>::type c;
U<__builtin_offsetof(A, a[N])>::type d; // expected-error +{{}} expected-warning 0+{{}}
}
}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Parser/cxx-undeclared-identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ namespace ImplicitInt {
// PR7180
int f(a::b::c); // expected-error {{use of undeclared identifier 'a'}}

class Foo::Bar { // expected-error {{use of undeclared identifier 'Foo'}}
// expected-error {{expected unqualified-id}}
class Foo::Bar { // expected-error {{use of undeclared identifier 'Foo'}} \
// expected-error {{expected ';' after class}}
4 changes: 4 additions & 0 deletions clang/test/Parser/declarators.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ struct test9 {
struct test10 { int a; } static test10x;
struct test11 { int a; } const test11x;

// PR6216
void test12(void) {
(void)__builtin_offsetof(struct { char c; int i; }, i);
}

// rdar://7608537
struct test13 { int a; } (test13x);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Parser/recovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,6 @@ struct ::, struct ::; // expected-error 2 {{expected identifier}} expected-error
enum ::, enum ::; // expected-error 2 {{expected identifier}}
struct ::__super, struct ::__super; // expected-error 2 {{expected identifier}} expected-error 2 {{expected '::' after '__super'}}
struct ::template foo, struct ::template bar; // expected-error 2 {{expected identifier}} expected-error 2 {{declaration of anonymous struct must be a definition}} expected-warning {{declaration does not declare anything}}
struct ::foo struct::; // expected-error {{no struct named 'foo' in the global namespace}} expected-error {{expected identifier}}
struct ::foo struct::; // expected-error {{no struct named 'foo' in the global namespace}} expected-error {{expected identifier}} expected-error {{declaration of anonymous struct must be a definition}}
class :: : {} a; // expected-error {{expected identifier}} expected-error {{expected class name}}
}
5 changes: 3 additions & 2 deletions clang/test/SemaCXX/invalid-template-params.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ class C0 {
public:
template<typename T0, typename T1 = T0 // missing closing angle bracket
struct S0 {}; // expected-error {{'S0' cannot be defined in a type specifier}}
// expected-error@-1 {{expected ',' or '>' in template-parameter-list}}
// expected-error@-2 {{declaration does not declare anything}}
// expected-error@-1 {{cannot combine with previous 'type-name' declaration specifier}}
// expected-error@-2 {{expected ',' or '>' in template-parameter-list}}
// expected-error@-3 {{declaration does not declare anything}}
C0() : m(new S0<int>) {} // expected-error {{expected '(' for function-style cast or type construction}}
// expected-error@-1 {{expected expression}}
S0<int> *m; // expected-error {{expected member name or ';' after declaration specifiers}}
Expand Down
15 changes: 0 additions & 15 deletions clang/test/SemaCXX/offsetof.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,3 @@ struct Derived : virtual Base {
expected-error {{invalid application of 'offsetof' to a field of a virtual base}}
};
}

int test_definition(void) {
return __builtin_offsetof(struct A // expected-error {{'A' cannot be defined in a type specifier}}
{
int a;
struct B // FIXME: error diagnostic message for nested definitions
// https://reviews.llvm.org/D133574
// fixme-error{{'A' cannot be defined in '__builtin_offsetof'}}
{
int c;
int d;
};
B x;
}, a);
}
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/rdar42746401.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ template <int>
class b;
class c; // expected-note{{forward declaration}}

::b<0> struct c::d // expected-error{{incomplete type}} expected-error{{expected unqualified-id}}
::b<0> struct c::d // expected-error{{incomplete type}} expected-error{{cannot combine}} expected-error{{expected unqualified-id}}